Thread (25 messages) flat view 25 messages, 3 authors, 8d ago

Re: [PATCH 02/10] af_unix: record the pid of the sending thread

From: Alexander Mikhalitsyn <hidden>
Date: 2026-09-07 09:55:36
Also in: linux-fsdevel, lkml

Am Mo., 31. Aug. 2026 um 13:21 Uhr schrieb Christian Brauner
[off-list ref]:
quoted hunk ↗ jump to hunk
Currently only the struct pid of the thread-group leader is recorded.
The identity of the actual thread that sent the message or is connected
to a given socket cannot be retrieved.

Add the plumbing to make it possible to retrieve a pidfd for the sender.
Nothing uses the thread-specific struct pid yet. No functional changes.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 include/net/scm.h  |  7 +++----
 net/core/scm.c     | 21 +++++++++++++++++----
 net/unix/af_unix.c | 23 +++++++++++++----------
 net/unix/af_unix.h |  3 ++-
 4 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/include/net/scm.h b/include/net/scm.h
index 86ae6bc109ec..aa7d15c5fc27 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -42,7 +42,7 @@ struct scm_fp_list {
 };

 struct scm_cookie {
-       struct pid              *pid;           /* Skb credentials */
+       DECLARE_PIDS(pid, PIDTYPE_TGID);        /* Skb credentials by pid type */
        struct scm_fp_list      *fp;            /* Passed files         */
        struct scm_creds        creds;          /* Skb credentials      */
 #ifdef CONFIG_SECURITY_NETWORK
@@ -69,7 +69,7 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
 static __inline__ void scm_set_cred(struct scm_cookie *scm,
                                    struct pid *pid, kuid_t uid, kgid_t gid)
 {
-       scm->pid = get_pid(pid);
+       scm->pid[PIDTYPE_TGID] = get_pid(pid);
        scm->creds.pid = pid_vnr(pid);
        scm->creds.uid = uid;
        scm->creds.gid = gid;
@@ -77,8 +77,7 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,

 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
 {
-       put_pid(scm->pid);
-       scm->pid = NULL;
+       put_pids(scm->pid);
 }

 static __inline__ void scm_destroy(struct scm_cookie *scm)
diff --git a/net/core/scm.c b/net/core/scm.c
index f0d44ecdb11f..9b9e119c353a 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -149,6 +149,7 @@ EXPORT_SYMBOL(__scm_destroy);

 static inline int scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
 {
+       struct pid *thread_pid;
        int err;

        /* drop all previous references */
@@ -158,7 +159,18 @@ static inline int scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
        if (unlikely(err))
                return err;

-       scm->pid = pid;
+       /* A sender naming its own thread-group sends from the current thread. */
+       if (pid == task_tgid(current))
+               thread_pid = task_pid(current);
+       else
+               thread_pid = pid;
Hi Christian,

The patch looks good to me, but this spot raised some doubts for me.

If scm_replace_pid() is called with pid == task_tgid(current) then all
good, because we
get scm->pid[PIDTYPE_TGID] == pid and  scm->pid[PIDTYPE_PID] ==
task_pid(current). All good.

If scm_replace_pid() is supplied with pid that has a type PIDTYPE_TGID, then:
- scm->pid[PIDTYPE_TGID] == pid. Good.
- scm->pid[PIDTYPE_PID] = pid. Doesn't looks correct, shoudn't we do
something like:
{
        struct task_struct *task;

        rcu_read_lock();
        task = pid_task(pid, PIDTYPE_TGID);
        thread_pid = task_pid(task);
        rcu_read_unlock();
}

to get a correct thread_pid for both cases here?

Kind regards,
Alex
quoted hunk ↗ jump to hunk
+
+       err = pidfs_register_pid(thread_pid);
+       if (unlikely(err))
+               return err;
+
+       scm->pid[PIDTYPE_TGID] = pid;
+       scm->pid[PIDTYPE_PID] = get_pid(thread_pid);
        scm->creds.pid = pid_vnr(pid);
        return 0;
 }
@@ -207,7 +219,8 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
                        if (err)
                                goto error;

-                       if (!p->pid || pid_vnr(p->pid) != creds.pid) {
+                       if (!p->pid[PIDTYPE_TGID] ||
+                           pid_vnr(p->pid[PIDTYPE_TGID]) != creds.pid) {
                                struct pid *pid;
                                err = -ESRCH;
                                pid = find_get_pid(creds.pid);
@@ -504,10 +517,10 @@ static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
                return;
        }

-       if (!scm->pid)
+       if (!scm->pid[PIDTYPE_TGID])
                return;

-       pidfd = pidfd_prepare(scm->pid, PIDFD_STALE, &pidfd_file);
+       pidfd = pidfd_prepare(scm->pid[PIDTYPE_TGID], PIDFD_STALE, &pidfd_file);

        if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
                if (pidfd_file) {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 13f9926bf205..011af84e3626 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1973,7 +1973,7 @@ static void unix_destruct_scm(struct sk_buff *skb)
 {
        struct scm_cookie scm = {};

-       swap(scm.pid, UNIXCB(skb).pid);
+       swap_pids(scm.pid, UNIXCB(skb).pid);

        if (UNIXCB(skb).fp)
                unix_detach_fds(&scm, skb);
@@ -1991,7 +1991,7 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
 {
        int err = 0;

-       UNIXCB(skb).pid = get_pid(scm->pid);
+       get_pids(UNIXCB(skb).pid, scm->pid);
        UNIXCB(skb).uid = scm->creds.uid;
        UNIXCB(skb).gid = scm->creds.gid;
        UNIXCB(skb).fp = NULL;
@@ -2005,7 +2005,10 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen

 static void unix_skb_to_scm(struct sk_buff *skb, struct scm_cookie *scm)
 {
-       scm_set_cred(scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
+       get_pids(scm->pid, UNIXCB(skb).pid);
+       scm->creds.pid = pid_vnr(scm->pid[PIDTYPE_TGID]);
+       scm->creds.uid = UNIXCB(skb).uid;
+       scm->creds.gid = UNIXCB(skb).gid;
        unix_set_secdata(scm, skb);
 }
@@ -2025,20 +2028,20 @@ static void unix_skb_to_scm(struct sk_buff *skb, struct scm_cookie *scm)
 static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
                                const struct sock *other)
 {
-       if (UNIXCB(skb).pid)
+       if (UNIXCB(skb).pid[PIDTYPE_TGID])
                return 0;

        if (unix_may_passcred(sk) || unix_may_passcred(other) ||
            !other->sk_socket) {
-               struct pid *pid;
                int err;

-               pid = task_tgid(current);
-               err = pidfs_register_pid(pid);
-               if (unlikely(err))
+               get_task_pids(UNIXCB(skb).pid, current);
+               err = pidfs_register_pids(UNIXCB(skb).pid);
+               if (unlikely(err)) {
+                       put_pids(UNIXCB(skb).pid);
                        return err;
+               }

-               UNIXCB(skb).pid = get_pid(pid);
                current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
        }
@@ -2048,7 +2051,7 @@ static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
 static bool unix_skb_scm_eq(struct sk_buff *skb,
                            struct scm_cookie *scm)
 {
-       return UNIXCB(skb).pid == scm->pid &&
+       return UNIXCB(skb).pid[PIDTYPE_TGID] == scm->pid[PIDTYPE_TGID] &&
               uid_eq(UNIXCB(skb).uid, scm->creds.uid) &&
               gid_eq(UNIXCB(skb).gid, scm->creds.gid) &&
               unix_secdata_eq(scm, skb);
diff --git a/net/unix/af_unix.h b/net/unix/af_unix.h
index 8119dbeef3a3..402742895acc 100644
--- a/net/unix/af_unix.h
+++ b/net/unix/af_unix.h
@@ -2,6 +2,7 @@
 #ifndef __AF_UNIX_H
 #define __AF_UNIX_H

+#include <linux/pid_types.h>
 #include <linux/uidgid.h>

 #define UNIX_HASH_MOD  (256 - 1)
@@ -11,7 +12,7 @@
 struct sock *unix_peer_get(struct sock *sk);

 struct unix_skb_parms {
-       struct pid              *pid;           /* skb credentials      */
+       DECLARE_PIDS(pid, PIDTYPE_TGID);        /* skb credentials by pid type */
        kuid_t                  uid;
        kgid_t                  gid;
        struct scm_fp_list      *fp;            /* Passed files         */

--
2.53.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help