summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-08-17 18:15:01 -0700
committerJakub Kicinski <kuba@kernel.org>2026-08-17 18:15:01 -0700
commitf461b94f1a1bf389dc6b893e194f66ecc86cb20a (patch)
treebca616d4c221e53f531775be5bbe228bae8dd4ce /include
parent768af217217bf147429fde629f8d8eedeba49072 (diff)
parent5d513ce19de963c7e36904c98d7b02ecd16a30a1 (diff)
Merge branch 'net-af_unix-useful-handling-of-lsm-denials-on-scm_rights'
Jori Koolstra says: ==================== net: af_unix: useful handling of LSM denials on SCM_RIGHTS Right now if some LSM denies an AF_UNIX socket peer to receive a SCM_RIGHTS fd, the SCM_RIGHTS fd array will be cut short at that point, and MSG_CTRUNC is set on return of recvmsg(2). This is highly problematic behaviour, because it leaves the receiver wondering what happened. As per man page MSG_CTRUNC is supposed to indicate that the control buffer was sized too short, but suddenly a permission error might result in the exact same flag being set. Moreover, the receiver has no chance to determine how many fds got originally sent and how many were suppressed.[1] Add a SO_RIGHTS_NOTRUNC option to UNIX sockets to enable more useful handling of LSM denials when receiving SCM_RIGHTS messages: instead of truncating the message at the first blocked fd, keep every fd slot and store the LSM errno in the blocked slot. This option is inherited by the accept()-ed socket when set on the listen() socket. [1]: https://github.com/uapi-group/kernel-features#useful-handling-of-lsm-denials-on-scm_rights ==================== Link: https://patch.msgid.link/20260813162818.149248-1-jkoolstra@xs4all.nl Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/net/af_unix.h1
-rw-r--r--include/net/scm.h13
-rw-r--r--include/uapi/asm-generic/socket.h2
3 files changed, 7 insertions, 9 deletions
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 34f53dde65ce..bb1b3dee02e8 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -49,6 +49,7 @@ struct unix_sock {
struct scm_stat scm_stat;
int inq_len;
bool recvmsg_inq;
+ bool scm_rights_notrunc;
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
struct sk_buff *oob_skb;
#endif
diff --git a/include/net/scm.h b/include/net/scm.h
index c52519669349..86ae6bc109ec 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -50,8 +50,8 @@ struct scm_cookie {
#endif
};
-void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
-void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
+void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm, bool notrunc);
+void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm, bool notrunc);
int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
void __scm_destroy(struct scm_cookie *scm);
struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);
@@ -107,13 +107,8 @@ void scm_recv(struct socket *sock, struct msghdr *msg,
void scm_recv_unix(struct socket *sock, struct msghdr *msg,
struct scm_cookie *scm, int flags);
-static inline int scm_recv_one_fd(struct file *f, int __user *ufd,
- unsigned int flags)
-{
- if (!ufd)
- return -EFAULT;
- return receive_fd(f, ufd, flags);
-}
+int scm_recv_one_fd(struct file *f, int __user *ufd, unsigned int flags,
+ bool notrunc);
#endif /* __LINUX_NET_SCM_H */
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 53b5a8c002b1..84ea7b92936e 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -150,6 +150,8 @@
#define SO_INQ 84
#define SCM_INQ SO_INQ
+#define SO_RIGHTS_NOTRUNC 85
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))