scm: Move scm_recv() from scm.h to scm.c.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Mon, 19 May 2025 20:57:54 +0000 (13:57 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 May 2025 09:24:18 +0000 (10:24 +0100)
scm_recv() has been placed in scm.h since the pre-git era for no
particular reason (I think), which makes the file really fragile.

For example, when you move SOCK_PASSCRED from include/linux/net.h to
enum sock_flags in include/net/sock.h, you will see weird build failure
due to terrible dependency.

To avoid the build failure in the future, let's move scm_recv(_unix())?
and its callees to scm.c.

Note that only scm_recv() needs to be exported for Bluetooth.

scm_send() should be moved to scm.c too, but I'll revisit later.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/scm.h
net/core/scm.c

index 22bb49589fde54b94492a870c03024a95b6c2f11..84c4707e78a56554bff1b6839a830e8b36c0168e 100644 (file)
@@ -102,123 +102,10 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
        return __scm_send(sock, msg, scm);
 }
 
-#ifdef CONFIG_SECURITY_NETWORK
-static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
-{
-       struct lsm_context ctx;
-       int err;
-
-       if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-               err = security_secid_to_secctx(scm->secid, &ctx);
-
-               if (err >= 0) {
-                       put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
-                                ctx.context);
-                       security_release_secctx(&ctx);
-               }
-       }
-}
-
-static inline bool scm_has_secdata(struct socket *sock)
-{
-       return test_bit(SOCK_PASSSEC, &sock->flags);
-}
-#else
-static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
-{ }
-
-static inline bool scm_has_secdata(struct socket *sock)
-{
-       return false;
-}
-#endif /* CONFIG_SECURITY_NETWORK */
-
-static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
-{
-       struct file *pidfd_file = NULL;
-       int len, 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_flags & MSG_CMSG_COMPAT)
-               len = sizeof(struct compat_cmsghdr) + sizeof(int);
-       else
-               len = sizeof(struct cmsghdr) + sizeof(int);
-
-       if (msg->msg_controllen < len) {
-               msg->msg_flags |= MSG_CTRUNC;
-               return;
-       }
-
-       if (!scm->pid)
-               return;
-
-       pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
-
-       if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
-               if (pidfd_file) {
-                       put_unused_fd(pidfd);
-                       fput(pidfd_file);
-               }
-
-               return;
-       }
-
-       if (pidfd_file)
-               fd_install(pidfd, pidfd_file);
-}
-
-static inline bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
-                                    struct scm_cookie *scm, int flags)
-{
-       if (!msg->msg_control) {
-               if (test_bit(SOCK_PASSCRED, &sock->flags) ||
-                   test_bit(SOCK_PASSPIDFD, &sock->flags) ||
-                   scm->fp || scm_has_secdata(sock))
-                       msg->msg_flags |= MSG_CTRUNC;
-               scm_destroy(scm);
-               return false;
-       }
-
-       if (test_bit(SOCK_PASSCRED, &sock->flags)) {
-               struct user_namespace *current_ns = current_user_ns();
-               struct ucred ucreds = {
-                       .pid = scm->creds.pid,
-                       .uid = from_kuid_munged(current_ns, scm->creds.uid),
-                       .gid = from_kgid_munged(current_ns, scm->creds.gid),
-               };
-               put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
-       }
-
-       scm_passec(sock, msg, scm);
-
-       if (scm->fp)
-               scm_detach_fds(msg, scm);
-
-       return true;
-}
-
-static inline void scm_recv(struct socket *sock, struct msghdr *msg,
-                           struct scm_cookie *scm, int flags)
-{
-       if (!__scm_recv_common(sock, msg, scm, flags))
-               return;
-
-       scm_destroy_cred(scm);
-}
-
-static inline void scm_recv_unix(struct socket *sock, struct msghdr *msg,
-                                struct scm_cookie *scm, int flags)
-{
-       if (!__scm_recv_common(sock, msg, scm, flags))
-               return;
-
-       if (test_bit(SOCK_PASSPIDFD, &sock->flags))
-               scm_pidfd_recv(msg, scm);
-
-       scm_destroy_cred(scm);
-}
+void scm_recv(struct socket *sock, struct msghdr *msg,
+             struct scm_cookie *scm, int flags);
+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)
index 733c0cbd393d241b530aadc292de84af25225122..66e02b18c3591514f986e339184e5b5490376b65 100644 (file)
@@ -404,3 +404,126 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
        return new_fpl;
 }
 EXPORT_SYMBOL(scm_fp_dup);
+
+#ifdef CONFIG_SECURITY_NETWORK
+static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{
+       struct lsm_context ctx;
+       int err;
+
+       if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+               err = security_secid_to_secctx(scm->secid, &ctx);
+
+               if (err >= 0) {
+                       put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
+                                ctx.context);
+
+                       security_release_secctx(&ctx);
+               }
+       }
+}
+
+static bool scm_has_secdata(struct socket *sock)
+{
+       return test_bit(SOCK_PASSSEC, &sock->flags);
+}
+#else
+static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{
+}
+
+static bool scm_has_secdata(struct socket *sock)
+{
+       return false;
+}
+#endif
+
+static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
+{
+       struct file *pidfd_file = NULL;
+       int len, 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_flags & MSG_CMSG_COMPAT)
+               len = sizeof(struct compat_cmsghdr) + sizeof(int);
+       else
+               len = sizeof(struct cmsghdr) + sizeof(int);
+
+       if (msg->msg_controllen < len) {
+               msg->msg_flags |= MSG_CTRUNC;
+               return;
+       }
+
+       if (!scm->pid)
+               return;
+
+       pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
+
+       if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
+               if (pidfd_file) {
+                       put_unused_fd(pidfd);
+                       fput(pidfd_file);
+               }
+
+               return;
+       }
+
+       if (pidfd_file)
+               fd_install(pidfd, pidfd_file);
+}
+
+static bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
+                             struct scm_cookie *scm, int flags)
+{
+       if (!msg->msg_control) {
+               if (test_bit(SOCK_PASSCRED, &sock->flags) ||
+                   test_bit(SOCK_PASSPIDFD, &sock->flags) ||
+                   scm->fp || scm_has_secdata(sock))
+                       msg->msg_flags |= MSG_CTRUNC;
+
+               scm_destroy(scm);
+               return false;
+       }
+
+       if (test_bit(SOCK_PASSCRED, &sock->flags)) {
+               struct user_namespace *current_ns = current_user_ns();
+               struct ucred ucreds = {
+                       .pid = scm->creds.pid,
+                       .uid = from_kuid_munged(current_ns, scm->creds.uid),
+                       .gid = from_kgid_munged(current_ns, scm->creds.gid),
+               };
+
+               put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
+       }
+
+       scm_passec(sock, msg, scm);
+
+       if (scm->fp)
+               scm_detach_fds(msg, scm);
+
+       return true;
+}
+
+void scm_recv(struct socket *sock, struct msghdr *msg,
+             struct scm_cookie *scm, int flags)
+{
+       if (!__scm_recv_common(sock, msg, scm, flags))
+               return;
+
+       scm_destroy_cred(scm);
+}
+EXPORT_SYMBOL(scm_recv);
+
+void scm_recv_unix(struct socket *sock, struct msghdr *msg,
+                  struct scm_cookie *scm, int flags)
+{
+       if (!__scm_recv_common(sock, msg, scm, flags))
+               return;
+
+       if (test_bit(SOCK_PASSPIDFD, &sock->flags))
+               scm_pidfd_recv(msg, scm);
+
+       scm_destroy_cred(scm);
+}