* [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD
@ 2025-06-29 21:44 Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
` (5 more replies)
0 siblings, 6 replies; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Willem de Bruijn,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima, Simon Horman
This is a logical continuation of a story from [1], where Christian
extented SO_PEERPIDFD to allow getting pidfds for a reaped tasks.
Git tree:
https://github.com/mihalicyn/linux/commits/scm_pidfd_stale
Series based on https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git/log/?h=vfs-6.17.pidfs
It does not use pidfs_get_pid()/pidfs_put_pid() API as these were removed in a scope of [2].
I've checked that net-next branch currently (still) has these obsolete functions, but it
will eventually include changes from [2], so it's not a big problem.
Link: https://lore.kernel.org/all/20250425-work-pidfs-net-v2-0-450a19461e75@kernel.org/ [1]
Link: https://lore.kernel.org/all/20250618-work-pidfs-persistent-v2-0-98f3456fd552@kernel.org/ [2]
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Alexander Mikhalitsyn (6):
af_unix: rework unix_maybe_add_creds() to allow sleep
af_unix: introduce unix_skb_to_scm helper
af_unix: introduce and use __scm_replace_pid() helper
af_unix: stash pidfs dentry when needed
af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD
selftests: net: extend SCM_PIDFD test to cover stale pidfds
include/net/scm.h | 46 +++-
net/core/scm.c | 13 +-
net/unix/af_unix.c | 76 ++++--
.../testing/selftests/net/af_unix/scm_pidfd.c | 217 ++++++++++++++----
4 files changed, 285 insertions(+), 67 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-06-30 18:57 ` Kuniyuki Iwashima
2025-07-01 8:00 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper Alexander Mikhalitsyn
` (4 subsequent siblings)
5 siblings, 2 replies; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima
As a preparation for the next patches we need to allow sleeping
in unix_maybe_add_creds() and also return err. Currently, we can't do
that as unix_maybe_add_creds() is being called under unix_state_lock().
There is no need for this, really. So let's move call sites of
this helper a bit and do necessary function signature changes.
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
net/unix/af_unix.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 129388c309b0..6072d89ce2e7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1955,21 +1955,26 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
return err;
}
-/*
+/* unix_maybe_add_creds() adds current task uid/gid and struct pid to skb if needed.
+ *
* Some apps rely on write() giving SCM_CREDENTIALS
* We include credentials if source or destination socket
* asserted SOCK_PASSCRED.
+ *
+ * Context: May sleep.
*/
-static void unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
- const struct sock *other)
+static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
+ const struct sock *other)
{
if (UNIXCB(skb).pid)
- return;
+ return 0;
if (unix_may_passcred(sk) || unix_may_passcred(other)) {
UNIXCB(skb).pid = get_pid(task_tgid(current));
current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
}
+
+ return 0;
}
static bool unix_skb_scm_eq(struct sk_buff *skb,
@@ -2104,6 +2109,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out_sock_put;
}
+ err = unix_maybe_add_creds(skb, sk, other);
+ if (err)
+ goto out_sock_put;
+
restart:
sk_locked = 0;
unix_state_lock(other);
@@ -2212,7 +2221,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
if (sock_flag(other, SOCK_RCVTSTAMP))
__net_timestamp(skb);
- unix_maybe_add_creds(skb, sk, other);
scm_stat_add(other, skb);
skb_queue_tail(&other->sk_receive_queue, skb);
unix_state_unlock(other);
@@ -2256,6 +2264,10 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
if (err < 0)
goto out;
+ err = unix_maybe_add_creds(skb, sk, other);
+ if (err)
+ goto out;
+
skb_put(skb, 1);
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
@@ -2275,7 +2287,6 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
goto out_unlock;
}
- unix_maybe_add_creds(skb, sk, other);
scm_stat_add(other, skb);
spin_lock(&other->sk_receive_queue.lock);
@@ -2369,6 +2380,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
fds_sent = true;
+ err = unix_maybe_add_creds(skb, sk, other);
+ if (err)
+ goto out_free;
+
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
err = skb_splice_from_iter(skb, &msg->msg_iter, size,
@@ -2399,7 +2414,6 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
goto out_free;
}
- unix_maybe_add_creds(skb, sk, other);
scm_stat_add(other, skb);
skb_queue_tail(&other->sk_receive_queue, skb);
unix_state_unlock(other);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-06-30 18:59 ` Kuniyuki Iwashima
2025-07-01 8:01 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper Alexander Mikhalitsyn
` (3 subsequent siblings)
5 siblings, 2 replies; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima
Instead of open-coding let's consolidate this logic in a separate
helper. This will simplify further changes.
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
net/unix/af_unix.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6072d89ce2e7..5efe6e44abdf 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1955,6 +1955,12 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
return err;
}
+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);
+ unix_set_secdata(scm, skb);
+}
+
/* unix_maybe_add_creds() adds current task uid/gid and struct pid to skb if needed.
*
* Some apps rely on write() giving SCM_CREDENTIALS
@@ -2561,8 +2567,7 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
memset(&scm, 0, sizeof(scm));
- scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
- unix_set_secdata(&scm, skb);
+ unix_skb_to_scm(skb, &scm);
if (!(flags & MSG_PEEK)) {
if (UNIXCB(skb).fp)
@@ -2947,8 +2952,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
break;
} else if (unix_may_passcred(sk)) {
/* Copy credentials */
- scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
- unix_set_secdata(&scm, skb);
+ unix_skb_to_scm(skb, &scm);
check_creds = true;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-06-30 19:45 ` Kuniyuki Iwashima
2025-06-29 21:44 ` [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed Alexander Mikhalitsyn
` (2 subsequent siblings)
5 siblings, 1 reply; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn, Leon Romanovsky, Arnd Bergmann,
Christian Brauner, Lennart Poettering, Luca Boccassi,
David Rheinsberg, Kuniyuki Iwashima
Existing logic in __scm_send() related to filling an struct scm_cookie
with a proper struct pid reference is already pretty tricky. Let's
simplify it a bit by introducing a new helper. This helper will be
extended in one of the next patches.
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
include/net/scm.h | 10 ++++++++++
net/core/scm.c | 11 ++++++++---
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/include/net/scm.h b/include/net/scm.h
index 84c4707e78a5..856eb3a380f6 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -88,6 +88,16 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
__scm_destroy(scm);
}
+static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
+{
+ /* drop all previous references */
+ scm_destroy_cred(scm);
+
+ scm->pid = get_pid(pid);
+ scm->creds.pid = pid_vnr(pid);
+ return 0;
+}
+
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
struct scm_cookie *scm, bool forcecreds)
{
diff --git a/net/core/scm.c b/net/core/scm.c
index 0225bd94170f..0e71d5a249a1 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -189,15 +189,20 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
if (err)
goto error;
- p->creds.pid = creds.pid;
if (!p->pid || pid_vnr(p->pid) != creds.pid) {
struct pid *pid;
err = -ESRCH;
pid = find_get_pid(creds.pid);
if (!pid)
goto error;
- put_pid(p->pid);
- p->pid = pid;
+
+ err = __scm_replace_pid(p, pid);
+ /* Release what we get from find_get_pid() as
+ * __scm_replace_pid() takes all necessary refcounts.
+ */
+ put_pid(pid);
+ if (err)
+ goto error;
}
err = -EINVAL;
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
` (2 preceding siblings ...)
2025-06-29 21:44 ` [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-06-30 20:03 ` Kuniyuki Iwashima
2025-06-29 21:44 ` [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds Alexander Mikhalitsyn
5 siblings, 1 reply; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima
We need to ensure that pidfs dentry is allocated when we meet any
struct pid for the first time. This will allows us to open pidfd
even after the task it corresponds to is reaped.
Basically, we need to identify all places where we fill skb/scm_cookie
with struct pid reference for the first time and call pidfs_register_pid().
Tricky thing here is that we have a few places where this happends
depending on what userspace is doing:
- [__scm_replace_pid()] explicitly sending an SCM_CREDENTIALS message
and specified pid in a numeric format
- [unix_maybe_add_creds()] enabled SO_PASSCRED/SO_PASSPIDFD but
didn't send SCM_CREDENTIALS explicitly
- [scm_send()] force_creds is true. Netlink case.
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
include/net/scm.h | 35 ++++++++++++++++++++++++++++++-----
net/unix/af_unix.c | 36 +++++++++++++++++++++++++++++++++---
2 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/include/net/scm.h b/include/net/scm.h
index 856eb3a380f6..d1ae0704f230 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -8,6 +8,7 @@
#include <linux/file.h>
#include <linux/security.h>
#include <linux/pid.h>
+#include <linux/pidfs.h>
#include <linux/nsproxy.h>
#include <linux/sched/signal.h>
#include <net/compat.h>
@@ -66,19 +67,37 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
{ }
#endif /* CONFIG_SECURITY_NETWORK */
-static __inline__ void scm_set_cred(struct scm_cookie *scm,
- struct pid *pid, kuid_t uid, kgid_t gid)
+static __inline__ int __scm_set_cred(struct scm_cookie *scm,
+ struct pid *pid, bool pidfs_register,
+ kuid_t uid, kgid_t gid)
{
- scm->pid = get_pid(pid);
+ if (pidfs_register) {
+ int err;
+
+ err = pidfs_register_pid(pid);
+ if (err)
+ return err;
+ }
+
+ scm->pid = get_pid(pid);
+
scm->creds.pid = pid_vnr(pid);
scm->creds.uid = uid;
scm->creds.gid = gid;
+ return 0;
+}
+
+static __inline__ void scm_set_cred(struct scm_cookie *scm,
+ struct pid *pid, kuid_t uid, kgid_t gid)
+{
+ /* __scm_set_cred() can't fail when pidfs_register == false */
+ (void) __scm_set_cred(scm, pid, false, uid, gid);
}
static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
{
put_pid(scm->pid);
- scm->pid = NULL;
+ scm->pid = NULL;
}
static __inline__ void scm_destroy(struct scm_cookie *scm)
@@ -90,9 +109,15 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
{
+ int err;
+
/* drop all previous references */
scm_destroy_cred(scm);
+ err = pidfs_register_pid(pid);
+ if (err)
+ return err;
+
scm->pid = get_pid(pid);
scm->creds.pid = pid_vnr(pid);
return 0;
@@ -105,7 +130,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
scm->creds.uid = INVALID_UID;
scm->creds.gid = INVALID_GID;
if (forcecreds)
- scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
+ __scm_set_cred(scm, task_tgid(current), true, current_uid(), current_gid());
unix_get_peersec_dgram(sock, scm);
if (msg->msg_controllen <= 0)
return 0;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 5efe6e44abdf..1f4a5fe8a1f7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1924,12 +1924,34 @@ static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
scm->fp = scm_fp_dup(UNIXCB(skb).fp);
}
+static int __skb_set_pid(struct sk_buff *skb, struct pid *pid, bool pidfs_register)
+{
+ if (pidfs_register) {
+ int err;
+
+ err = pidfs_register_pid(pid);
+ if (err)
+ return err;
+ }
+
+ UNIXCB(skb).pid = get_pid(pid);
+ return 0;
+}
+
static void unix_destruct_scm(struct sk_buff *skb)
{
struct scm_cookie scm;
memset(&scm, 0, sizeof(scm));
- scm.pid = UNIXCB(skb).pid;
+
+ /* Pass ownership of struct pid from skb to scm cookie.
+ *
+ * We rely on scm_destroy() -> scm_destroy_cred() to properly
+ * release everything.
+ */
+ scm.pid = UNIXCB(skb).pid;
+ UNIXCB(skb).pid = NULL;
+
if (UNIXCB(skb).fp)
unix_detach_fds(&scm, skb);
@@ -1943,7 +1965,10 @@ 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);
+ err = __skb_set_pid(skb, scm->pid, false);
+ if (unlikely(err))
+ return err;
+
UNIXCB(skb).uid = scm->creds.uid;
UNIXCB(skb).gid = scm->creds.gid;
UNIXCB(skb).fp = NULL;
@@ -1976,7 +2001,12 @@ static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
return 0;
if (unix_may_passcred(sk) || unix_may_passcred(other)) {
- UNIXCB(skb).pid = get_pid(task_tgid(current));
+ int err;
+
+ err = __skb_set_pid(skb, task_tgid(current), true);
+ if (unlikely(err))
+ return err;
+
current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
` (3 preceding siblings ...)
2025-06-29 21:44 ` [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-07-01 7:52 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds Alexander Mikhalitsyn
5 siblings, 1 reply; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kernel, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn, Leon Romanovsky, Arnd Bergmann,
Christian Brauner, Lennart Poettering, Luca Boccassi,
David Rheinsberg, Kuniyuki Iwashima
Now everything is ready to pass PIDFD_STALE to pidfd_prepare().
This will allow opening pidfd for reaped tasks.
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
include/net/scm.h | 1 +
net/core/scm.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/net/scm.h b/include/net/scm.h
index d1ae0704f230..1960c2b4f0b1 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -8,6 +8,7 @@
#include <linux/file.h>
#include <linux/security.h>
#include <linux/pid.h>
+#include <uapi/linux/pidfd.h>
#include <linux/pidfs.h>
#include <linux/nsproxy.h>
#include <linux/sched/signal.h>
diff --git a/net/core/scm.c b/net/core/scm.c
index 0e71d5a249a1..022d5035d146 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -464,7 +464,7 @@ static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
if (!scm->pid)
return;
- pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
+ pidfd = pidfd_prepare(scm->pid, PIDFD_STALE, &pidfd_file);
if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
if (pidfd_file) {
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
` (4 preceding siblings ...)
2025-06-29 21:44 ` [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD Alexander Mikhalitsyn
@ 2025-06-29 21:44 ` Alexander Mikhalitsyn
2025-07-01 7:59 ` Christian Brauner
5 siblings, 1 reply; 18+ messages in thread
From: Alexander Mikhalitsyn @ 2025-06-29 21:44 UTC (permalink / raw)
To: kuniyu
Cc: Alexander Mikhalitsyn, linux-kselftest, linux-kernel, netdev,
Shuah Khan, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Christian Brauner, Lennart Poettering,
Luca Boccassi, David Rheinsberg, Kuniyuki Iwashima
Extend SCM_PIDFD test scenarios to also cover dead task's
pidfd retrieval and reading its exit info.
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: Shuah Khan <shuah@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Luca Boccassi <bluca@debian.org>
Cc: David Rheinsberg <david@readahead.eu>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
---
.../testing/selftests/net/af_unix/scm_pidfd.c | 217 ++++++++++++++----
1 file changed, 173 insertions(+), 44 deletions(-)
diff --git a/tools/testing/selftests/net/af_unix/scm_pidfd.c b/tools/testing/selftests/net/af_unix/scm_pidfd.c
index 7e534594167e..37e034874034 100644
--- a/tools/testing/selftests/net/af_unix/scm_pidfd.c
+++ b/tools/testing/selftests/net/af_unix/scm_pidfd.c
@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include "../../pidfd/pidfd.h"
#include "../../kselftest_harness.h"
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
@@ -26,6 +27,8 @@
#define SCM_PIDFD 0x04
#endif
+#define CHILD_EXIT_CODE_OK 123
+
static void child_die()
{
exit(1);
@@ -126,16 +129,65 @@ static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
return result;
}
+struct cmsg_data {
+ struct ucred *ucred;
+ int *pidfd;
+};
+
+static int parse_cmsg(struct msghdr *msg, struct cmsg_data *res)
+{
+ struct cmsghdr *cmsg;
+ int data = 0;
+
+ if (msg->msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
+ log_err("recvmsg: truncated");
+ return 1;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_PIDFD) {
+ if (cmsg->cmsg_len < sizeof(*res->pidfd)) {
+ log_err("CMSG parse: SCM_PIDFD wrong len");
+ return 1;
+ }
+
+ res->pidfd = (void *)CMSG_DATA(cmsg);
+ }
+
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_CREDENTIALS) {
+ if (cmsg->cmsg_len < sizeof(*res->ucred)) {
+ log_err("CMSG parse: SCM_CREDENTIALS wrong len");
+ return 1;
+ }
+
+ res->ucred = (void *)CMSG_DATA(cmsg);
+ }
+ }
+
+ if (!res->pidfd) {
+ log_err("CMSG parse: SCM_PIDFD not found");
+ return 1;
+ }
+
+ if (!res->ucred) {
+ log_err("CMSG parse: SCM_CREDENTIALS not found");
+ return 1;
+ }
+
+ return 0;
+}
+
static int cmsg_check(int fd)
{
struct msghdr msg = { 0 };
- struct cmsghdr *cmsg;
+ struct cmsg_data res;
struct iovec iov;
- struct ucred *ucred = NULL;
int data = 0;
char control[CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(sizeof(int))] = { 0 };
- int *pidfd = NULL;
pid_t parent_pid;
int err;
@@ -158,53 +210,99 @@ static int cmsg_check(int fd)
return 1;
}
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_PIDFD) {
- if (cmsg->cmsg_len < sizeof(*pidfd)) {
- log_err("CMSG parse: SCM_PIDFD wrong len");
- return 1;
- }
+ /* send(pfd, "x", sizeof(char), 0) */
+ if (data != 'x') {
+ log_err("recvmsg: data corruption");
+ return 1;
+ }
- pidfd = (void *)CMSG_DATA(cmsg);
- }
+ if (parse_cmsg(&msg, &res)) {
+ log_err("CMSG parse: parse_cmsg() failed");
+ return 1;
+ }
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_CREDENTIALS) {
- if (cmsg->cmsg_len < sizeof(*ucred)) {
- log_err("CMSG parse: SCM_CREDENTIALS wrong len");
- return 1;
- }
+ /* pidfd from SCM_PIDFD should point to the parent process PID */
+ parent_pid =
+ get_pid_from_fdinfo_file(*res.pidfd, "Pid:", sizeof("Pid:") - 1);
+ if (parent_pid != getppid()) {
+ log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid());
+ close(*res.pidfd);
+ return 1;
+ }
- ucred = (void *)CMSG_DATA(cmsg);
- }
+ close(*res.pidfd);
+ return 0;
+}
+
+static int cmsg_check_dead(int fd, int expected_pid)
+{
+ int err;
+ struct msghdr msg = { 0 };
+ struct cmsg_data res;
+ struct iovec iov;
+ int data = 0;
+ char control[CMSG_SPACE(sizeof(struct ucred)) +
+ CMSG_SPACE(sizeof(int))] = { 0 };
+ pid_t client_pid;
+ struct pidfd_info info = {
+ .mask = PIDFD_INFO_EXIT,
+ };
+
+ iov.iov_base = &data;
+ iov.iov_len = sizeof(data);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = control;
+ msg.msg_controllen = sizeof(control);
+
+ err = recvmsg(fd, &msg, 0);
+ if (err < 0) {
+ log_err("recvmsg");
+ return 1;
}
- /* send(pfd, "x", sizeof(char), 0) */
- if (data != 'x') {
+ if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
+ log_err("recvmsg: truncated");
+ return 1;
+ }
+
+ /* send(cfd, "y", sizeof(char), 0) */
+ if (data != 'y') {
log_err("recvmsg: data corruption");
return 1;
}
- if (!pidfd) {
- log_err("CMSG parse: SCM_PIDFD not found");
+ if (parse_cmsg(&msg, &res)) {
+ log_err("CMSG parse: parse_cmsg() failed");
return 1;
}
- if (!ucred) {
- log_err("CMSG parse: SCM_CREDENTIALS not found");
+ /*
+ * pidfd from SCM_PIDFD should point to the client_pid.
+ * Let's read exit information and check if it's what
+ * we expect to see.
+ */
+ if (ioctl(*res.pidfd, PIDFD_GET_INFO, &info)) {
+ log_err("%s: ioctl(PIDFD_GET_INFO) failed", __func__);
+ close(*res.pidfd);
return 1;
}
- /* pidfd from SCM_PIDFD should point to the parent process PID */
- parent_pid =
- get_pid_from_fdinfo_file(*pidfd, "Pid:", sizeof("Pid:") - 1);
- if (parent_pid != getppid()) {
- log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid());
+ if (!(info.mask & PIDFD_INFO_EXIT)) {
+ log_err("%s: No exit information from ioctl(PIDFD_GET_INFO)", __func__);
+ close(*res.pidfd);
return 1;
}
+ err = WIFEXITED(info.exit_code) ? WEXITSTATUS(info.exit_code) : 1;
+ if (err != CHILD_EXIT_CODE_OK) {
+ log_err("%s: wrong exit_code %d != %d", __func__, err, CHILD_EXIT_CODE_OK);
+ close(*res.pidfd);
+ return 1;
+ }
+
+ close(*res.pidfd);
return 0;
}
@@ -291,6 +389,24 @@ static void fill_sockaddr(struct sock_addr *addr, bool abstract)
memcpy(sun_path_buf, addr->sock_name, strlen(addr->sock_name));
}
+static int sk_enable_cred_pass(int sk)
+{
+ int on = 0;
+
+ on = 1;
+ if (setsockopt(sk, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
+ log_err("Failed to set SO_PASSCRED");
+ return 1;
+ }
+
+ if (setsockopt(sk, SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
+ log_err("Failed to set SO_PASSPIDFD");
+ return 1;
+ }
+
+ return 0;
+}
+
static void client(FIXTURE_DATA(scm_pidfd) *self,
const FIXTURE_VARIANT(scm_pidfd) *variant)
{
@@ -299,7 +415,6 @@ static void client(FIXTURE_DATA(scm_pidfd) *self,
struct ucred peer_cred;
int peer_pidfd;
pid_t peer_pid;
- int on = 0;
cfd = socket(AF_UNIX, variant->type, 0);
if (cfd < 0) {
@@ -322,14 +437,8 @@ static void client(FIXTURE_DATA(scm_pidfd) *self,
child_die();
}
- on = 1;
- if (setsockopt(cfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
- log_err("Failed to set SO_PASSCRED");
- child_die();
- }
-
- if (setsockopt(cfd, SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
- log_err("Failed to set SO_PASSPIDFD");
+ if (sk_enable_cred_pass(cfd)) {
+ log_err("sk_enable_cred_pass() failed");
child_die();
}
@@ -340,6 +449,12 @@ static void client(FIXTURE_DATA(scm_pidfd) *self,
child_die();
}
+ /* send something to the parent so it can receive SCM_PIDFD too and validate it */
+ if (send(cfd, "y", sizeof(char), 0) == -1) {
+ log_err("Failed to send(cfd, \"y\", sizeof(char), 0)");
+ child_die();
+ }
+
/* skip further for SOCK_DGRAM as it's not applicable */
if (variant->type == SOCK_DGRAM)
return;
@@ -398,7 +513,13 @@ TEST_F(scm_pidfd, test)
close(self->server);
close(self->startup_pipe[0]);
client(self, variant);
- exit(0);
+
+ /*
+ * It's a bit unusual, but in case of success we return non-zero
+ * exit code (CHILD_EXIT_CODE_OK) and then we expect to read it
+ * from ioctl(PIDFD_GET_INFO) in cmsg_check_dead().
+ */
+ exit(CHILD_EXIT_CODE_OK);
}
close(self->startup_pipe[1]);
@@ -421,9 +542,17 @@ TEST_F(scm_pidfd, test)
ASSERT_NE(-1, err);
}
- close(pfd);
waitpid(self->client_pid, &child_status, 0);
- ASSERT_EQ(0, WIFEXITED(child_status) ? WEXITSTATUS(child_status) : 1);
+ /* see comment before exit(CHILD_EXIT_CODE_OK) */
+ ASSERT_EQ(CHILD_EXIT_CODE_OK, WIFEXITED(child_status) ? WEXITSTATUS(child_status) : 1);
+
+ err = sk_enable_cred_pass(pfd);
+ ASSERT_EQ(0, err);
+
+ err = cmsg_check_dead(pfd, self->client_pid);
+ ASSERT_EQ(0, err);
+
+ close(pfd);
}
TEST_HARNESS_MAIN
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
@ 2025-06-30 18:57 ` Kuniyuki Iwashima
2025-07-01 8:00 ` Christian Brauner
1 sibling, 0 replies; 18+ messages in thread
From: Kuniyuki Iwashima @ 2025-06-30 18:57 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Christian Brauner, Lennart Poettering,
Luca Boccassi, David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
<aleksandr.mikhalitsyn@canonical.com> wrote:
>
> As a preparation for the next patches we need to allow sleeping
> in unix_maybe_add_creds() and also return err. Currently, we can't do
> that as unix_maybe_add_creds() is being called under unix_state_lock().
> There is no need for this, really. So let's move call sites of
> this helper a bit and do necessary function signature changes.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
> net/unix/af_unix.c | 28 +++++++++++++++++++++-------
> 1 file changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 129388c309b0..6072d89ce2e7 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1955,21 +1955,26 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
> return err;
> }
>
> -/*
> +/* unix_maybe_add_creds() adds current task uid/gid and struct pid to skb if needed.
This is not a correct kdoc format.
https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#function-documentation
> + *
> * Some apps rely on write() giving SCM_CREDENTIALS
> * We include credentials if source or destination socket
> * asserted SOCK_PASSCRED.
> + *
> + * Context: May sleep.
This should be added later when this function starts to sleep.
> */
> -static void unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
> - const struct sock *other)
> +static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
> + const struct sock *other)
> {
> if (UNIXCB(skb).pid)
> - return;
> + return 0;
>
> if (unix_may_passcred(sk) || unix_may_passcred(other)) {
> UNIXCB(skb).pid = get_pid(task_tgid(current));
> current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
> }
> +
> + return 0;
> }
>
> static bool unix_skb_scm_eq(struct sk_buff *skb,
> @@ -2104,6 +2109,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
> goto out_sock_put;
> }
>
> + err = unix_maybe_add_creds(skb, sk, other);
> + if (err)
> + goto out_sock_put;
> +
> restart:
> sk_locked = 0;
> unix_state_lock(other);
> @@ -2212,7 +2221,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
> if (sock_flag(other, SOCK_RCVTSTAMP))
> __net_timestamp(skb);
>
> - unix_maybe_add_creds(skb, sk, other);
> scm_stat_add(other, skb);
> skb_queue_tail(&other->sk_receive_queue, skb);
> unix_state_unlock(other);
> @@ -2256,6 +2264,10 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
> if (err < 0)
> goto out;
>
> + err = unix_maybe_add_creds(skb, sk, other);
> + if (err)
> + goto out;
> +
> skb_put(skb, 1);
> err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
>
> @@ -2275,7 +2287,6 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other,
> goto out_unlock;
> }
>
> - unix_maybe_add_creds(skb, sk, other);
> scm_stat_add(other, skb);
>
> spin_lock(&other->sk_receive_queue.lock);
> @@ -2369,6 +2380,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>
> fds_sent = true;
>
> + err = unix_maybe_add_creds(skb, sk, other);
> + if (err)
> + goto out_free;
> +
> if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
> skb->ip_summed = CHECKSUM_UNNECESSARY;
> err = skb_splice_from_iter(skb, &msg->msg_iter, size,
> @@ -2399,7 +2414,6 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
> goto out_free;
> }
>
> - unix_maybe_add_creds(skb, sk, other);
> scm_stat_add(other, skb);
> skb_queue_tail(&other->sk_receive_queue, skb);
> unix_state_unlock(other);
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper
2025-06-29 21:44 ` [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper Alexander Mikhalitsyn
@ 2025-06-30 18:59 ` Kuniyuki Iwashima
2025-07-01 8:01 ` Christian Brauner
1 sibling, 0 replies; 18+ messages in thread
From: Kuniyuki Iwashima @ 2025-06-30 18:59 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Christian Brauner, Lennart Poettering,
Luca Boccassi, David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
<aleksandr.mikhalitsyn@canonical.com> wrote:
>
> Instead of open-coding let's consolidate this logic in a separate
> helper. This will simplify further changes.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper
2025-06-29 21:44 ` [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper Alexander Mikhalitsyn
@ 2025-06-30 19:45 ` Kuniyuki Iwashima
2025-07-01 8:48 ` Aleksandr Mikhalitsyn
0 siblings, 1 reply; 18+ messages in thread
From: Kuniyuki Iwashima @ 2025-06-30 19:45 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg
[dropped my previous email address]
On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
<aleksandr.mikhalitsyn@canonical.com> wrote:
>
> Existing logic in __scm_send() related to filling an struct scm_cookie
> with a proper struct pid reference is already pretty tricky. Let's
> simplify it a bit by introducing a new helper. This helper will be
> extended in one of the next patches.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
> include/net/scm.h | 10 ++++++++++
> net/core/scm.c | 11 ++++++++---
> 2 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/include/net/scm.h b/include/net/scm.h
> index 84c4707e78a5..856eb3a380f6 100644
> --- a/include/net/scm.h
> +++ b/include/net/scm.h
> @@ -88,6 +88,16 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
> __scm_destroy(scm);
> }
>
> +static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
It seems this function is only called from __scm_send() so this should
be moved to .c (and inlined ?).
> +{
> + /* drop all previous references */
> + scm_destroy_cred(scm);
> +
> + scm->pid = get_pid(pid);
This looks redundant. Maybe move the put_pid() under if (error)
in __scm_send().
> + scm->creds.pid = pid_vnr(pid);
> + return 0;
> +}
> +
> static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
> struct scm_cookie *scm, bool forcecreds)
> {
> diff --git a/net/core/scm.c b/net/core/scm.c
> index 0225bd94170f..0e71d5a249a1 100644
> --- a/net/core/scm.c
> +++ b/net/core/scm.c
> @@ -189,15 +189,20 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
> if (err)
> goto error;
>
> - p->creds.pid = creds.pid;
> if (!p->pid || pid_vnr(p->pid) != creds.pid) {
> struct pid *pid;
> err = -ESRCH;
> pid = find_get_pid(creds.pid);
> if (!pid)
> goto error;
> - put_pid(p->pid);
> - p->pid = pid;
> +
> + err = __scm_replace_pid(p, pid);
> + /* Release what we get from find_get_pid() as
> + * __scm_replace_pid() takes all necessary refcounts.
> + */
> + put_pid(pid);
> + if (err)
> + goto error;
> }
>
> err = -EINVAL;
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed
2025-06-29 21:44 ` [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed Alexander Mikhalitsyn
@ 2025-06-30 20:03 ` Kuniyuki Iwashima
2025-07-01 8:46 ` Aleksandr Mikhalitsyn
0 siblings, 1 reply; 18+ messages in thread
From: Kuniyuki Iwashima @ 2025-06-30 20:03 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Christian Brauner, Lennart Poettering,
Luca Boccassi, David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
<aleksandr.mikhalitsyn@canonical.com> wrote:
>
> We need to ensure that pidfs dentry is allocated when we meet any
> struct pid for the first time. This will allows us to open pidfd
> even after the task it corresponds to is reaped.
>
> Basically, we need to identify all places where we fill skb/scm_cookie
> with struct pid reference for the first time and call pidfs_register_pid().
>
> Tricky thing here is that we have a few places where this happends
> depending on what userspace is doing:
> - [__scm_replace_pid()] explicitly sending an SCM_CREDENTIALS message
> and specified pid in a numeric format
> - [unix_maybe_add_creds()] enabled SO_PASSCRED/SO_PASSPIDFD but
> didn't send SCM_CREDENTIALS explicitly
> - [scm_send()] force_creds is true. Netlink case.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
> include/net/scm.h | 35 ++++++++++++++++++++++++++++++-----
> net/unix/af_unix.c | 36 +++++++++++++++++++++++++++++++++---
> 2 files changed, 63 insertions(+), 8 deletions(-)
>
> diff --git a/include/net/scm.h b/include/net/scm.h
> index 856eb3a380f6..d1ae0704f230 100644
> --- a/include/net/scm.h
> +++ b/include/net/scm.h
> @@ -8,6 +8,7 @@
> #include <linux/file.h>
> #include <linux/security.h>
> #include <linux/pid.h>
> +#include <linux/pidfs.h>
> #include <linux/nsproxy.h>
> #include <linux/sched/signal.h>
> #include <net/compat.h>
> @@ -66,19 +67,37 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
> { }
> #endif /* CONFIG_SECURITY_NETWORK */
>
> -static __inline__ void scm_set_cred(struct scm_cookie *scm,
> - struct pid *pid, kuid_t uid, kgid_t gid)
> +static __inline__ int __scm_set_cred(struct scm_cookie *scm,
> + struct pid *pid, bool pidfs_register,
> + kuid_t uid, kgid_t gid)
scm_set_cred() is only called from 3 places, and I think you can simply
pass pidfd_register == false from one of the places.
while at it, please replace s/__inline__/inline/
> {
> - scm->pid = get_pid(pid);
> + if (pidfs_register) {
> + int err;
> +
> + err = pidfs_register_pid(pid);
nit: int err = pidfs_...();
> + if (err)
> + return err;
> + }
> +
> + scm->pid = get_pid(pid);
> +
> scm->creds.pid = pid_vnr(pid);
> scm->creds.uid = uid;
> scm->creds.gid = gid;
> + return 0;
> +}
> +
> +static __inline__ void scm_set_cred(struct scm_cookie *scm,
> + struct pid *pid, kuid_t uid, kgid_t gid)
> +{
> + /* __scm_set_cred() can't fail when pidfs_register == false */
> + (void) __scm_set_cred(scm, pid, false, uid, gid);
I think this (void) style is unnecessary for recent compilers.
> }
>
> static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
> {
> put_pid(scm->pid);
> - scm->pid = NULL;
> + scm->pid = NULL;
> }
>
> static __inline__ void scm_destroy(struct scm_cookie *scm)
> @@ -90,9 +109,15 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
>
> static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
> {
> + int err;
> +
> /* drop all previous references */
> scm_destroy_cred(scm);
>
> + err = pidfs_register_pid(pid);
> + if (err)
> + return err;
> +
> scm->pid = get_pid(pid);
> scm->creds.pid = pid_vnr(pid);
> return 0;
> @@ -105,7 +130,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
> scm->creds.uid = INVALID_UID;
> scm->creds.gid = INVALID_GID;
> if (forcecreds)
> - scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
> + __scm_set_cred(scm, task_tgid(current), true, current_uid(), current_gid());
> unix_get_peersec_dgram(sock, scm);
> if (msg->msg_controllen <= 0)
> return 0;
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 5efe6e44abdf..1f4a5fe8a1f7 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1924,12 +1924,34 @@ static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
> scm->fp = scm_fp_dup(UNIXCB(skb).fp);
> }
>
> +static int __skb_set_pid(struct sk_buff *skb, struct pid *pid, bool pidfs_register)
unix_set_pid_to_skb ?
> +{
> + if (pidfs_register) {
> + int err;
> +
> + err = pidfs_register_pid(pid);
> + if (err)
> + return err;
> + }
> +
> + UNIXCB(skb).pid = get_pid(pid);
> + return 0;
> +}
> +
> static void unix_destruct_scm(struct sk_buff *skb)
> {
> struct scm_cookie scm;
>
> memset(&scm, 0, sizeof(scm));
> - scm.pid = UNIXCB(skb).pid;
> +
> + /* Pass ownership of struct pid from skb to scm cookie.
> + *
> + * We rely on scm_destroy() -> scm_destroy_cred() to properly
> + * release everything.
> + */
> + scm.pid = UNIXCB(skb).pid;
> + UNIXCB(skb).pid = NULL;
The skb is under destruction and we no longer touch it, so
this chunk is not needed.
> +
> if (UNIXCB(skb).fp)
> unix_detach_fds(&scm, skb);
>
> @@ -1943,7 +1965,10 @@ 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);
> + err = __skb_set_pid(skb, scm->pid, false);
> + if (unlikely(err))
> + return err;
> +
> UNIXCB(skb).uid = scm->creds.uid;
> UNIXCB(skb).gid = scm->creds.gid;
> UNIXCB(skb).fp = NULL;
> @@ -1976,7 +2001,12 @@ static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
> return 0;
>
> if (unix_may_passcred(sk) || unix_may_passcred(other)) {
> - UNIXCB(skb).pid = get_pid(task_tgid(current));
> + int err;
> +
> + err = __skb_set_pid(skb, task_tgid(current), true);
> + if (unlikely(err))
> + return err;
> +
> current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
> }
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD
2025-06-29 21:44 ` [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD Alexander Mikhalitsyn
@ 2025-07-01 7:52 ` Christian Brauner
0 siblings, 0 replies; 18+ messages in thread
From: Christian Brauner @ 2025-07-01 7:52 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: kuniyu, linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Leon Romanovsky, Arnd Bergmann, Lennart Poettering, Luca Boccassi,
David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 11:44:42PM +0200, Alexander Mikhalitsyn wrote:
> Now everything is ready to pass PIDFD_STALE to pidfd_prepare().
> This will allow opening pidfd for reaped tasks.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
Thanks!
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds
2025-06-29 21:44 ` [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds Alexander Mikhalitsyn
@ 2025-07-01 7:59 ` Christian Brauner
2025-07-01 8:47 ` Aleksandr Mikhalitsyn
0 siblings, 1 reply; 18+ messages in thread
From: Christian Brauner @ 2025-07-01 7:59 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: kuniyu, linux-kselftest, linux-kernel, netdev, Shuah Khan,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 11:44:43PM +0200, Alexander Mikhalitsyn wrote:
> Extend SCM_PIDFD test scenarios to also cover dead task's
> pidfd retrieval and reading its exit info.
>
> Cc: linux-kselftest@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: Shuah Khan <shuah@kernel.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
Thanks for the tests!
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
2025-06-30 18:57 ` Kuniyuki Iwashima
@ 2025-07-01 8:00 ` Christian Brauner
1 sibling, 0 replies; 18+ messages in thread
From: Christian Brauner @ 2025-07-01 8:00 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: kuniyu, linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Lennart Poettering, Luca Boccassi,
David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 11:44:38PM +0200, Alexander Mikhalitsyn wrote:
> As a preparation for the next patches we need to allow sleeping
> in unix_maybe_add_creds() and also return err. Currently, we can't do
> that as unix_maybe_add_creds() is being called under unix_state_lock().
> There is no need for this, really. So let's move call sites of
> this helper a bit and do necessary function signature changes.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
This looks good to me.
Please feel free to carry my RvB post the minor fixes requested by
Kuniyuki:
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper
2025-06-29 21:44 ` [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper Alexander Mikhalitsyn
2025-06-30 18:59 ` Kuniyuki Iwashima
@ 2025-07-01 8:01 ` Christian Brauner
1 sibling, 0 replies; 18+ messages in thread
From: Christian Brauner @ 2025-07-01 8:01 UTC (permalink / raw)
To: Alexander Mikhalitsyn
Cc: kuniyu, linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Lennart Poettering, Luca Boccassi,
David Rheinsberg, Kuniyuki Iwashima
On Sun, Jun 29, 2025 at 11:44:39PM +0200, Alexander Mikhalitsyn wrote:
> Instead of open-coding let's consolidate this logic in a separate
> helper. This will simplify further changes.
>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Leon Romanovsky <leon@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Lennart Poettering <mzxreary@0pointer.de>
> Cc: Luca Boccassi <bluca@debian.org>
> Cc: David Rheinsberg <david@readahead.eu>
> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> ---
Nice simplification:
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed
2025-06-30 20:03 ` Kuniyuki Iwashima
@ 2025-07-01 8:46 ` Aleksandr Mikhalitsyn
0 siblings, 0 replies; 18+ messages in thread
From: Aleksandr Mikhalitsyn @ 2025-07-01 8:46 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Leon Romanovsky,
Arnd Bergmann, Christian Brauner, Lennart Poettering,
Luca Boccassi, David Rheinsberg
On Mon, Jun 30, 2025 at 10:03 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
> <aleksandr.mikhalitsyn@canonical.com> wrote:
> >
> > We need to ensure that pidfs dentry is allocated when we meet any
> > struct pid for the first time. This will allows us to open pidfd
> > even after the task it corresponds to is reaped.
> >
> > Basically, we need to identify all places where we fill skb/scm_cookie
> > with struct pid reference for the first time and call pidfs_register_pid().
> >
> > Tricky thing here is that we have a few places where this happends
> > depending on what userspace is doing:
> > - [__scm_replace_pid()] explicitly sending an SCM_CREDENTIALS message
> > and specified pid in a numeric format
> > - [unix_maybe_add_creds()] enabled SO_PASSCRED/SO_PASSPIDFD but
> > didn't send SCM_CREDENTIALS explicitly
> > - [scm_send()] force_creds is true. Netlink case.
> >
> > Cc: linux-kernel@vger.kernel.org
> > Cc: netdev@vger.kernel.org
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Cc: Jakub Kicinski <kuba@kernel.org>
> > Cc: Paolo Abeni <pabeni@redhat.com>
> > Cc: Simon Horman <horms@kernel.org>
> > Cc: Leon Romanovsky <leon@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Christian Brauner <brauner@kernel.org>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Cc: Lennart Poettering <mzxreary@0pointer.de>
> > Cc: Luca Boccassi <bluca@debian.org>
> > Cc: David Rheinsberg <david@readahead.eu>
> > Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> > ---
> > include/net/scm.h | 35 ++++++++++++++++++++++++++++++-----
> > net/unix/af_unix.c | 36 +++++++++++++++++++++++++++++++++---
> > 2 files changed, 63 insertions(+), 8 deletions(-)
> >
> > diff --git a/include/net/scm.h b/include/net/scm.h
> > index 856eb3a380f6..d1ae0704f230 100644
> > --- a/include/net/scm.h
> > +++ b/include/net/scm.h
> > @@ -8,6 +8,7 @@
> > #include <linux/file.h>
> > #include <linux/security.h>
> > #include <linux/pid.h>
> > +#include <linux/pidfs.h>
> > #include <linux/nsproxy.h>
> > #include <linux/sched/signal.h>
> > #include <net/compat.h>
> > @@ -66,19 +67,37 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
> > { }
> > #endif /* CONFIG_SECURITY_NETWORK */
> >
> > -static __inline__ void scm_set_cred(struct scm_cookie *scm,
> > - struct pid *pid, kuid_t uid, kgid_t gid)
> > +static __inline__ int __scm_set_cred(struct scm_cookie *scm,
> > + struct pid *pid, bool pidfs_register,
> > + kuid_t uid, kgid_t gid)
>
> scm_set_cred() is only called from 3 places, and I think you can simply
> pass pidfd_register == false from one of the places.
Hi Kuniyuki,
Thanks for such a fast review! ;-)
I've just sent a -v2 with all fixes you've suggested:
https://lore.kernel.org/netdev/20250701083922.97928-1-aleksandr.mikhalitsyn@canonical.com/#r
Kind regards,
Alex
>
> while at it, please replace s/__inline__/inline/
Have done ;)
>
> > {
> > - scm->pid = get_pid(pid);
> > + if (pidfs_register) {
> > + int err;
> > +
> > + err = pidfs_register_pid(pid);
>
> nit: int err = pidfs_...();
Fixed!
>
> > + if (err)
> > + return err;
> > + }
> > +
> > + scm->pid = get_pid(pid);
> > +
> > scm->creds.pid = pid_vnr(pid);
> > scm->creds.uid = uid;
> > scm->creds.gid = gid;
> > + return 0;
> > +}
> > +
> > +static __inline__ void scm_set_cred(struct scm_cookie *scm,
> > + struct pid *pid, kuid_t uid, kgid_t gid)
> > +{
> > + /* __scm_set_cred() can't fail when pidfs_register == false */
> > + (void) __scm_set_cred(scm, pid, false, uid, gid);
>
> I think this (void) style is unnecessary for recent compilers.
+
>
> > }
> >
> > static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
> > {
> > put_pid(scm->pid);
> > - scm->pid = NULL;
> > + scm->pid = NULL;
> > }
> >
> > static __inline__ void scm_destroy(struct scm_cookie *scm)
> > @@ -90,9 +109,15 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
> >
> > static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
> > {
> > + int err;
> > +
> > /* drop all previous references */
> > scm_destroy_cred(scm);
> >
> > + err = pidfs_register_pid(pid);
> > + if (err)
> > + return err;
> > +
> > scm->pid = get_pid(pid);
> > scm->creds.pid = pid_vnr(pid);
> > return 0;
> > @@ -105,7 +130,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
> > scm->creds.uid = INVALID_UID;
> > scm->creds.gid = INVALID_GID;
> > if (forcecreds)
> > - scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
> > + __scm_set_cred(scm, task_tgid(current), true, current_uid(), current_gid());
> > unix_get_peersec_dgram(sock, scm);
> > if (msg->msg_controllen <= 0)
> > return 0;
> > diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> > index 5efe6e44abdf..1f4a5fe8a1f7 100644
> > --- a/net/unix/af_unix.c
> > +++ b/net/unix/af_unix.c
> > @@ -1924,12 +1924,34 @@ static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
> > scm->fp = scm_fp_dup(UNIXCB(skb).fp);
> > }
> >
> > +static int __skb_set_pid(struct sk_buff *skb, struct pid *pid, bool pidfs_register)
>
> unix_set_pid_to_skb ?
+
>
> > +{
> > + if (pidfs_register) {
> > + int err;
> > +
> > + err = pidfs_register_pid(pid);
> > + if (err)
> > + return err;
> > + }
> > +
> > + UNIXCB(skb).pid = get_pid(pid);
> > + return 0;
> > +}
> > +
> > static void unix_destruct_scm(struct sk_buff *skb)
> > {
> > struct scm_cookie scm;
> >
> > memset(&scm, 0, sizeof(scm));
> > - scm.pid = UNIXCB(skb).pid;
> > +
> > + /* Pass ownership of struct pid from skb to scm cookie.
> > + *
> > + * We rely on scm_destroy() -> scm_destroy_cred() to properly
> > + * release everything.
> > + */
> > + scm.pid = UNIXCB(skb).pid;
> > + UNIXCB(skb).pid = NULL;
>
> The skb is under destruction and we no longer touch it, so
> this chunk is not needed.
>
+
>
> > +
> > if (UNIXCB(skb).fp)
> > unix_detach_fds(&scm, skb);
> >
> > @@ -1943,7 +1965,10 @@ 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);
> > + err = __skb_set_pid(skb, scm->pid, false);
> > + if (unlikely(err))
> > + return err;
> > +
> > UNIXCB(skb).uid = scm->creds.uid;
> > UNIXCB(skb).gid = scm->creds.gid;
> > UNIXCB(skb).fp = NULL;
> > @@ -1976,7 +2001,12 @@ static int unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk,
> > return 0;
> >
> > if (unix_may_passcred(sk) || unix_may_passcred(other)) {
> > - UNIXCB(skb).pid = get_pid(task_tgid(current));
> > + int err;
> > +
> > + err = __skb_set_pid(skb, task_tgid(current), true);
> > + if (unlikely(err))
> > + return err;
> > +
> > current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
> > }
> >
> > --
> > 2.43.0
> >
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds
2025-07-01 7:59 ` Christian Brauner
@ 2025-07-01 8:47 ` Aleksandr Mikhalitsyn
0 siblings, 0 replies; 18+ messages in thread
From: Aleksandr Mikhalitsyn @ 2025-07-01 8:47 UTC (permalink / raw)
To: Christian Brauner
Cc: kuniyu, linux-kselftest, linux-kernel, netdev, Shuah Khan,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Lennart Poettering, Luca Boccassi, David Rheinsberg,
Kuniyuki Iwashima
On Tue, Jul 1, 2025 at 9:59 AM Christian Brauner <brauner@kernel.org> wrote:
>
> On Sun, Jun 29, 2025 at 11:44:43PM +0200, Alexander Mikhalitsyn wrote:
> > Extend SCM_PIDFD test scenarios to also cover dead task's
> > pidfd retrieval and reading its exit info.
> >
> > Cc: linux-kselftest@vger.kernel.org
> > Cc: linux-kernel@vger.kernel.org
> > Cc: netdev@vger.kernel.org
> > Cc: Shuah Khan <shuah@kernel.org>
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Cc: Jakub Kicinski <kuba@kernel.org>
> > Cc: Paolo Abeni <pabeni@redhat.com>
> > Cc: Simon Horman <horms@kernel.org>
> > Cc: Christian Brauner <brauner@kernel.org>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Cc: Lennart Poettering <mzxreary@0pointer.de>
> > Cc: Luca Boccassi <bluca@debian.org>
> > Cc: David Rheinsberg <david@readahead.eu>
> > Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> > ---
>
> Thanks for the tests!
> Reviewed-by: Christian Brauner <brauner@kernel.org>
Thanks for off-list discussions/review and help too, Christian! ;-)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper
2025-06-30 19:45 ` Kuniyuki Iwashima
@ 2025-07-01 8:48 ` Aleksandr Mikhalitsyn
0 siblings, 0 replies; 18+ messages in thread
From: Aleksandr Mikhalitsyn @ 2025-07-01 8:48 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: linux-kernel, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn,
Leon Romanovsky, Arnd Bergmann, Christian Brauner,
Lennart Poettering, Luca Boccassi, David Rheinsberg
On Mon, Jun 30, 2025 at 9:46 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> [dropped my previous email address]
>
> On Sun, Jun 29, 2025 at 2:45 PM Alexander Mikhalitsyn
> <aleksandr.mikhalitsyn@canonical.com> wrote:
> >
> > Existing logic in __scm_send() related to filling an struct scm_cookie
> > with a proper struct pid reference is already pretty tricky. Let's
> > simplify it a bit by introducing a new helper. This helper will be
> > extended in one of the next patches.
> >
> > Cc: linux-kernel@vger.kernel.org
> > Cc: netdev@vger.kernel.org
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Cc: Jakub Kicinski <kuba@kernel.org>
> > Cc: Paolo Abeni <pabeni@redhat.com>
> > Cc: Simon Horman <horms@kernel.org>
> > Cc: Willem de Bruijn <willemb@google.com>
> > Cc: Leon Romanovsky <leon@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Christian Brauner <brauner@kernel.org>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Cc: Lennart Poettering <mzxreary@0pointer.de>
> > Cc: Luca Boccassi <bluca@debian.org>
> > Cc: David Rheinsberg <david@readahead.eu>
> > Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> > ---
> > include/net/scm.h | 10 ++++++++++
> > net/core/scm.c | 11 ++++++++---
> > 2 files changed, 18 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/net/scm.h b/include/net/scm.h
> > index 84c4707e78a5..856eb3a380f6 100644
> > --- a/include/net/scm.h
> > +++ b/include/net/scm.h
> > @@ -88,6 +88,16 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
> > __scm_destroy(scm);
> > }
> >
> > +static __inline__ int __scm_replace_pid(struct scm_cookie *scm, struct pid *pid)
>
> It seems this function is only called from __scm_send() so this should
> be moved to .c (and inlined ?).
sure!
>
> > +{
> > + /* drop all previous references */
> > + scm_destroy_cred(scm);
> > +
> > + scm->pid = get_pid(pid);
>
> This looks redundant. Maybe move the put_pid() under if (error)
> in __scm_send().
yep, fixed in v2.
>
> > + scm->creds.pid = pid_vnr(pid);
> > + return 0;
> > +}
> > +
> > static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
> > struct scm_cookie *scm, bool forcecreds)
> > {
> > diff --git a/net/core/scm.c b/net/core/scm.c
> > index 0225bd94170f..0e71d5a249a1 100644
> > --- a/net/core/scm.c
> > +++ b/net/core/scm.c
> > @@ -189,15 +189,20 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
> > if (err)
> > goto error;
> >
> > - p->creds.pid = creds.pid;
> > if (!p->pid || pid_vnr(p->pid) != creds.pid) {
> > struct pid *pid;
> > err = -ESRCH;
> > pid = find_get_pid(creds.pid);
> > if (!pid)
> > goto error;
> > - put_pid(p->pid);
> > - p->pid = pid;
> > +
> > + err = __scm_replace_pid(p, pid);
> > + /* Release what we get from find_get_pid() as
> > + * __scm_replace_pid() takes all necessary refcounts.
> > + */
> > + put_pid(pid);
> > + if (err)
> > + goto error;
> > }
> >
> > err = -EINVAL;
> > --
> > 2.43.0
> >
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-07-01 8:48 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-29 21:44 [RESEND PATCH net-next 0/6] allow reaped pidfds receive in SCM_PIDFD Alexander Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 1/6] af_unix: rework unix_maybe_add_creds() to allow sleep Alexander Mikhalitsyn
2025-06-30 18:57 ` Kuniyuki Iwashima
2025-07-01 8:00 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 2/6] af_unix: introduce unix_skb_to_scm helper Alexander Mikhalitsyn
2025-06-30 18:59 ` Kuniyuki Iwashima
2025-07-01 8:01 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 3/6] af_unix: introduce and use __scm_replace_pid() helper Alexander Mikhalitsyn
2025-06-30 19:45 ` Kuniyuki Iwashima
2025-07-01 8:48 ` Aleksandr Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 4/6] af_unix: stash pidfs dentry when needed Alexander Mikhalitsyn
2025-06-30 20:03 ` Kuniyuki Iwashima
2025-07-01 8:46 ` Aleksandr Mikhalitsyn
2025-06-29 21:44 ` [RESEND PATCH net-next 5/6] af_unix: enable handing out pidfds for reaped tasks in SCM_PIDFD Alexander Mikhalitsyn
2025-07-01 7:52 ` Christian Brauner
2025-06-29 21:44 ` [RESEND PATCH net-next 6/6] selftests: net: extend SCM_PIDFD test to cover stale pidfds Alexander Mikhalitsyn
2025-07-01 7:59 ` Christian Brauner
2025-07-01 8:47 ` Aleksandr Mikhalitsyn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox