From: Heiko Carstens <hca@xxxxxxxxxxxxx> Date: Fri, 1 Sep 2023 22:05:17 +0200 > On Thu, Jun 08, 2023 at 10:26:25PM +0200, Alexander Mikhalitsyn wrote: > > Implement SCM_PIDFD, a new type of CMSG type analogical to SCM_CREDENTIALS, > > but it contains pidfd instead of plain pid, which allows programmers not > > to care about PID reuse problem. > > > > We mask SO_PASSPIDFD feature if CONFIG_UNIX is not builtin because > > it depends on a pidfd_prepare() API which is not exported to the kernel > > modules. > > > > Idea comes from UAPI kernel group: > > https://uapi-group.org/kernel-features/ > > > > Big thanks to Christian Brauner and Lennart Poettering for productive > > discussions about this. > > > > Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> > > Cc: Eric Dumazet <edumazet@xxxxxxxxxx> > > Cc: Jakub Kicinski <kuba@xxxxxxxxxx> > > Cc: Paolo Abeni <pabeni@xxxxxxxxxx> > > Cc: Leon Romanovsky <leon@xxxxxxxxxx> > > Cc: David Ahern <dsahern@xxxxxxxxxx> > > Cc: Arnd Bergmann <arnd@xxxxxxxx> > > Cc: Kees Cook <keescook@xxxxxxxxxxxx> > > Cc: Christian Brauner <brauner@xxxxxxxxxx> > > Cc: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> > > Cc: Lennart Poettering <mzxreary@xxxxxxxxxxx> > > Cc: Luca Boccassi <bluca@xxxxxxxxxx> > > Cc: linux-kernel@xxxxxxxxxxxxxxx > > Cc: netdev@xxxxxxxxxxxxxxx > > Cc: linux-arch@xxxxxxxxxxxxxxx > > Tested-by: Luca Boccassi <bluca@xxxxxxxxxx> > > Reviewed-by: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> > > Reviewed-by: Christian Brauner <brauner@xxxxxxxxxx> > > Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@xxxxxxxxxxxxx> > > --- > > arch/alpha/include/uapi/asm/socket.h | 2 ++ > > arch/mips/include/uapi/asm/socket.h | 2 ++ > > arch/parisc/include/uapi/asm/socket.h | 2 ++ > > arch/sparc/include/uapi/asm/socket.h | 2 ++ > > include/linux/net.h | 1 + > > include/linux/socket.h | 1 + > > include/net/scm.h | 39 +++++++++++++++++++++++-- > > include/uapi/asm-generic/socket.h | 2 ++ > > net/core/sock.c | 11 +++++++ > > net/mptcp/sockopt.c | 1 + > > net/unix/af_unix.c | 18 ++++++++---- > > tools/include/uapi/asm-generic/socket.h | 2 ++ > > 12 files changed, 76 insertions(+), 7 deletions(-) > ... > > +static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm) > > +{ > > + struct file *pidfd_file = NULL; > > + int pidfd; > > + > > + /* > > + * put_cmsg() doesn't return an error if CMSG is truncated, > > + * that's why we need to opencode these checks here. > > + */ > > + if ((msg->msg_controllen <= sizeof(struct cmsghdr)) || > > + (msg->msg_controllen - sizeof(struct cmsghdr)) < sizeof(int)) { > > + msg->msg_flags |= MSG_CTRUNC; > > + return; > > + } > > This does not work for compat tasks since the size of struct cmsghdr (aka > struct compat_cmsghdr) is differently. If the check from put_cmsg() is > open-coded here, then also a different check for compat tasks needs to be > added. > > Discovered this because I was wondering why strace compat tests fail; it > seems because of this. > > See https://github.com/strace/strace/blob/master/tests/scm_pidfd.c > > For compat tasks recvmsg() returns with msg_flags=MSG_CTRUNC since the > above code expects a larger buffer than is necessary. Can you test this ? ---8<--- diff --git a/include/net/scm.h b/include/net/scm.h index c5bcdf65f55c..099497ce4aee 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -9,6 +9,7 @@ #include <linux/pid.h> #include <linux/nsproxy.h> #include <linux/sched/signal.h> +#include <net/compat.h> /* Well, we should have at least one descriptor open * to accept passed FDs 8) @@ -125,14 +126,19 @@ static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm struct file *pidfd_file = NULL; int pidfd; - /* - * put_cmsg() doesn't return an error if CMSG is truncated, + /* put_cmsg() doesn't return an error if CMSG is truncated, * that's why we need to opencode these checks here. */ - if ((msg->msg_controllen <= sizeof(struct cmsghdr)) || - (msg->msg_controllen - sizeof(struct cmsghdr)) < sizeof(int)) { - msg->msg_flags |= MSG_CTRUNC; - return; + if (msg->msg_flags & MSG_CMSG_COMPAT) { + if (msg->msg_controllen < sizeof(struct compat_cmsghdr) + sizeof(int)) { + msg->msg_flags |= MSG_CTRUNC; + return; + } + } else { + if (msg->msg_controllen < sizeof(struct cmsghdr) + sizeof(int)) { + msg->msg_flags |= MSG_CTRUNC; + return; + } } if (!scm->pid) ---8<---