From: Kuniyuki Iwashima <kuniyu@amazon.com>
To: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Willem de Bruijn <willemb@google.com>
Cc: Simon Horman <horms@kernel.org>,
Christian Brauner <brauner@kernel.org>,
Kuniyuki Iwashima <kuniyu@amazon.com>,
Kuniyuki Iwashima <kuni1840@gmail.com>, <netdev@vger.kernel.org>
Subject: [PATCH v2 net-next 6/9] af_unix: Move SOCK_PASS{CRED,PIDFD,SEC} to struct sock.
Date: Fri, 9 May 2025 18:56:29 -0700 [thread overview]
Message-ID: <20250510015652.9931-7-kuniyu@amazon.com> (raw)
In-Reply-To: <20250510015652.9931-1-kuniyu@amazon.com>
As explained in the next patch, SO_PASSRIGHTS would have a problem
if we assigned a corresponding bit to socket->flags, so it must be
managed in struct sock.
Mixing socket->flags and sk->sk_flags for similar options will look
confusing, and sk->sk_flags does not have enough space on 32bit system.
Also, as mentioned in commit 16e572626961 ("af_unix: dont send
SCM_CREDENTIALS by default"), SOCK_PASSCRED and SOCK_PASSPID handling
is known to be slow, and managing the flags in struct socket cannot
avoid that for embryo sockets.
Let's move SOCK_PASS{CRED,PIDFD,SEC} to struct sock.
While at it, other SOCK_XXX flags in net.h are grouped as enum.
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
include/linux/net.h | 15 +++++++--------
include/net/sock.h | 13 ++++++++++++-
net/core/scm.c | 29 ++++++++++++++---------------
net/core/sock.c | 12 ++++++------
net/unix/af_unix.c | 18 ++----------------
5 files changed, 41 insertions(+), 46 deletions(-)
diff --git a/include/linux/net.h b/include/linux/net.h
index 0ff950eecc6b..f8418d6e33e0 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -36,14 +36,13 @@ struct net;
* in sock->flags, but moved into sk->sk_wq->flags to be RCU protected.
* Eventually all flags will be in sk->sk_wq->flags.
*/
-#define SOCKWQ_ASYNC_NOSPACE 0
-#define SOCKWQ_ASYNC_WAITDATA 1
-#define SOCK_NOSPACE 2
-#define SOCK_PASSCRED 3
-#define SOCK_PASSSEC 4
-#define SOCK_SUPPORT_ZC 5
-#define SOCK_CUSTOM_SOCKOPT 6
-#define SOCK_PASSPIDFD 7
+enum socket_flags {
+ SOCKWQ_ASYNC_NOSPACE,
+ SOCKWQ_ASYNC_WAITDATA,
+ SOCK_NOSPACE,
+ SOCK_SUPPORT_ZC,
+ SOCK_CUSTOM_SOCKOPT,
+};
#ifndef ARCH_HAS_SOCKET_TYPES
/**
diff --git a/include/net/sock.h b/include/net/sock.h
index af0719ba331f..036ed7d394ba 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -337,6 +337,10 @@ struct sk_filter;
* @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME
* @sk_txtime_report_errors: set report errors mode for SO_TXTIME
* @sk_txtime_unused: unused txtime flags
+ * @sk_scm_recv_flags: All flags used by scm_recv()
+ * @sk_scm_credentials: flagged by SO_PASSCRED to recv SCM_CREDENTIALS
+ * @sk_scm_security: flagged by SO_PASSSEC to recv SCM_SECURITY
+ * @sk_scm_pidfd: flagged by SO_PASSPIDFD to recv SCM_PIDFD
* @ns_tracker: tracker for netns reference
* @sk_user_frags: xarray of pages the user is holding a reference on.
* @sk_owner: reference to the real owner of the socket that calls
@@ -523,7 +527,14 @@ struct sock {
#endif
int sk_disconnects;
- u8 sk_txrehash;
+ union {
+ u8 sk_txrehash;
+ u8 sk_scm_recv_flags;
+ u8 sk_scm_credentials : 1,
+ sk_scm_security : 1,
+ sk_scm_pidfd : 1,
+ sk_scm_unused : 5;
+ };
u8 sk_clockid;
u8 sk_txtime_deadline_mode : 1,
sk_txtime_report_errors : 1,
diff --git a/net/core/scm.c b/net/core/scm.c
index 3f756f00e41e..ffc0b917b4e7 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -406,12 +406,12 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
EXPORT_SYMBOL(scm_fp_dup);
#ifdef CONFIG_SECURITY_NETWORK
-static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+static void scm_passec(struct sock *sk, struct msghdr *msg, struct scm_cookie *scm)
{
struct lsm_context ctx;
int err;
- if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+ if (sk->sk_scm_security) {
err = security_secid_to_secctx(scm->secid, &ctx);
if (err >= 0) {
@@ -423,15 +423,15 @@ static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cooki
}
}
-static bool scm_has_secdata(struct socket *sock)
+static bool scm_has_secdata(struct sock *sk)
{
- return test_bit(SOCK_PASSSEC, &sock->flags);
+ return sk->sk_scm_security;
}
#else
-static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+static inline void scm_passec(struct sock *sk, struct msghdr *msg, struct scm_cookie *scm)
{ }
-static inline bool scm_has_secdata(struct socket *sock)
+static inline bool scm_has_secdata(struct sock *sk)
{
return false;
}
@@ -473,20 +473,19 @@ static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
fd_install(pidfd, pidfd_file);
}
-static bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
+static bool __scm_recv_common(struct sock *sk, 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))
+ if (sk->sk_scm_credentials || sk->sk_scm_pidfd ||
+ scm->fp || scm_has_secdata(sk))
msg->msg_flags |= MSG_CTRUNC;
scm_destroy(scm);
return false;
}
- if (test_bit(SOCK_PASSCRED, &sock->flags)) {
+ if (sk->sk_scm_credentials) {
struct user_namespace *current_ns = current_user_ns();
struct ucred ucreds = {
.pid = scm->creds.pid,
@@ -497,7 +496,7 @@ static bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
}
- scm_passec(sock, msg, scm);
+ scm_passec(sk, msg, scm);
if (scm->fp)
scm_detach_fds(msg, scm);
@@ -508,7 +507,7 @@ static bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
void scm_recv(struct socket *sock, struct msghdr *msg,
struct scm_cookie *scm, int flags)
{
- if (!__scm_recv_common(sock, msg, scm, flags))
+ if (!__scm_recv_common(sock->sk, msg, scm, flags))
return;
scm_destroy_cred(scm);
@@ -518,10 +517,10 @@ 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))
+ if (!__scm_recv_common(sock->sk, msg, scm, flags))
return;
- if (test_bit(SOCK_PASSPIDFD, &sock->flags))
+ if (sock->sk->sk_scm_pidfd)
scm_pidfd_recv(msg, scm);
scm_destroy_cred(scm);
diff --git a/net/core/sock.c b/net/core/sock.c
index 1ab59efbafc5..9540cbe3d83e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1224,19 +1224,19 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
if (!sk_may_scm_recv(sk))
return -EOPNOTSUPP;
- assign_bit(SOCK_PASSSEC, &sock->flags, valbool);
+ sk->sk_scm_security = valbool;
return 0;
case SO_PASSCRED:
if (!sk_may_scm_recv(sk))
return -EOPNOTSUPP;
- assign_bit(SOCK_PASSCRED, &sock->flags, valbool);
+ sk->sk_scm_credentials = valbool;
return 0;
case SO_PASSPIDFD:
if (!sk_is_unix(sk))
return -EOPNOTSUPP;
- assign_bit(SOCK_PASSPIDFD, &sock->flags, valbool);
+ sk->sk_scm_pidfd = valbool;
return 0;
case SO_TYPE:
case SO_PROTOCOL:
@@ -1865,14 +1865,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
case SO_PASSCRED:
if (sk_may_scm_recv(sk))
- v.val = !!test_bit(SOCK_PASSCRED, &sock->flags);
+ v.val = sk->sk_scm_credentials;
else
v.val = 0;
break;
case SO_PASSPIDFD:
if (sk_is_unix(sk))
- v.val = !!test_bit(SOCK_PASSPIDFD, &sock->flags);
+ v.val = sk->sk_scm_pidfd;
else
v.val = 0;
break;
@@ -1972,7 +1972,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
case SO_PASSSEC:
if (sk_may_scm_recv(sk))
- v.val = !!test_bit(SOCK_PASSSEC, &sock->flags);
+ v.val = sk->sk_scm_security;
else
v.val = 0;
break;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index a39497fd6e98..83436297b0b3 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -767,10 +767,7 @@ static void copy_peercred(struct sock *sk, struct sock *peersk)
static bool unix_may_passcred(const struct sock *sk)
{
- struct socket *sock = sk->sk_socket;
-
- return test_bit(SOCK_PASSCRED, &sock->flags) ||
- test_bit(SOCK_PASSPIDFD, &sock->flags);
+ return sk->sk_scm_credentials || sk->sk_scm_pidfd;
}
static int unix_listen(struct socket *sock, int backlog)
@@ -1713,17 +1710,6 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
return 0;
}
-static void unix_sock_inherit_flags(const struct socket *old,
- struct socket *new)
-{
- if (test_bit(SOCK_PASSCRED, &old->flags))
- set_bit(SOCK_PASSCRED, &new->flags);
- if (test_bit(SOCK_PASSPIDFD, &old->flags))
- set_bit(SOCK_PASSPIDFD, &new->flags);
- if (test_bit(SOCK_PASSSEC, &old->flags))
- set_bit(SOCK_PASSSEC, &new->flags);
-}
-
static int unix_accept(struct socket *sock, struct socket *newsock,
struct proto_accept_arg *arg)
{
@@ -1760,7 +1746,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock,
unix_state_lock(tsk);
unix_update_edges(unix_sk(tsk));
newsock->state = SS_CONNECTED;
- unix_sock_inherit_flags(sock, newsock);
+ tsk->sk_scm_recv_flags = sk->sk_scm_recv_flags;
sock_graft(tsk, newsock);
unix_state_unlock(tsk);
return 0;
--
2.49.0
next prev parent reply other threads:[~2025-05-10 1:59 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-10 1:56 [PATCH v2 net-next 0/9] af_unix: Introduce SO_PASSRIGHTS Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 1/9] af_unix: Factorise test_bit() for SOCK_PASSCRED and SOCK_PASSPIDFD Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 2/9] af_unix: Don't pass struct socket to maybe_add_creds() Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 3/9] scm: Move scm_recv() from scm.h to scm.c Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 4/9] tcp: Restrict SO_TXREHASH to TCP socket Kuniyuki Iwashima
2025-05-12 19:18 ` Willem de Bruijn
2025-05-12 22:14 ` Kuniyuki Iwashima
2025-05-13 2:42 ` Willem de Bruijn
2025-05-13 3:11 ` Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 5/9] net: Restrict SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH} Kuniyuki Iwashima
2025-05-10 1:56 ` Kuniyuki Iwashima [this message]
2025-05-12 19:20 ` [PATCH v2 net-next 6/9] af_unix: Move SOCK_PASS{CRED,PIDFD,SEC} to struct sock Willem de Bruijn
2025-05-12 22:20 ` Kuniyuki Iwashima
2025-05-13 2:44 ` Willem de Bruijn
2025-05-13 3:18 ` Kuniyuki Iwashima
2025-05-13 2:03 ` kernel test robot
2025-05-10 1:56 ` [PATCH v2 net-next 7/9] af_unix: Inherit sk_flags at connect() Kuniyuki Iwashima
2025-05-12 19:38 ` Willem de Bruijn
2025-05-12 22:34 ` Kuniyuki Iwashima
2025-05-13 2:48 ` Willem de Bruijn
2025-05-13 3:20 ` Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 8/9] af_unix: Introduce SO_PASSRIGHTS Kuniyuki Iwashima
2025-05-10 1:56 ` [PATCH v2 net-next 9/9] selftest: af_unix: Test SO_PASSRIGHTS Kuniyuki Iwashima
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250510015652.9931-7-kuniyu@amazon.com \
--to=kuniyu@amazon.com \
--cc=brauner@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=kuni1840@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=willemb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.