From: Tristan Madani <tristmd@gmail.com>
To: Paul Moore <paul@paul-moore.com>,
Stephen Smalley <stephen.smalley.work@gmail.com>
Cc: Ondrej Mosnacek <omosnace@redhat.com>,
Richard Haines <richard_c_haines@btinternet.com>,
selinux@vger.kernel.org, stable@vger.kernel.org,
Tristan Madani <tristan@talencesecurity.com>
Subject: [PATCH v2] selinux: use socket SID for SCTP ASCONF permission checks
Date: Sun, 30 Aug 2026 20:11:57 +0000 [thread overview]
Message-ID: <20260830201157.2084730-1-tristmd@gmail.com> (raw)
From: Tristan Madani <tristan@talencesecurity.com>
__selinux_socket_bind() and selinux_socket_connect_helper() call
sock_has_perm() which uses current_sid() as the AVC subject. When
selinux_sctp_bind_connect() is invoked from the ASCONF processing
path (sctp_process_asconf), current refers to whichever task was
interrupted, so the permission check evaluates an unrelated subject.
Fix by extracting the sock_has_perm() call out of
__selinux_socket_bind() and selinux_socket_connect_helper() into
their callers. The process-context wrappers (selinux_socket_bind,
selinux_socket_connect) call sock_has_perm() directly.
For selinux_sctp_bind_connect(), determine the caller SID based on
the optname: SCTP_PARAM_SET_PRIMARY and SCTP_PARAM_ADD_IP are ASCONF
chunk parameter types only passed from the softirq processing path,
so use the socket own SID (sksec->sid), consistent with other
softirq-context hooks such as selinux_socket_sock_rcv_skb() and
selinux_sctp_assoc_request(). All other optnames originate from
process-context syscalls and use current_sid().
Factor out __sock_has_perm() with an explicit subject SID parameter
so that sock_has_perm() remains unchanged for all other callers.
Fixes: d452930fd3b9 ("selinux: Add SCTP support")
Cc: stable@vger.kernel.org
Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
Changes in v2:
- Do not use sksec->sid unconditionally; determine the caller SID
based on the optname so that process-context callers (bind, connect,
connectx, sendmsg) still use current_sid() [Paul Moore, Sashiko]
- Factor out __sock_has_perm() with an explicit SID parameter and keep
sock_has_perm() as a thin wrapper for all other callers
- Move the sock_has_perm() call out of __selinux_socket_bind() and
selinux_socket_connect_helper() into their respective callers
(selinux_socket_bind, selinux_socket_connect, selinux_sctp_bind_connect)
security/selinux/hooks.c | 47 ++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 12 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 035aaf113d1da..ab9653ae06fc8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4918,7 +4918,7 @@ static bool sock_skip_has_perm(u32 sid)
}
-static int sock_has_perm(struct sock *sk, u32 perms)
+static int __sock_has_perm(struct sock *sk, u32 sid, u32 perms)
{
struct sk_security_struct *sksec = selinux_sock(sk);
struct common_audit_data ad;
@@ -4929,10 +4929,15 @@ static int sock_has_perm(struct sock *sk, u32 perms)
ad_net_init_from_sk(&ad, &net, sk);
- return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
+ return avc_has_perm(sid, sksec->sid, sksec->sclass, perms,
&ad);
}
+static int sock_has_perm(struct sock *sk, u32 perms)
+{
+ return __sock_has_perm(sk, current_sid(), perms);
+}
+
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
@@ -5006,11 +5011,7 @@ static int __selinux_socket_bind(struct sock *sk, struct sockaddr *address, int
{
struct sk_security_struct *sksec = selinux_sock(sk);
u16 family;
- int err;
-
- err = sock_has_perm(sk, SOCKET__BIND);
- if (err)
- goto out;
+ int err = 0;
/* If PF_INET or PF_INET6, check name_bind permission for the port. */
family = sk->sk_family;
@@ -5135,6 +5136,11 @@ static int __selinux_socket_bind(struct sock *sk, struct sockaddr *address, int
static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
+ int err;
+
+ err = sock_has_perm(sock->sk, SOCKET__BIND);
+ if (err)
+ return err;
return __selinux_socket_bind(sock->sk, address, addrlen);
}
@@ -5145,11 +5151,8 @@ static int selinux_socket_connect_helper(struct sock *sk,
struct sockaddr *address, int addrlen)
{
struct sk_security_struct *sksec = selinux_sock(sk);
- int err;
+ int err = 0;
- err = sock_has_perm(sk, SOCKET__CONNECT);
- if (err)
- return err;
if (addrlen < offsetofend(struct sockaddr, sa_family))
return -EINVAL;
@@ -5232,6 +5235,9 @@ static int selinux_socket_connect(struct socket *sock,
int err;
struct sock *sk = sock->sk;
+ err = sock_has_perm(sk, SOCKET__CONNECT);
+ if (err)
+ return err;
err = selinux_socket_connect_helper(sk, address, addrlen);
if (err)
return err;
@@ -5731,13 +5737,25 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
struct sockaddr *address,
int addrlen)
{
+ struct sk_security_struct *sksec = selinux_sock(sk);
int len, err = 0, walk_size = 0;
void *addr_buf;
struct sockaddr *addr;
+ u32 caller_sid;
if (!selinux_policycap_extsockclass())
return 0;
+ /* SCTP_PARAM_SET_PRIMARY and SCTP_PARAM_ADD_IP are ASCONF chunk
+ * parameter types passed from sctp_process_asconf() in softirq
+ * context where current is not meaningful. Use the socket own
+ * SID for permission checks in that case; all other optnames
+ * originate from process-context syscalls.
+ */
+ caller_sid = (optname == SCTP_PARAM_SET_PRIMARY ||
+ optname == SCTP_PARAM_ADD_IP) ?
+ sksec->sid : current_sid();
+
/* Process one or more addresses that may be IPv4 or IPv6 */
addr_buf = address;
@@ -5767,13 +5785,18 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
case SCTP_PRIMARY_ADDR:
case SCTP_SET_PEER_PRIMARY_ADDR:
case SCTP_SOCKOPT_BINDX_ADD:
- err = __selinux_socket_bind(sk, addr, len);
+ err = __sock_has_perm(sk, caller_sid, SOCKET__BIND);
+ if (!err)
+ err = __selinux_socket_bind(sk, addr, len);
break;
/* Connect checks */
case SCTP_SOCKOPT_CONNECTX:
case SCTP_PARAM_SET_PRIMARY:
case SCTP_PARAM_ADD_IP:
case SCTP_SENDMSG_CONNECT:
+ err = __sock_has_perm(sk, caller_sid, SOCKET__CONNECT);
+ if (err)
+ return err;
err = selinux_socket_connect_helper(sk, addr, len);
if (err)
return err;
--
2.47.3
next reply other threads:[~2026-08-30 20:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 20:11 Tristan Madani [this message]
2026-08-30 20:18 ` [PATCH v2] selinux: use socket SID for SCTP ASCONF permission checks sashiko-bot
2026-08-31 13:43 ` Stephen Smalley
2026-09-03 2:24 ` Paul Moore
2026-09-03 12:32 ` Stephen Smalley
2026-09-03 15:47 ` Paul Moore
2026-09-04 12:11 ` Stephen Smalley
2026-09-04 15:26 ` Paul Moore
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=20260830201157.2084730-1-tristmd@gmail.com \
--to=tristmd@gmail.com \
--cc=omosnace@redhat.com \
--cc=paul@paul-moore.com \
--cc=richard_c_haines@btinternet.com \
--cc=selinux@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=stephen.smalley.work@gmail.com \
--cc=tristan@talencesecurity.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox