Skip to content

Commit 7a5b467

Browse files
committed
Merge patch series "allow to create pidfds for reaped tasks with SCM_PIDFD"
This is a logical continuation of the earlier work to create pidfds for reaped tasks through the SO_PEERPIDFD socket option merged in 923ea4d ("Merge patch series "net, pidfs: enable handing out pidfds for reaped sk->sk_peer_pid""). * patches from https://lore.kernel.org/[email protected]: selftests: net: extend SCM_PIDFD test to cover stale pidfds af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD af_unix: stash pidfs dentry when needed af_unix/scm: fix whitespace errors af_unix: introduce and use scm_replace_pid() helper af_unix: introduce unix_skb_to_scm helper af_unix: rework unix_maybe_add_creds() to allow sleep Link: https://lore.kernel.org/[email protected] Signed-off-by: Christian Brauner <[email protected]>
2 parents 8676730 + 861bdc6 commit 7a5b467

File tree

4 files changed

+247
-63
lines changed

4 files changed

+247
-63
lines changed

include/net/scm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
6969
static __inline__ void scm_set_cred(struct scm_cookie *scm,
7070
struct pid *pid, kuid_t uid, kgid_t gid)
7171
{
72-
scm->pid = get_pid(pid);
72+
scm->pid = get_pid(pid);
7373
scm->creds.pid = pid_vnr(pid);
7474
scm->creds.uid = uid;
7575
scm->creds.gid = gid;
@@ -78,7 +78,7 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
7878
static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
7979
{
8080
put_pid(scm->pid);
81-
scm->pid = NULL;
81+
scm->pid = NULL;
8282
}
8383

8484
static __inline__ void scm_destroy(struct scm_cookie *scm)

net/core/scm.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <linux/security.h>
2424
#include <linux/pid_namespace.h>
2525
#include <linux/pid.h>
26+
#include <uapi/linux/pidfd.h>
27+
#include <linux/pidfs.h>
2628
#include <linux/nsproxy.h>
2729
#include <linux/slab.h>
2830
#include <linux/errqueue.h>
@@ -145,6 +147,22 @@ void __scm_destroy(struct scm_cookie *scm)
145147
}
146148
EXPORT_SYMBOL(__scm_destroy);
147149

150+
static inline int scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
151+
{
152+
int err;
153+
154+
/* drop all previous references */
155+
scm_destroy_cred(scm);
156+
157+
err = pidfs_register_pid(pid);
158+
if (unlikely(err))
159+
return err;
160+
161+
scm->pid = pid;
162+
scm->creds.pid = pid_vnr(pid);
163+
return 0;
164+
}
165+
148166
int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
149167
{
150168
const struct proto_ops *ops = READ_ONCE(sock->ops);
@@ -189,15 +207,21 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
189207
if (err)
190208
goto error;
191209

192-
p->creds.pid = creds.pid;
193210
if (!p->pid || pid_vnr(p->pid) != creds.pid) {
194211
struct pid *pid;
195212
err = -ESRCH;
196213
pid = find_get_pid(creds.pid);
197214
if (!pid)
198215
goto error;
199-
put_pid(p->pid);
200-
p->pid = pid;
216+
217+
/* pass a struct pid reference from
218+
* find_get_pid() to scm_replace_pid().
219+
*/
220+
err = scm_replace_pid(p, pid);
221+
if (err) {
222+
put_pid(pid);
223+
goto error;
224+
}
201225
}
202226

203227
err = -EINVAL;
@@ -459,7 +483,7 @@ static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
459483
if (!scm->pid)
460484
return;
461485

462-
pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
486+
pidfd = pidfd_prepare(scm->pid, PIDFD_STALE, &pidfd_file);
463487

464488
if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
465489
if (pidfd_file) {

net/unix/af_unix.c

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ static void unix_destruct_scm(struct sk_buff *skb)
19291929
struct scm_cookie scm;
19301930

19311931
memset(&scm, 0, sizeof(scm));
1932-
scm.pid = UNIXCB(skb).pid;
1932+
scm.pid = UNIXCB(skb).pid;
19331933
if (UNIXCB(skb).fp)
19341934
unix_detach_fds(&scm, skb);
19351935

@@ -1955,21 +1955,45 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
19551955
return err;
19561956
}
19571957

1958-
/*
1958+
static void unix_skb_to_scm(struct sk_buff *skb, struct scm_cookie *scm)
1959+
{
1960+
scm_set_cred(scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
1961+
unix_set_secdata(scm, skb);
1962+
}
1963+
1964+
/**
1965+
* unix_maybe_add_creds() - Adds current task uid/gid and struct pid to skb if needed.
1966+
* @skb: skb to attach creds to.
1967+
* @sk: Sender sock.
1968+
* @other: Receiver sock.
1969+
*
19591970
* Some apps rely on write() giving SCM_CREDENTIALS
19601971
* We include credentials if source or destination socket
19611972
* asserted SOCK_PASSCRED.
1973+
*
1974+
* Context: May sleep.
1975+
* Return: On success zero, on error a negative error code is returned.
19621976
*/
1963-
static void unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
1964-
const struct sock *other)
1977+
static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
1978+
const struct sock *other)
19651979
{
19661980
if (UNIXCB(skb).pid)
1967-
return;
1981+
return 0;
19681982

19691983
if (unix_may_passcred(sk) || unix_may_passcred(other)) {
1970-
UNIXCB(skb).pid = get_pid(task_tgid(current));
1984+
struct pid *pid;
1985+
int err;
1986+
1987+
pid = task_tgid(current);
1988+
err = pidfs_register_pid(pid);
1989+
if (unlikely(err))
1990+
return err;
1991+
1992+
UNIXCB(skb).pid = get_pid(pid);
19711993
current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
19721994
}
1995+
1996+
return 0;
19731997
}
19741998

19751999
static bool unix_skb_scm_eq(struct sk_buff *skb,
@@ -2104,6 +2128,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
21042128
goto out_sock_put;
21052129
}
21062130

2131+
err = unix_maybe_add_creds(skb, sk, other);
2132+
if (err)
2133+
goto out_sock_put;
2134+
21072135
restart:
21082136
sk_locked = 0;
21092137
unix_state_lock(other);
@@ -2212,7 +2240,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
22122240
if (sock_flag(other, SOCK_RCVTSTAMP))
22132241
__net_timestamp(skb);
22142242

2215-
unix_maybe_add_creds(skb, sk, other);
22162243
scm_stat_add(other, skb);
22172244
skb_queue_tail(&other->sk_receive_queue, skb);
22182245
unix_state_unlock(other);
@@ -2256,6 +2283,10 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
22562283
if (err < 0)
22572284
goto out;
22582285

2286+
err = unix_maybe_add_creds(skb, sk, other);
2287+
if (err)
2288+
goto out;
2289+
22592290
skb_put(skb, 1);
22602291
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
22612292

@@ -2275,7 +2306,6 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
22752306
goto out_unlock;
22762307
}
22772308

2278-
unix_maybe_add_creds(skb, sk, other);
22792309
scm_stat_add(other, skb);
22802310

22812311
spin_lock(&other->sk_receive_queue.lock);
@@ -2369,6 +2399,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
23692399

23702400
fds_sent = true;
23712401

2402+
err = unix_maybe_add_creds(skb, sk, other);
2403+
if (err)
2404+
goto out_free;
2405+
23722406
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
23732407
skb->ip_summed = CHECKSUM_UNNECESSARY;
23742408
err = skb_splice_from_iter(skb, &msg->msg_iter, size,
@@ -2399,7 +2433,6 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
23992433
goto out_free;
24002434
}
24012435

2402-
unix_maybe_add_creds(skb, sk, other);
24032436
scm_stat_add(other, skb);
24042437
skb_queue_tail(&other->sk_receive_queue, skb);
24052438
unix_state_unlock(other);
@@ -2547,8 +2580,7 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
25472580

25482581
memset(&scm, 0, sizeof(scm));
25492582

2550-
scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
2551-
unix_set_secdata(&scm, skb);
2583+
unix_skb_to_scm(skb, &scm);
25522584

25532585
if (!(flags & MSG_PEEK)) {
25542586
if (UNIXCB(skb).fp)
@@ -2933,8 +2965,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
29332965
break;
29342966
} else if (unix_may_passcred(sk)) {
29352967
/* Copy credentials */
2936-
scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
2937-
unix_set_secdata(&scm, skb);
2968+
unix_skb_to_scm(skb, &scm);
29382969
check_creds = true;
29392970
}
29402971

0 commit comments

Comments
 (0)