* [PATCH 0/7] unix.7: Socket Options and SCM_* fixes
@ 2026-10-21 21:22 Günther Noack
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
` (6 more replies)
0 siblings, 7 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar; +Cc: linux-man, Günther Noack, Kuniyuki Iwashima
Hello!
This is patch set (B) spun off from the "Documentation fixes in
unix(7)" patch set [1], which is now split into these three parts:
(A) Miscellaneous fixes, mostly in unix.7, one in socket.7
(B) Socket options and Socket-level Control Messages (SCM_*) <-- this one
(C) sock_diag.7
This patch set fixes unix(7) documentation related to socket options
and SCM_* control messages. The first 5 commits are fixes and factual
corrections, the last two commits are documenting two relevant new
features (PIDFD passing and SO_PASSRIGHTS).
The patch set is based on the "miscellaneous" patch set (A) ("General
Unix Domain Socket fixes"), since it is touching some error code
documentation in the same corner as what is getting changed in (A).
Thank you for your reviews on v1 and v2 of the still-joined patch set.
Compared to v2, the following things happened:
* Some commit message rewording (especially quoted the kernel code
more directly).
* I removed the commit that changed the wording about Out-of-Band
messaging, per Kuniyuki's suggestion in [2].
* The ETOOMANYREFS commit is a SCM_RIGHTS-specific error; the Autobind
documentation change is included here because it refers to
SO_PASSPIDFD.
* I am not 100% happy with how verbose the SCM_SECURITY change has
become, but I don't see a good way to shorten it without cutting
away from the substance.
More details are attached in the commit notes.
This patch set has been produced with the help of a LLM, which was
helpful for spotting a long list of inaccuracies, comparing the
documentation with the kernel implementation. (More details in [1])
–Günther
P.S.: Part (C) will come soon, but not today any more. :)
That part is more independent again and, being about "sock_diag",
it is outside of the main unix(7) documentation.
[1] https://lore.kernel.org/all/20261018173712.27670-1-gnoack3000@gmail.com/
[2] https://lore.kernel.org/all/CAAVpQUBh+J-aBLbkpzT7qmt7B714O529HWcTuQsVLT4wLBnDJA@mail.gmail.com/
Günther Noack (7):
man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one
message
man/man7/unix.7: Autobind: Clarify when it happens, and mention
SO_PASSPIDFD
man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just
SELinux
man/man7/unix.7: SO_PASSSEC: wfix
man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
man/man7/unix.7: Document SO_PASSRIGHTS
man/man7/unix.7 | 215 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 201 insertions(+), 14 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-22 21:14 ` Alejandro Colomar
2026-10-24 4:45 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message Günther Noack
` (5 subsequent siblings)
6 siblings, 2 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Michael Kerrisk, Willy Tarreau,
Kuniyuki Iwashima
The ETOOMANYREFS error is detected in too_many_unix_fds() in
net/unix/af_unix.c when the user's (not the processes') in-flight FDs
exceed RLIMIT_NOFILE, and the process has neither CAP_SYS_RESOURCE nor
CAP_SYS_ADMIN. The error is raised when all of the following
(simplified) conditions are true:
* user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)
* !capable(CAP_SYS_RESOURCE)
* !capable(CAP_SYS_ADMIN)
The check was introduced in linux.git 712f4aad406b (2016-01-11; "unix:
properly account for FDs passed over unix sockets").
Fixes: dc4eea68b565 (2016-12-17; "unix.7: Document ETOOMANYREFS for SCM_RIGHTS send exceeding RLIMIT_NOFILE limit")
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
Notes:
Double checked in code -- the condition under which this error is
returned was not fully spelled out.
man/man7/unix.7 | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index 79198445c581..0d2ea8bda2ae 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -785,10 +785,14 @@ when sending a file descriptor as ancillary data over
a UNIX domain socket (see the description of
.BR SCM_RIGHTS ,
above).
-It occurs if the number of "in-flight" file descriptors exceeds the
+It occurs if the number of "in-flight" file descriptors
+sent by processes of the caller's real user ID
+exceeds the caller's
.B RLIMIT_NOFILE
-resource limit and the caller does not have the
+resource limit and the caller has neither the
.B CAP_SYS_RESOURCE
+nor the
+.B CAP_SYS_ADMIN
capability.
An in-flight file descriptor is one that has been sent using
.BR sendmsg (2)
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-22 21:28 ` Alejandro Colomar
2026-10-21 21:22 ` [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD Günther Noack
` (4 subsequent siblings)
6 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Michael Kerrisk, Kuniyuki Iwashima
Verified in Linux kernel code:
__scm_send() in linux.git net/core/scm.c walks all control messages
in a loop like this:
for_each_cmsghdr(cmsg, msg) {
// ...
switch (cmsg->cmsg_type)
{
case SCM_RIGHTS:
// Append(!) file descriptors
// up to the SCM_MAX_FD limit
break;
case SCM_CREDENTIALS:
// Replace previously set credentials
break;
default:
goto error;
}
}
So it is possible to pass multiple SCM_* messages -- they will compose
if possible and override the previous value if not. Since their
contents are being conflated that way, they will appear as one message
again on the receiving side.
Keep the recommendation as portability advice, and describe the Linux
behavior.
Fixes: 5b5cb1958062 (2018-07-10; "unix.7: When sending ancillary data, only one item of each type may be sent")
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
Notes:
The factual analysis in the commit message is correct.
I kept the LLM phrasing; it did not seem overly wordy to me and the
style is in line with the paragraph after it, which also documents
Linux-only vs. portable APIs that way.
man/man7/unix.7 | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index 0d2ea8bda2ae..a1dce8c47246 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -543,7 +543,24 @@ option must be enabled on the socket (see above).
.P
When sending ancillary data with
.BR sendmsg (2),
-only one item of each of the above types may be included in the sent message.
+portable applications should include
+only one item of each of the above types in the sent message.
+On Linux,
+if several
+.B SCM_RIGHTS
+items are included,
+their file descriptors are combined into a single list,
+to which the
+.B SCM_MAX_FD
+limit applies as a whole,
+and the receiver gets them in a single
+.B SCM_RIGHTS
+item;
+if several
+.B SCM_CREDENTIALS
+items are included,
+each of them is checked,
+and the last one takes effect.
.P
At least one byte of real data should be sent when sending ancillary data.
On Linux, this is required to successfully send ancillary data over
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
2026-10-21 21:22 ` [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-24 4:57 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux Günther Noack
` (3 subsequent siblings)
6 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Michael Kerrisk,
Alexander Mikhalitsyn, Kuniyuki Iwashima
Autobind happens if either one of SO_PASSCRED/SO_PASSPIDFD is set and
either connect() or sendmsg() happens. Mention SO_PASSPIDFD and
clarify that autobind does not happen immediately when setting these
socket options.
In linux.git net/unix/af_unix.c, unix_autobind() is called by
unix_dgram_connect(), unix_stream_connect() and unix_dgram_sendmsg(),
if the socket has no address and unix_may_passcred() is true.
unix_may_passcred() is also true when SO_PASSPIDFD is set, which was
added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add SO_PASSPIDFD and
SCM_PIDFD"), Linux 6.5.
Also, the old text said "not yet connected", but the condition is
about the socket not being bound.
Fixes: 9d1fd1157306 (1999-06-15, 2022-12-19; "man-pages 1.24")
Fixes: 0cf2caa41ea6 (2010-10-10; "unix.7: Document the autobind feature")
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
Notes:
Rephrased the LLM-generated text so that the canonical description is
in the "Autobind feature" section and the other place just refers to
it.
SO_PASSPIDFD is unfortunately not documented yet at this point in
time, but it's still correct to mention it here.
man/man7/unix.7 | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index a1dce8c47246..ded82768322b 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -301,8 +301,14 @@ if the sender did not specify
.B SCM_CREDENTIALS
ancillary data.
.IP
-When this option is set and the socket is not yet connected,
-a unique name in the abstract namespace will be generated automatically.
+When this option is set on a socket that is not bound to an address,
+the socket is autobound to a unique name in the abstract namespace
+when
+.BR connect (2)
+or
+.BR sendmsg (2)
+is called on it;
+see "Autobind feature", below.
.IP
The value given as an argument to
.BR setsockopt (2)
@@ -370,10 +376,19 @@ call specifies
as
.IR sizeof(sa_family_t) ,
.\" i.e., sizeof(short)
-or the
+or if
+.BR connect (2)
+or
+.BR sendmsg (2)
+is called on a socket that was
+not explicitly bound to an address
+and that has the
.B SO_PASSCRED
-socket option was specified for a socket that was
-not explicitly bound to an address,
+or
+.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
+.B SO_PASSPIDFD
+(since Linux 6.5)
+socket option enabled,
then the socket is autobound to an abstract address.
The address consists of a null byte
followed by 5 bytes in the character set
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
` (2 preceding siblings ...)
2026-10-21 21:22 ` [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-23 9:57 ` Alejandro Colomar
2026-10-21 21:22 ` [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix Günther Noack
` (2 subsequent siblings)
6 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Michael Kerrisk, Kuniyuki Iwashima
Reword the description of SCM_SECURITY to not be specific to SELinux.
The security context is populated in scm_passec() in linux.git
net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
is currently implemented by SELinux, Smack and AppArmor.
Also clarify the properties of the returned string:
* There is no NAME_MAX limit on the length; SELinux contexts can be
longer than that. If the control buffer is too small, put_cmsg()
truncates the data and sets MSG_CTRUNC.
* Whether the string is null-terminated also depends on the LSM:
SELinux includes the null byte in the length, but smack_to_secctx()
in security/smack/smack_lsm.c uses strlen() and doesn't.
Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
Notes:
This feature is also available in other LSMs. Unfortunately, they
implemented it inconsistently and that complicates the description of
how string boundaries are handled. Linux does indeed neither
guarantee that this terminates with a NUL byte, nor that NAME_MAX is
large enough to hold it.
This is the verbose variant, but I am open for suggestions regarding
what level of detail is appropriate here.
man/man7/unix.7 | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index ded82768322b..4abd216d19c7 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -317,7 +317,7 @@ and returned as the result of
is an integer boolean flag.
.TP
.B SO_PASSSEC
-Enables receiving of the SELinux security label of the peer socket
+Enables receiving of the security label of the peer socket
in an ancillary message of type
.B SCM_SECURITY
(see below).
@@ -544,13 +544,26 @@ message, the
option must be enabled on the socket.
.TP
.B SCM_SECURITY
-Receive the SELinux security context (the security label)
-of the peer socket.
-The received ancillary data is a null-terminated string containing
+Receive the security context (the security label)
+of the peer socket,
+as provided by the active Linux Security Module (LSM),
+such as SELinux or Smack.
+The received ancillary data is a string containing
the security context.
-The receiver should allocate at least
+Whether the string includes a terminating null byte
+depends on the LSM;
+the length of the data is given by the
+.I cmsg_len
+field.
+There is no fixed limit on the length of the security context;
+allocating
.B NAME_MAX
-bytes in the data portion of the ancillary message for this data.
+bytes in the data portion of the ancillary message
+is usually enough.
+If the buffer is too small,
+the data is truncated and the
+.B MSG_CTRUNC
+flag is set (see below).
.IP
To receive the security context, the
.B SO_PASSSEC
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
` (3 preceding siblings ...)
2026-10-21 21:22 ` [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-24 5:02 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD Günther Noack
2026-10-21 21:22 ` [PATCH 7/7] man/man7/unix.7: Document SO_PASSRIGHTS Günther Noack
6 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar; +Cc: linux-man, Günther Noack, Kuniyuki Iwashima
Use "security context", as in the description of SCM_SECURITY.
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
man/man7/unix.7 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index 4abd216d19c7..67dd10cc146f 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -317,7 +317,7 @@ and returned as the result of
is an integer boolean flag.
.TP
.B SO_PASSSEC
-Enables receiving of the security label of the peer socket
+Enables receiving of the security context of the peer socket
in an ancillary message of type
.B SCM_SECURITY
(see below).
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
` (4 preceding siblings ...)
2026-10-21 21:22 ` [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
2026-10-24 5:22 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 7/7] man/man7/unix.7: Document SO_PASSRIGHTS Günther Noack
6 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Alexander Mikhalitsyn,
Christian Brauner, Kuniyuki Iwashima, Eric Dumazet
These were added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add
SO_PASSPIDFD and SCM_PIDFD") and 7b26952a91cf (2023-06-12; "net: core:
add getsockopt SO_PEERPIDFD"), both in Linux 6.5. They are the PID
file descriptor counterparts of SO_PASSCRED/SCM_CREDENTIALS and
SO_PEERCRED.
SO_PASSPIDFD
sk_setsockopt() and sk_getsockopt() in net/core/sock.c handle it
as a boolean flag for AF_UNIX sockets (EOPNOTSUPP otherwise).
Like SO_PASSCRED, it triggers autobind, which was already
mentioned in "Autobind feature".
SCM_PIDFD
scm_pidfd_recv() in net/core/scm.c creates the PID file
descriptor from scm->pid, which is the PID given in the sender's
SCM_CREDENTIALS, or the sender's own PID by default. The fd is
created with O_CLOEXEC by pidfd_prepare(). If pidfd_prepare()
fails, its negative error number is put into the cmsg data.
Sending SCM_PIDFD is rejected by __scm_send() (EINVAL).
Since Linux 6.17, with c679d17d3f2d (2025-07-04; "af_unix:
enable handing out pidfds for reaped tasks in SCM_PIDFD"),
PIDFD_STALE is passed, so this also works for reaped processes.
Before that, pidfd_prepare() returned -EINVAL for them.
SO_PEERPIDFD
sk_getsockopt() returns a PID file descriptor for sk_peer_pid,
or fails with ENODATA if there is none.
Since Linux 6.16, with 20b70e58961b (2025-04-28; "net, pidfs:
enable handing out pidfds for reaped sk->sk_peer_pid"), this also
works for reaped processes on AF_UNIX sockets. Before that, it
failed with EINVAL.
Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Eric Dumazet <edumazet@kernel.org>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
man/man7/unix.7 | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index 67dd10cc146f..a4457508fd2a 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -316,6 +316,33 @@ and returned as the result of
.BR getsockopt (2)
is an integer boolean flag.
.TP
+.BR SO_PASSPIDFD " (since Linux 6.5)"
+.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
+Enabling this socket option causes receipt of a PID file descriptor
+(see
+.BR pidfd_open (2))
+referring to the sending process in an
+.B SCM_PIDFD
+ancillary message in each subsequently received message
+(see below).
+.IP
+As with
+.BR SO_PASSCRED ,
+when this option is set on a socket that is not bound to an address,
+the socket is autobound to a unique name in the abstract namespace
+when
+.BR connect (2)
+or
+.BR sendmsg (2)
+is called on it;
+see "Autobind feature", below.
+.IP
+The value given as an argument to
+.BR setsockopt (2)
+and returned as the result of
+.BR getsockopt (2)
+is an integer boolean flag.
+.TP
.B SO_PASSSEC
Enables receiving of the security context of the peer socket
in an ancillary message of type
@@ -367,6 +394,43 @@ stream and sequenced-packet sockets, and for
.B AF_UNIX
socket pairs created using
.BR socketpair (2).
+.TP
+.BR SO_PEERPIDFD " (since Linux 6.5)"
+.\" commit 7b26952a91cf65ff1cc867a2382a8964d8c0ee7d
+This read-only socket option returns a new PID file descriptor
+(see
+.BR pidfd_open (2))
+referring to the peer process connected to this socket.
+This is the process whose credentials are returned by
+.BR SO_PEERCRED .
+Unlike the PID returned by
+.BR SO_PEERCRED ,
+the PID file descriptor cannot come to refer to a different process
+if the peer process terminates and its PID is reused.
+.IP
+The argument to
+.BR getsockopt (2)
+is a pointer to an
+.IR int ,
+in which the PID file descriptor is returned.
+The close-on-exec flag
+.RB ( FD_CLOEXEC )
+is set on the new file descriptor.
+.IP
+If the socket has no peer process,
+.BR getsockopt (2)
+fails with the error
+.BR ENODATA .
+.IP
+Since Linux 6.16,
+.\" commit 20b70e58961b855e61f2c6a7a19a38a64ad1bed6
+a PID file descriptor is returned
+even if the peer process has already terminated and been reaped.
+Before Linux 6.16,
+.BR getsockopt (2)
+failed with the error
+.B EINVAL
+in this case.
.\"
.SS Autobind feature
If a
@@ -543,6 +607,42 @@ message, the
.B SO_PASSCRED
option must be enabled on the socket.
.TP
+.BR SCM_PIDFD " (since Linux 6.5)"
+.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
+Receive a PID file descriptor
+(see
+.BR pidfd_open (2))
+referring to the sending process.
+The data portion contains a single
+.IR int .
+The PID file descriptor refers to the process whose PID would be
+received in an
+.B SCM_CREDENTIALS
+message;
+if the sender specified
+.B SCM_CREDENTIALS
+ancillary data,
+it refers to the process with the PID given there.
+The close-on-exec flag
+.RB ( FD_CLOEXEC )
+is set on the new file descriptor.
+.IP
+If the PID file descriptor cannot be created,
+the data portion contains a negative error number instead.
+Since Linux 6.17,
+.\" commit c679d17d3f2d895b34e660673141ad250889831f
+a PID file descriptor is created
+even if the sending process has already terminated and been reaped.
+Before Linux 6.17,
+.B \-EINVAL
+was received in this case.
+.IP
+This message cannot be sent;
+it is generated by the kernel.
+To receive it, the
+.B SO_PASSPIDFD
+option must be enabled on the socket.
+.TP
.B SCM_SECURITY
Receive the security context (the security label)
of the peer socket,
@@ -1273,6 +1373,7 @@ see
and
.BR seccomp_unotify (2).
.SH SEE ALSO
+.BR pidfd_open (2),
.BR recvmsg (2),
.BR sendmsg (2),
.BR socket (2),
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 7/7] man/man7/unix.7: Document SO_PASSRIGHTS
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
` (5 preceding siblings ...)
2026-10-21 21:22 ` [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD Günther Noack
@ 2026-10-21 21:22 ` Günther Noack
6 siblings, 0 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-21 21:22 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Günther Noack, Kuniyuki Iwashima,
Willem de Bruijn
SO_PASSRIGHTS was added in linux.git 77cbe1a6d873 (2025-05-23;
"af_unix: Introduce SO_PASSRIGHTS."), in Linux 6.16. It lets a
receiver refuse file descriptors passed with SCM_RIGHTS, so that an
untrusted peer cannot leave it with file descriptors whose final
close() blocks for a long time (for example, a file on a hung NFS
mount or a FUSE-controlled file).
The option is enabled by default (unix_create1()). When the receiving
socket has it disabled, unix_dgram_sendmsg(), unix_stream_sendmsg(),
and queue_oob() fail with EPERM if the message carries file
descriptors. The check happens at send time, so messages that are
already queued are unaffected.
Also add the new EPERM case to ERRORS.
Link: [1] <https://uapi-group.org/kernel-features/#disabling-reception-of-scm_rights-for-af_unix-sockets>
Link: [2] <https://lore.kernel.org/all/20250519205820.66184-1-kuniyu@amazon.com/>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Assisted-by: LLM
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
man/man7/unix.7 | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/man/man7/unix.7 b/man/man7/unix.7
index a4457508fd2a..1aa223b2c79d 100644
--- a/man/man7/unix.7
+++ b/man/man7/unix.7
@@ -343,6 +343,35 @@ and returned as the result of
.BR getsockopt (2)
is an integer boolean flag.
.TP
+.BR SO_PASSRIGHTS " (since Linux 6.16)"
+.\" commit 77cbe1a6d8730a07f99f9263c2d5f2304cf5e830
+This socket option controls whether the socket accepts
+file descriptors from its peers in
+.B SCM_RIGHTS
+ancillary messages (see below).
+It is enabled by default.
+When it is disabled,
+.BR sendmsg (2)
+calls that pass file descriptors to this socket
+fail with the error
+.BR EPERM .
+The option is checked when the message is sent;
+disabling it does not affect messages
+that are already queued on the socket.
+.IP
+Processes that do not expect to receive file descriptors
+can disable this option.
+Once the file descriptors have been passed,
+closing them is the responsibility of the receiving process,
+and this may block for a long time,
+for example for a file on an unresponsive network file system.
+.IP
+The value given as an argument to
+.BR setsockopt (2)
+and returned as the result of
+.BR getsockopt (2)
+is an integer boolean flag.
+.TP
.B SO_PASSSEC
Enables receiving of the security context of the peer socket
in an ancillary message of type
@@ -893,6 +922,14 @@ or
specified a datagram socket as the remote address,
but that socket is connected to a different socket.
.TP
+.B EPERM
+The sender passed file descriptors in an
+.B SCM_RIGHTS
+ancillary message,
+but the receiving socket has the
+.B SO_PASSRIGHTS
+option disabled.
+.TP
.B EPIPE
Remote socket was closed on a stream socket.
If enabled, a
--
2.56.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
@ 2026-10-22 21:14 ` Alejandro Colomar
2026-10-23 16:50 ` Günther Noack
2026-10-24 4:45 ` Kuniyuki Iwashima
1 sibling, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-22 21:14 UTC (permalink / raw)
To: Günther Noack
Cc: linux-man, Michael Kerrisk, Willy Tarreau, Kuniyuki Iwashima
[-- Attachment #1: Type: text/plain, Size: 2582 bytes --]
Hi Günther
> Date: 2026-10-21 23:22:50+0200
> From: Günther Noack <gnoack3000@gmail.com>
>
> The ETOOMANYREFS error is detected in too_many_unix_fds() in
> net/unix/af_unix.c when the user's (not the processes') in-flight FDs
> exceed RLIMIT_NOFILE, and the process has neither CAP_SYS_RESOURCE nor
> CAP_SYS_ADMIN. The error is raised when all of the following
> (simplified) conditions are true:
>
> * user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)
> * !capable(CAP_SYS_RESOURCE)
> * !capable(CAP_SYS_ADMIN)
>
> The check was introduced in linux.git 712f4aad406b (2016-01-11; "unix:
> properly account for FDs passed over unix sockets").
>
> Fixes: dc4eea68b565 (2016-12-17; "unix.7: Document ETOOMANYREFS for SCM_RIGHTS send exceeding RLIMIT_NOFILE limit")
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: Willy Tarreau <w@1wt.eu>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
Reviewed-by: Alejandro Colomar <alx@kernel.org>
>
> Notes:
> Double checked in code -- the condition under which this error is
> returned was not fully spelled out.
>
> man/man7/unix.7 | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index 79198445c581..0d2ea8bda2ae 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -785,10 +785,14 @@ when sending a file descriptor as ancillary data over
Would you mind having a look at CONTRIBUTING.d/git for improving the
hunk context?
git-diff(1), gitattributes(5)
To produce useful hunk contexts in manual pages, we need to hack
git(1)'s idea of a function name, and also to tell git what is a
manual page.
$ git config --global diff.man.xfuncname '^\.S[SHsh] .*$';
$ mkdir -p ~/.config/git/;
$ echo '*.[0-9]* diff=man' >>~/.config/git/attributes;
Cheers,
Alex
> a UNIX domain socket (see the description of
> .BR SCM_RIGHTS ,
> above).
> -It occurs if the number of "in-flight" file descriptors exceeds the
> +It occurs if the number of "in-flight" file descriptors
> +sent by processes of the caller's real user ID
> +exceeds the caller's
> .B RLIMIT_NOFILE
> -resource limit and the caller does not have the
> +resource limit and the caller has neither the
> .B CAP_SYS_RESOURCE
> +nor the
> +.B CAP_SYS_ADMIN
> capability.
> An in-flight file descriptor is one that has been sent using
> .BR sendmsg (2)
> --
> 2.56.0
>
>
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message
2026-10-21 21:22 ` [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message Günther Noack
@ 2026-10-22 21:28 ` Alejandro Colomar
2026-10-23 17:09 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-22 21:28 UTC (permalink / raw)
To: Günther Noack; +Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima
[-- Attachment #1: Type: text/plain, Size: 3319 bytes --]
Hi Günther,
> Date: 2026-10-21 23:22:51+0200
> From: Günther Noack <gnoack3000@gmail.com>
>
> Verified in Linux kernel code:
I think 'verified' in a commit message seems inappropriate. It should
describe, rather than verify, and the verification would come only from
the review tags. Maybe say something like "Relevant kernel code:".
> __scm_send() in linux.git net/core/scm.c walks all control messages
> in a loop like this:
>
> for_each_cmsghdr(cmsg, msg) {
> // ...
> switch (cmsg->cmsg_type)
> {
> case SCM_RIGHTS:
> // Append(!) file descriptors
> // up to the SCM_MAX_FD limit
> break;
> case SCM_CREDENTIALS:
> // Replace previously set credentials
Since these are your comments, and not actual comments in the source
code (are they yours, or from the LLM?), I'd format them clearly as
such using invalid code rather than comments:
... replace previously set credentials ...
> break;
> default:
> goto error;
> }
> }
>
> So it is possible to pass multiple SCM_* messages -- they will compose
> if possible and override the previous value if not. Since their
> contents are being conflated that way, they will appear as one message
> again on the receiving side.
>
> Keep the recommendation as portability advice, and describe the Linux
> behavior.
>
> Fixes: 5b5cb1958062 (2018-07-10; "unix.7: When sending ancillary data, only one item of each type may be sent")
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
>
> Notes:
> The factual analysis in the commit message is correct.
>
> I kept the LLM phrasing; it did not seem overly wordy to me and the
> style is in line with the paragraph after it, which also documents
> Linux-only vs. portable APIs that way.
>
> man/man7/unix.7 | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index 0d2ea8bda2ae..a1dce8c47246 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -543,7 +543,24 @@ option must be enabled on the socket (see above).
> .P
> When sending ancillary data with
> .BR sendmsg (2),
> -only one item of each of the above types may be included in the sent message.
> +portable applications should include
> +only one item of each of the above types in the sent message.
> +On Linux,
> +if several
> +.B SCM_RIGHTS
> +items are included,
> +their file descriptors are combined into a single list,
> +to which the
> +.B SCM_MAX_FD
> +limit applies as a whole,
> +and the receiver gets them in a single
> +.B SCM_RIGHTS
> +item;
> +if several
> +.B SCM_CREDENTIALS
> +items are included,
> +each of them is checked,
> +and the last one takes effect.
Is 'takes effect' appropriate? I think 'is sent' might be more
appropriate, right? There's nothing taking effect, I think (but I'm not
an expert in SCM_* stuff).
Have a lovely night!
Alex
> .P
> At least one byte of real data should be sent when sending ancillary data.
> On Linux, this is required to successfully send ancillary data over
> --
> 2.56.0
>
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-21 21:22 ` [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux Günther Noack
@ 2026-10-23 9:57 ` Alejandro Colomar
2026-10-23 17:57 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-23 9:57 UTC (permalink / raw)
To: Günther Noack; +Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima
[-- Attachment #1: Type: text/plain, Size: 3710 bytes --]
Hi Günther,
> Date: 2026-10-21 23:22:53+0200
> From: Günther Noack <gnoack3000@gmail.com>
>
> Reword the description of SCM_SECURITY to not be specific to SELinux.
>
> The security context is populated in scm_passec() in linux.git
> net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
> is currently implemented by SELinux, Smack and AppArmor.
>
> Also clarify the properties of the returned string:
>
> * There is no NAME_MAX limit on the length; SELinux contexts can be
> longer than that. If the control buffer is too small, put_cmsg()
> truncates the data and sets MSG_CTRUNC.
>
> * Whether the string is null-terminated also depends on the LSM:
> SELinux includes the null byte in the length, but smack_to_secctx()
> in security/smack/smack_lsm.c uses strlen() and doesn't.
...
> Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
>
> Notes:
> This feature is also available in other LSMs. Unfortunately, they
> implemented it inconsistently and that complicates the description of
> how string boundaries are handled. Linux does indeed neither
> guarantee that this terminates with a NUL byte, nor that NAME_MAX is
> large enough to hold it.
...
>
> This is the verbose variant, but I am open for suggestions regarding
> what level of detail is appropriate here.
>
> man/man7/unix.7 | 25 +++++++++++++++++++------
> 1 file changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index ded82768322b..4abd216d19c7 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -317,7 +317,7 @@ and returned as the result of
> is an integer boolean flag.
> .TP
> .B SO_PASSSEC
> -Enables receiving of the SELinux security label of the peer socket
> +Enables receiving of the security label of the peer socket
> in an ancillary message of type
> .B SCM_SECURITY
> (see below).
> @@ -544,13 +544,26 @@ message, the
> option must be enabled on the socket.
> .TP
> .B SCM_SECURITY
> -Receive the SELinux security context (the security label)
> -of the peer socket.
> -The received ancillary data is a null-terminated string containing
> +Receive the security context (the security label)
> +of the peer socket,
> +as provided by the active Linux Security Module (LSM),
> +such as SELinux or Smack.
> +The received ancillary data is a string containing
> the security context.
> -The receiver should allocate at least
> +Whether the string includes a terminating null byte
> +depends on the LSM;
This seems to contradict the commit message. The commit message says
that the string is terminated, but that the reported length might or
might not be off-by-one (i.e., not count or count the '\0').
This text, however, is saying that in some cases there might not be
a '\0' at all.
Am I missing something?
Have a lovely day!
Alex
> +the length of the data is given by the
> +.I cmsg_len
> +field.
> +There is no fixed limit on the length of the security context;
> +allocating
> .B NAME_MAX
> -bytes in the data portion of the ancillary message for this data.
> +bytes in the data portion of the ancillary message
> +is usually enough.
> +If the buffer is too small,
> +the data is truncated and the
> +.B MSG_CTRUNC
> +flag is set (see below).
> .IP
> To receive the security context, the
> .B SO_PASSSEC
> --
> 2.56.0
>
>
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
2026-10-22 21:14 ` Alejandro Colomar
@ 2026-10-23 16:50 ` Günther Noack
0 siblings, 0 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-23 16:50 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Willy Tarreau, Kuniyuki Iwashima
On Thu, Oct 22, 2026 at 11:14:09PM +0200, Alejandro Colomar wrote:
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index 79198445c581..0d2ea8bda2ae 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -785,10 +785,14 @@ when sending a file descriptor as ancillary data over
>
> Would you mind having a look at CONTRIBUTING.d/git for improving the
> hunk context?
>
> git-diff(1), gitattributes(5)
> To produce useful hunk contexts in manual pages, we need to hack
> git(1)'s idea of a function name, and also to tell git what is a
> manual page.
>
> $ git config --global diff.man.xfuncname '^\.S[SHsh] .*$';
> $ mkdir -p ~/.config/git/;
> $ echo '*.[0-9]* diff=man' >>~/.config/git/attributes;
Nice trick! Applied.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message
2026-10-22 21:28 ` Alejandro Colomar
@ 2026-10-23 17:09 ` Günther Noack
0 siblings, 0 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-23 17:09 UTC (permalink / raw)
To: Alejandro Colomar; +Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima
Hello Alejandro!
On Thu, Oct 22, 2026 at 11:28:12PM +0200, Alejandro Colomar wrote:
> > Date: 2026-10-21 23:22:51+0200
> > From: Günther Noack <gnoack3000@gmail.com>
> >
> > Verified in Linux kernel code:
>
> I think 'verified' in a commit message seems inappropriate. It should
> describe, rather than verify, and the verification would come only from
> the review tags. Maybe say something like "Relevant kernel code:".
Good point, replaced. I'll double check the other commits as well.
> > __scm_send() in linux.git net/core/scm.c walks all control messages
> > in a loop like this:
> >
> > for_each_cmsghdr(cmsg, msg) {
> > // ...
> > switch (cmsg->cmsg_type)
> > {
> > case SCM_RIGHTS:
> > // Append(!) file descriptors
> > // up to the SCM_MAX_FD limit
> > break;
> > case SCM_CREDENTIALS:
> > // Replace previously set credentials
>
> Since these are your comments, and not actual comments in the source
> code (are they yours, or from the LLM?), I'd format them clearly as
> such using invalid code rather than comments:
>
> ... replace previously set credentials ...
Done.
Yes, I transcribed the source code by hand here, including these
comments.
> > break;
> > default:
> > goto error;
> > }
> > }
> >
> > So it is possible to pass multiple SCM_* messages -- they will compose
> > if possible and override the previous value if not. Since their
> > contents are being conflated that way, they will appear as one message
> > again on the receiving side.
> >
> > Keep the recommendation as portability advice, and describe the Linux
> > behavior.
> >
> > Fixes: 5b5cb1958062 (2018-07-10; "unix.7: When sending ancillary data, only one item of each type may be sent")
> > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Assisted-by: LLM
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> >
> > Notes:
> > The factual analysis in the commit message is correct.
> >
> > I kept the LLM phrasing; it did not seem overly wordy to me and the
> > style is in line with the paragraph after it, which also documents
> > Linux-only vs. portable APIs that way.
> >
> > man/man7/unix.7 | 19 ++++++++++++++++++-
> > 1 file changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index 0d2ea8bda2ae..a1dce8c47246 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -543,7 +543,24 @@ option must be enabled on the socket (see above).
> > .P
> > When sending ancillary data with
> > .BR sendmsg (2),
> > -only one item of each of the above types may be included in the sent message.
> > +portable applications should include
> > +only one item of each of the above types in the sent message.
> > +On Linux,
> > +if several
> > +.B SCM_RIGHTS
> > +items are included,
> > +their file descriptors are combined into a single list,
> > +to which the
> > +.B SCM_MAX_FD
> > +limit applies as a whole,
> > +and the receiver gets them in a single
> > +.B SCM_RIGHTS
> > +item;
> > +if several
> > +.B SCM_CREDENTIALS
> > +items are included,
> > +each of them is checked,
> > +and the last one takes effect.
>
> Is 'takes effect' appropriate? I think 'is sent' might be more
> appropriate, right? There's nothing taking effect, I think (but I'm not
> an expert in SCM_* stuff).
You are right, "takes effect" is maybe too much described from the
angle of the implementation - I replaced it with "is sent".
What's happening is that the sender process specifies the "struct
ucred", which contains a pid, uid and gid in the SCM_CREDENTIALS
control message. When the kernel deals with these, it *checks* that
they are valid (they describe the sending process *OR* the sending
process is privileged and can send what it wants). Only the last of
these SCM_CREDENTIALS messages survives that processing though and the
receiving process then only sees that last one.
Thanks for the review!
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-23 9:57 ` Alejandro Colomar
@ 2026-10-23 17:57 ` Günther Noack
2026-10-23 18:13 ` Alejandro Colomar
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-23 17:57 UTC (permalink / raw)
To: Alejandro Colomar; +Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima
Hello Alejandro!
On Fri, Oct 23, 2026 at 11:57:41AM +0200, Alejandro Colomar wrote:
> > Date: 2026-10-21 23:22:53+0200
> > From: Günther Noack <gnoack3000@gmail.com>
> >
> > Reword the description of SCM_SECURITY to not be specific to SELinux.
> >
> > The security context is populated in scm_passec() in linux.git
> > net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
> > is currently implemented by SELinux, Smack and AppArmor.
> >
> > Also clarify the properties of the returned string:
> >
> > * There is no NAME_MAX limit on the length; SELinux contexts can be
> > longer than that. If the control buffer is too small, put_cmsg()
> > truncates the data and sets MSG_CTRUNC.
> >
> > * Whether the string is null-terminated also depends on the LSM:
> > SELinux includes the null byte in the length, but smack_to_secctx()
> > in security/smack/smack_lsm.c uses strlen() and doesn't.
>
> ...
Ah, I can see that this is confusing; let me reformulate that without
mentioning this strlen() implementation detail. Smack returns a
buffer with a given size *without* including the null byte, roughly
like this (simplified):
int len = strlen(skp->smk_known);
/* populate */
cp->context = skp->smk_known;
cp->len = len; <-- does not span the null byte
Reformulating to:
...but smack_to_secctx() in security/smack/smack_lsm.c sends a
security context that does not end in a null byte.
> > Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
> > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Assisted-by: LLM
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> >
> > Notes:
> > This feature is also available in other LSMs. Unfortunately, they
> > implemented it inconsistently and that complicates the description of
> > how string boundaries are handled. Linux does indeed neither
> > guarantee that this terminates with a NUL byte, nor that NAME_MAX is
> > large enough to hold it.
>
> ...
>
> >
> > This is the verbose variant, but I am open for suggestions regarding
> > what level of detail is appropriate here.
> >
> > man/man7/unix.7 | 25 +++++++++++++++++++------
> > 1 file changed, 19 insertions(+), 6 deletions(-)
> >
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index ded82768322b..4abd216d19c7 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -317,7 +317,7 @@ and returned as the result of
> > is an integer boolean flag.
> > .TP
> > .B SO_PASSSEC
> > -Enables receiving of the SELinux security label of the peer socket
> > +Enables receiving of the security label of the peer socket
> > in an ancillary message of type
> > .B SCM_SECURITY
> > (see below).
> > @@ -544,13 +544,26 @@ message, the
> > option must be enabled on the socket.
> > .TP
> > .B SCM_SECURITY
> > -Receive the SELinux security context (the security label)
> > -of the peer socket.
> > -The received ancillary data is a null-terminated string containing
> > +Receive the security context (the security label)
> > +of the peer socket,
> > +as provided by the active Linux Security Module (LSM),
> > +such as SELinux or Smack.
> > +The received ancillary data is a string containing
> > the security context.
> > -The receiver should allocate at least
> > +Whether the string includes a terminating null byte
> > +depends on the LSM;
>
> This seems to contradict the commit message. The commit message says
> that the string is terminated, but that the reported length might or
> might not be off-by-one (i.e., not count or count the '\0').
>
> This text, however, is saying that in some cases there might not be
> a '\0' at all.
The TL;DR is that the byte after the returned buffer's declared length
can't be trusted to be 0 - it is undefined and can be clobbered.
I have not read the full kernel implementation now, but it can already
be seen in userspace that that adjacent byte can belong to a different
data structue:
## How control messages are represented
The security context is returned to user space as a cmsghdr structure,
as described in cmsg(3), where it is returned as a buffer of length
cmsg_len:
struct cmsghdr {
size_t cmsg_len; /* data byte count including header */
/* some other fields */
/* followed by
unsigned char cmsg_data[]; */
};
Reading beyond the declared cmsg_len is undefined, and callers don't
get any guarantees about the byte following the csmg_data[] buffer.
## Iterating from userspace through multiple control messages
Iterating through the cmsgs is done with the API described in cmsg(3),
CMSG_NXTHDR(). This is implemented as an inlined function in
/usr/include/bits/socket.h. The function does a bunch of validation
logic and then ends in this rather simple advancement logic:
__cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
+ CMSG_ALIGN (__cmsg->cmsg_len));
return __cmsg;
So, the cmsgs with their cmsg_data[] buffers are next to each other in
memory. They are aligned, but that still means that the byte after
cmsg_data[] might be part of the next cmsg header or beyond the list
of control messages.
---
The more I think about this, the more unsure I am that this is even
worth documenting. In the end, anyone reading and interpreting this
data probably needs to read the corresponding LSM anyway, and trailing
null bytes are probably the least of their worries...?
Maybe it would be better to just say something like "The format of the
security context is determined by the LSM responsible for it". WDYT?
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-23 17:57 ` Günther Noack
@ 2026-10-23 18:13 ` Alejandro Colomar
2026-10-26 22:41 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-23 18:13 UTC (permalink / raw)
To: Günther Noack; +Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima
[-- Attachment #1: Type: text/plain, Size: 7029 bytes --]
Hi Günther,
> Date: 2026-10-23 19:57:16+0200
> From: Günther Noack <gnoack3000@gmail.com>
>
> Hello Alejandro!
>
> On Fri, Oct 23, 2026 at 11:57:41AM +0200, Alejandro Colomar wrote:
> > > Date: 2026-10-21 23:22:53+0200
> > > From: Günther Noack <gnoack3000@gmail.com>
> > >
> > > Reword the description of SCM_SECURITY to not be specific to SELinux.
> > >
> > > The security context is populated in scm_passec() in linux.git
> > > net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
> > > is currently implemented by SELinux, Smack and AppArmor.
> > >
> > > Also clarify the properties of the returned string:
> > >
> > > * There is no NAME_MAX limit on the length; SELinux contexts can be
> > > longer than that. If the control buffer is too small, put_cmsg()
> > > truncates the data and sets MSG_CTRUNC.
> > >
> > > * Whether the string is null-terminated also depends on the LSM:
> > > SELinux includes the null byte in the length, but smack_to_secctx()
> > > in security/smack/smack_lsm.c uses strlen() and doesn't.
> >
> > ...
>
> Ah, I can see that this is confusing; let me reformulate that without
> mentioning this strlen() implementation detail. Smack returns a
> buffer with a given size *without* including the null byte, roughly
> like this (simplified):
>
> int len = strlen(skp->smk_known);
> /* populate */
> cp->context = skp->smk_known;
> cp->len = len; <-- does not span the null byte
>
> Reformulating to:
>
> ...but smack_to_secctx() in security/smack/smack_lsm.c sends a
> security context that does not end in a null byte.
>
> > > Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
> > > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > > Assisted-by: LLM
> > > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > > ---
> > >
> > > Notes:
> > > This feature is also available in other LSMs. Unfortunately, they
> > > implemented it inconsistently and that complicates the description of
> > > how string boundaries are handled. Linux does indeed neither
> > > guarantee that this terminates with a NUL byte, nor that NAME_MAX is
> > > large enough to hold it.
> >
> > ...
> >
> > >
> > > This is the verbose variant, but I am open for suggestions regarding
> > > what level of detail is appropriate here.
> > >
> > > man/man7/unix.7 | 25 +++++++++++++++++++------
> > > 1 file changed, 19 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > > index ded82768322b..4abd216d19c7 100644
> > > --- a/man/man7/unix.7
> > > +++ b/man/man7/unix.7
> > > @@ -317,7 +317,7 @@ and returned as the result of
> > > is an integer boolean flag.
> > > .TP
> > > .B SO_PASSSEC
> > > -Enables receiving of the SELinux security label of the peer socket
> > > +Enables receiving of the security label of the peer socket
> > > in an ancillary message of type
> > > .B SCM_SECURITY
> > > (see below).
> > > @@ -544,13 +544,26 @@ message, the
> > > option must be enabled on the socket.
> > > .TP
> > > .B SCM_SECURITY
> > > -Receive the SELinux security context (the security label)
> > > -of the peer socket.
> > > -The received ancillary data is a null-terminated string containing
> > > +Receive the security context (the security label)
> > > +of the peer socket,
> > > +as provided by the active Linux Security Module (LSM),
> > > +such as SELinux or Smack.
> > > +The received ancillary data is a string containing
> > > the security context.
> > > -The receiver should allocate at least
> > > +Whether the string includes a terminating null byte
> > > +depends on the LSM;
> >
> > This seems to contradict the commit message. The commit message says
> > that the string is terminated, but that the reported length might or
> > might not be off-by-one (i.e., not count or count the '\0').
> >
> > This text, however, is saying that in some cases there might not be
> > a '\0' at all.
>
> The TL;DR is that the byte after the returned buffer's declared length
> can't be trusted to be 0 - it is undefined and can be clobbered.
Huh! This is to me a bug. Would you mind reporting them this as a bug
and CCing me? I'd rather get this fixed in the kernel than documented
as broken.
Especially, if they use strlen(3) internally, this sounds very much like
a kernel bug, but even if not, it is clearly a kernel bug.
In any case, if we were to document this bug, we should not use the term
string, because anything not containing a '\0' is not a string, by
definition.
> I have not read the full kernel implementation now, but it can already
> be seen in userspace that that adjacent byte can belong to a different
> data structue:
>
>
> ## How control messages are represented
>
> The security context is returned to user space as a cmsghdr structure,
> as described in cmsg(3), where it is returned as a buffer of length
> cmsg_len:
>
> struct cmsghdr {
> size_t cmsg_len; /* data byte count including header */
> /* some other fields */
>
> /* followed by
> unsigned char cmsg_data[]; */
> };
>
> Reading beyond the declared cmsg_len is undefined, and callers don't
> get any guarantees about the byte following the csmg_data[] buffer.
>
>
> ## Iterating from userspace through multiple control messages
>
> Iterating through the cmsgs is done with the API described in cmsg(3),
> CMSG_NXTHDR(). This is implemented as an inlined function in
> /usr/include/bits/socket.h. The function does a bunch of validation
> logic and then ends in this rather simple advancement logic:
>
> __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
> + CMSG_ALIGN (__cmsg->cmsg_len));
> return __cmsg;
>
> So, the cmsgs with their cmsg_data[] buffers are next to each other in
> memory. They are aligned, but that still means that the byte after
> cmsg_data[] might be part of the next cmsg header or beyond the list
> of control messages.
>
> ---
>
>
> The more I think about this, the more unsure I am that this is even
> worth documenting. In the end, anyone reading and interpreting this
> data probably needs to read the corresponding LSM anyway, and trailing
> null bytes are probably the least of their worries...?
Not only that it's worth documenting, but this might be a vulnerability.
>
> Maybe it would be better to just say something like "The format of the
> security context is determined by the LSM responsible for it". WDYT?
I'm unwilling to accept a nonstring as a valid format, unless very good
reasons are stated. And if those reasons are stated as "that ship
sailed long ago", the way to document this might very well be BUGS.
Have a lovely night!
Alex
>
> –Günther
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
2026-10-22 21:14 ` Alejandro Colomar
@ 2026-10-24 4:45 ` Kuniyuki Iwashima
1 sibling, 0 replies; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-24 4:45 UTC (permalink / raw)
To: Günther Noack
Cc: Alejandro Colomar, linux-man, Michael Kerrisk, Willy Tarreau
On Wed, 21 Oct 2026 23:22:50 +0200, Günther Noack wrote:
> The ETOOMANYREFS error is detected in too_many_unix_fds() in
> net/unix/af_unix.c when the user's (not the processes') in-flight FDs
> exceed RLIMIT_NOFILE, and the process has neither CAP_SYS_RESOURCE nor
> CAP_SYS_ADMIN. The error is raised when all of the following
> (simplified) conditions are true:
>
> * user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)
> * !capable(CAP_SYS_RESOURCE)
> * !capable(CAP_SYS_ADMIN)
>
> The check was introduced in linux.git 712f4aad406b (2016-01-11; "unix:
> properly account for FDs passed over unix sockets").
>
> Fixes: dc4eea68b565 (2016-12-17; "unix.7: Document ETOOMANYREFS for SCM_RIGHTS send exceeding RLIMIT_NOFILE limit")
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: Willy Tarreau <w@1wt.eu>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD
2026-10-21 21:22 ` [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD Günther Noack
@ 2026-10-24 4:57 ` Kuniyuki Iwashima
2026-10-26 21:55 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-24 4:57 UTC (permalink / raw)
To: Günther Noack
Cc: Alejandro Colomar, linux-man, Michael Kerrisk,
Alexander Mikhalitsyn
On Wed, 21 Oct 2026 23:22:52 +0200, Günther Noack wrote:
> Autobind happens if either one of SO_PASSCRED/SO_PASSPIDFD is set and
> either connect() or sendmsg() happens. Mention SO_PASSPIDFD and
> clarify that autobind does not happen immediately when setting these
> socket options.
>
> In linux.git net/unix/af_unix.c, unix_autobind() is called by
> unix_dgram_connect(), unix_stream_connect() and unix_dgram_sendmsg(),
> if the socket has no address and unix_may_passcred() is true.
>
> unix_may_passcred() is also true when SO_PASSPIDFD is set, which was
> added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add SO_PASSPIDFD and
> SCM_PIDFD"), Linux 6.5.
>
> Also, the old text said "not yet connected", but the condition is
> about the socket not being bound.
>
> Fixes: 9d1fd1157306 (1999-06-15, 2022-12-19; "man-pages 1.24")
> Fixes: 0cf2caa41ea6 (2010-10-10; "unix.7: Document the autobind feature")
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
>
> Notes:
> Rephrased the LLM-generated text so that the canonical description is
> in the "Autobind feature" section and the other place just refers to
> it.
>
> SO_PASSPIDFD is unfortunately not documented yet at this point in
> time, but it's still correct to mention it here.
>
> man/man7/unix.7 | 25 ++++++++++++++++++++-----
> 1 file changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index a1dce8c47246..ded82768322b 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -301,8 +301,14 @@ if the sender did not specify
> .B SCM_CREDENTIALS
> ancillary data.
> .IP
> -When this option is set and the socket is not yet connected,
> -a unique name in the abstract namespace will be generated automatically.
> +When this option is set on a socket that is not bound to an address,
> +the socket is autobound to a unique name in the abstract namespace
> +when
> +.BR connect (2)
> +or
> +.BR sendmsg (2)
> +is called on it;
> +see "Autobind feature", below.
> .IP
> The value given as an argument to
> .BR setsockopt (2)
> @@ -370,10 +376,19 @@ call specifies
> as
> .IR sizeof(sa_family_t) ,
> .\" i.e., sizeof(short)
> -or the
> +or if
> +.BR connect (2)
> +or
> +.BR sendmsg (2)
> +is called on a socket that was
> +not explicitly bound to an address
> +and that has the
> .B SO_PASSCRED
> -socket option was specified for a socket that was
> -not explicitly bound to an address,
> +or
> +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
Do we really need this SHA1 here ?
> +.B SO_PASSPIDFD
> +(since Linux 6.5)
> +socket option enabled,
You will need to update here with SO_PASSPIDFD_THREAD,
https://lore.kernel.org/netdev/20261005-work-unix-passpidfd-v4-3-350183b6e02a@amutable.com/
but I'm not sure to what extent you want to clarify things.
For example, is "the socket is autobound when it passes
credentials or pidfd but is not yet bound." too vague ?
> then the socket is autobound to an abstract address.
> The address consists of a null byte
> followed by 5 bytes in the character set
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix
2026-10-21 21:22 ` [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix Günther Noack
@ 2026-10-24 5:02 ` Kuniyuki Iwashima
2026-10-24 8:36 ` Alejandro Colomar
0 siblings, 1 reply; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-24 5:02 UTC (permalink / raw)
To: Günther Noack; +Cc: Alejandro Colomar, linux-man
On Wed, 21 Oct 2026 23:22:54 +0200, Günther Noack wrote:
> Use "security context", as in the description of SCM_SECURITY.
>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
> man/man7/unix.7 | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index 4abd216d19c7..67dd10cc146f 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -317,7 +317,7 @@ and returned as the result of
> is an integer boolean flag.
> .TP
> .B SO_PASSSEC
> -Enables receiving of the security label of the peer socket
> +Enables receiving of the security context of the peer socket
Patch 4 touches here, why not squash ?
> in an ancillary message of type
> .B SCM_SECURITY
> (see below).
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
2026-10-21 21:22 ` [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD Günther Noack
@ 2026-10-24 5:22 ` Kuniyuki Iwashima
2026-10-26 23:02 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-24 5:22 UTC (permalink / raw)
To: Günther Noack
Cc: Alejandro Colomar, linux-man, Alexander Mikhalitsyn,
Christian Brauner, Eric Dumazet
On Wed, 21 Oct 2026 23:22:55 +0200, Günther Noack wrote:
> These were added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add
> SO_PASSPIDFD and SCM_PIDFD") and 7b26952a91cf (2023-06-12; "net: core:
> add getsockopt SO_PEERPIDFD"), both in Linux 6.5. They are the PID
> file descriptor counterparts of SO_PASSCRED/SCM_CREDENTIALS and
> SO_PEERCRED.
>
> SO_PASSPIDFD
> sk_setsockopt() and sk_getsockopt() in net/core/sock.c handle it
> as a boolean flag for AF_UNIX sockets (EOPNOTSUPP otherwise).
> Like SO_PASSCRED, it triggers autobind, which was already
> mentioned in "Autobind feature".
>
> SCM_PIDFD
> scm_pidfd_recv() in net/core/scm.c creates the PID file
> descriptor from scm->pid, which is the PID given in the sender's
> SCM_CREDENTIALS, or the sender's own PID by default. The fd is
> created with O_CLOEXEC by pidfd_prepare(). If pidfd_prepare()
> fails, its negative error number is put into the cmsg data.
> Sending SCM_PIDFD is rejected by __scm_send() (EINVAL).
>
> Since Linux 6.17, with c679d17d3f2d (2025-07-04; "af_unix:
> enable handing out pidfds for reaped tasks in SCM_PIDFD"),
> PIDFD_STALE is passed, so this also works for reaped processes.
> Before that, pidfd_prepare() returned -EINVAL for them.
>
> SO_PEERPIDFD
> sk_getsockopt() returns a PID file descriptor for sk_peer_pid,
> or fails with ENODATA if there is none.
>
> Since Linux 6.16, with 20b70e58961b (2025-04-28; "net, pidfs:
> enable handing out pidfds for reaped sk->sk_peer_pid"), this also
> works for reaped processes on AF_UNIX sockets. Before that, it
> failed with EINVAL.
>
> Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Eric Dumazet <edumazet@kernel.org>
> Assisted-by: LLM
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
> man/man7/unix.7 | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 101 insertions(+)
>
> diff --git a/man/man7/unix.7 b/man/man7/unix.7
> index 67dd10cc146f..a4457508fd2a 100644
> --- a/man/man7/unix.7
> +++ b/man/man7/unix.7
> @@ -316,6 +316,33 @@ and returned as the result of
> .BR getsockopt (2)
> is an integer boolean flag.
> .TP
> +.BR SO_PASSPIDFD " (since Linux 6.5)"
> +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
Why does pidfd only have SHA1 ?
> +Enabling this socket option causes receipt of a PID file descriptor
> +(see
> +.BR pidfd_open (2))
> +referring to the sending process in an
> +.B SCM_PIDFD
> +ancillary message in each subsequently received message
> +(see below).
> +.IP
> +As with
> +.BR SO_PASSCRED ,
> +when this option is set on a socket that is not bound to an address,
> +the socket is autobound to a unique name in the abstract namespace
> +when
> +.BR connect (2)
> +or
> +.BR sendmsg (2)
> +is called on it;
> +see "Autobind feature", below.
> +.IP
> +The value given as an argument to
> +.BR setsockopt (2)
> +and returned as the result of
> +.BR getsockopt (2)
> +is an integer boolean flag.
> +.TP
> .B SO_PASSSEC
> Enables receiving of the security context of the peer socket
> in an ancillary message of type
> @@ -367,6 +394,43 @@ stream and sequenced-packet sockets, and for
> .B AF_UNIX
> socket pairs created using
> .BR socketpair (2).
> +.TP
> +.BR SO_PEERPIDFD " (since Linux 6.5)"
> +.\" commit 7b26952a91cf65ff1cc867a2382a8964d8c0ee7d
> +This read-only socket option returns a new PID file descriptor
> +(see
> +.BR pidfd_open (2))
> +referring to the peer process connected to this socket.
Not sure if this is worth noting here, but "peer process" is
a bit unclear.
For example, if process A creates socekt A, calls listen(),
and pass it to process B and close()s the fd, and process C
creates socket C and connects to socket A, then getsockopt(C,
SO_PEERPIDFD) will return process A, not B.
> +This is the process whose credentials are returned by
> +.BR SO_PEERCRED .
> +Unlike the PID returned by
> +.BR SO_PEERCRED ,
> +the PID file descriptor cannot come to refer to a different process
> +if the peer process terminates and its PID is reused.
> +.IP
> +The argument to
> +.BR getsockopt (2)
> +is a pointer to an
> +.IR int ,
> +in which the PID file descriptor is returned.
> +The close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +is set on the new file descriptor.
> +.IP
> +If the socket has no peer process,
> +.BR getsockopt (2)
> +fails with the error
> +.BR ENODATA .
> +.IP
> +Since Linux 6.16,
> +.\" commit 20b70e58961b855e61f2c6a7a19a38a64ad1bed6
> +a PID file descriptor is returned
> +even if the peer process has already terminated and been reaped.
> +Before Linux 6.16,
> +.BR getsockopt (2)
> +failed with the error
> +.B EINVAL
> +in this case.
> .\"
> .SS Autobind feature
> If a
> @@ -543,6 +607,42 @@ message, the
> .B SO_PASSCRED
> option must be enabled on the socket.
> .TP
> +.BR SCM_PIDFD " (since Linux 6.5)"
> +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
> +Receive a PID file descriptor
> +(see
> +.BR pidfd_open (2))
> +referring to the sending process.
> +The data portion contains a single
> +.IR int .
> +The PID file descriptor refers to the process whose PID would be
> +received in an
> +.B SCM_CREDENTIALS
> +message;
> +if the sender specified
> +.B SCM_CREDENTIALS
> +ancillary data,
> +it refers to the process with the PID given there.
> +The close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +is set on the new file descriptor.
> +.IP
> +If the PID file descriptor cannot be created,
> +the data portion contains a negative error number instead.
> +Since Linux 6.17,
> +.\" commit c679d17d3f2d895b34e660673141ad250889831f
> +a PID file descriptor is created
> +even if the sending process has already terminated and been reaped.
> +Before Linux 6.17,
> +.B \-EINVAL
> +was received in this case.
> +.IP
> +This message cannot be sent;
> +it is generated by the kernel.
> +To receive it, the
> +.B SO_PASSPIDFD
> +option must be enabled on the socket.
> +.TP
> .B SCM_SECURITY
> Receive the security context (the security label)
> of the peer socket,
> @@ -1273,6 +1373,7 @@ see
> and
> .BR seccomp_unotify (2).
> .SH SEE ALSO
> +.BR pidfd_open (2),
> .BR recvmsg (2),
> .BR sendmsg (2),
> .BR socket (2),
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix
2026-10-24 5:02 ` Kuniyuki Iwashima
@ 2026-10-24 8:36 ` Alejandro Colomar
2026-10-26 22:42 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-24 8:36 UTC (permalink / raw)
To: Kuniyuki Iwashima; +Cc: Günther Noack, linux-man
[-- Attachment #1: Type: text/plain, Size: 1224 bytes --]
Hi Kuniyuki,
> Date: 2026-10-24 05:02:06+0000
> From: Kuniyuki Iwashima <kuniyu@google.com>
>
> On Wed, 21 Oct 2026 23:22:54 +0200, Günther Noack wrote:
> > Use "security context", as in the description of SCM_SECURITY.
> >
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Assisted-by: LLM
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> > man/man7/unix.7 | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index 4abd216d19c7..67dd10cc146f 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -317,7 +317,7 @@ and returned as the result of
> > is an integer boolean flag.
> > .TP
> > .B SO_PASSSEC
> > -Enables receiving of the security label of the peer socket
> > +Enables receiving of the security context of the peer socket
>
> Patch 4 touches here, why not squash ?
I prefer not squashing. It makes the commit messages more specific,
which is easier to understand and review in the future.
Have a lovely day!
Alex
>
>
> > in an ancillary message of type
> > .B SCM_SECURITY
> > (see below).
> > --
> > 2.56.0
> >
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD
2026-10-24 4:57 ` Kuniyuki Iwashima
@ 2026-10-26 21:55 ` Günther Noack
2026-10-27 5:04 ` Kuniyuki Iwashima
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-26 21:55 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: Alejandro Colomar, linux-man, Michael Kerrisk,
Alexander Mikhalitsyn
On Sat, Oct 24, 2026 at 04:57:58AM +0000, Kuniyuki Iwashima wrote:
> On Wed, 21 Oct 2026 23:22:52 +0200, Günther Noack wrote:
> > Autobind happens if either one of SO_PASSCRED/SO_PASSPIDFD is set and
> > either connect() or sendmsg() happens. Mention SO_PASSPIDFD and
> > clarify that autobind does not happen immediately when setting these
> > socket options.
> >
> > In linux.git net/unix/af_unix.c, unix_autobind() is called by
> > unix_dgram_connect(), unix_stream_connect() and unix_dgram_sendmsg(),
> > if the socket has no address and unix_may_passcred() is true.
> >
> > unix_may_passcred() is also true when SO_PASSPIDFD is set, which was
> > added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add SO_PASSPIDFD and
> > SCM_PIDFD"), Linux 6.5.
> >
> > Also, the old text said "not yet connected", but the condition is
> > about the socket not being bound.
> >
> > Fixes: 9d1fd1157306 (1999-06-15, 2022-12-19; "man-pages 1.24")
> > Fixes: 0cf2caa41ea6 (2010-10-10; "unix.7: Document the autobind feature")
> > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Assisted-by: LLM
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> >
> > Notes:
> > Rephrased the LLM-generated text so that the canonical description is
> > in the "Autobind feature" section and the other place just refers to
> > it.
> >
> > SO_PASSPIDFD is unfortunately not documented yet at this point in
> > time, but it's still correct to mention it here.
> >
> > man/man7/unix.7 | 25 ++++++++++++++++++++-----
> > 1 file changed, 20 insertions(+), 5 deletions(-)
> >
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index a1dce8c47246..ded82768322b 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -301,8 +301,14 @@ if the sender did not specify
> > .B SCM_CREDENTIALS
> > ancillary data.
> > .IP
> > -When this option is set and the socket is not yet connected,
> > -a unique name in the abstract namespace will be generated automatically.
> > +When this option is set on a socket that is not bound to an address,
> > +the socket is autobound to a unique name in the abstract namespace
> > +when
> > +.BR connect (2)
> > +or
> > +.BR sendmsg (2)
> > +is called on it;
> > +see "Autobind feature", below.
> > .IP
> > The value given as an argument to
> > .BR setsockopt (2)
> > @@ -370,10 +376,19 @@ call specifies
> > as
> > .IR sizeof(sa_family_t) ,
> > .\" i.e., sizeof(short)
> > -or the
> > +or if
> > +.BR connect (2)
> > +or
> > +.BR sendmsg (2)
> > +is called on a socket that was
> > +not explicitly bound to an address
> > +and that has the
> > .B SO_PASSCRED
> > -socket option was specified for a socket that was
> > -not explicitly bound to an address,
> > +or
> > +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
>
> Do we really need this SHA1 here ?
I'll drop it, since it's already pointed out in the commit message.
It seemed like the convention in these man pages, but apparently it's
not needed any more, as Alejandro also remarked in [1].
[1] https://lore.kernel.org/all/atulJkR7fAgyKhPP@debian/
> > +.B SO_PASSPIDFD
> > +(since Linux 6.5)
> > +socket option enabled,
>
> You will need to update here with SO_PASSPIDFD_THREAD,
> https://lore.kernel.org/netdev/20261005-work-unix-passpidfd-v4-3-350183b6e02a@amutable.com/
SO_PASSPIDFD_THREAD did not make it into Linux 7.3, and man pages
document stable features only, so it will have to go separately at a
later point in time.
> but I'm not sure to what extent you want to clarify things.
>
> For example, is "the socket is autobound when it passes
> credentials or pidfd but is not yet bound." too vague ?
In my ears, "passing credentials" might as well mean that the current
credentials are being *sent* over the socket, rather than received.
We could maybe say "when it is configured to receive credentials or
pidfd"? (But at that point, it's similarly long and less precise than
just listing the socket options.) I'd keep it as is for now, if
that's OK.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-23 18:13 ` Alejandro Colomar
@ 2026-10-26 22:41 ` Günther Noack
2026-10-27 8:54 ` Günther Noack
2026-10-27 16:32 ` Casey Schaufler
0 siblings, 2 replies; 35+ messages in thread
From: Günther Noack @ 2026-10-26 22:41 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
Hello Alejandro, Casey!
On Fri, Oct 23, 2026 at 08:13:22PM +0200, Alejandro Colomar wrote:
> > Date: 2026-10-23 19:57:16+0200
> > From: Günther Noack <gnoack3000@gmail.com>
> > On Fri, Oct 23, 2026 at 11:57:41AM +0200, Alejandro Colomar wrote:
> > > > Date: 2026-10-21 23:22:53+0200
> > > > From: Günther Noack <gnoack3000@gmail.com>
> > > >
> > > > Reword the description of SCM_SECURITY to not be specific to SELinux.
> > > >
> > > > The security context is populated in scm_passec() in linux.git
> > > > net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
> > > > is currently implemented by SELinux, Smack and AppArmor.
> > > >
> > > > Also clarify the properties of the returned string:
> > > >
> > > > * There is no NAME_MAX limit on the length; SELinux contexts can be
> > > > longer than that. If the control buffer is too small, put_cmsg()
> > > > truncates the data and sets MSG_CTRUNC.
> > > >
> > > > * Whether the string is null-terminated also depends on the LSM:
> > > > SELinux includes the null byte in the length, but smack_to_secctx()
> > > > in security/smack/smack_lsm.c uses strlen() and doesn't.
> > >
> > > ...
> >
> > Ah, I can see that this is confusing; let me reformulate that without
> > mentioning this strlen() implementation detail. Smack returns a
> > buffer with a given size *without* including the null byte, roughly
> > like this (simplified):
> >
> > int len = strlen(skp->smk_known);
> > /* populate */
> > cp->context = skp->smk_known;
> > cp->len = len; <-- does not span the null byte
> >
> > Reformulating to:
> >
> > ...but smack_to_secctx() in security/smack/smack_lsm.c sends a
> > security context that does not end in a null byte.
> >
> > > > Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
> > > > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > > > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > > > Assisted-by: LLM
> > > > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > > > ---
> > > >
> > > > Notes:
> > > > This feature is also available in other LSMs. Unfortunately, they
> > > > implemented it inconsistently and that complicates the description of
> > > > how string boundaries are handled. Linux does indeed neither
> > > > guarantee that this terminates with a NUL byte, nor that NAME_MAX is
> > > > large enough to hold it.
> > >
> > > ...
> > >
> > > >
> > > > This is the verbose variant, but I am open for suggestions regarding
> > > > what level of detail is appropriate here.
> > > >
> > > > man/man7/unix.7 | 25 +++++++++++++++++++------
> > > > 1 file changed, 19 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > > > index ded82768322b..4abd216d19c7 100644
> > > > --- a/man/man7/unix.7
> > > > +++ b/man/man7/unix.7
> > > > @@ -317,7 +317,7 @@ and returned as the result of
> > > > is an integer boolean flag.
> > > > .TP
> > > > .B SO_PASSSEC
> > > > -Enables receiving of the SELinux security label of the peer socket
> > > > +Enables receiving of the security label of the peer socket
> > > > in an ancillary message of type
> > > > .B SCM_SECURITY
> > > > (see below).
> > > > @@ -544,13 +544,26 @@ message, the
> > > > option must be enabled on the socket.
> > > > .TP
> > > > .B SCM_SECURITY
> > > > -Receive the SELinux security context (the security label)
> > > > -of the peer socket.
> > > > -The received ancillary data is a null-terminated string containing
> > > > +Receive the security context (the security label)
> > > > +of the peer socket,
> > > > +as provided by the active Linux Security Module (LSM),
> > > > +such as SELinux or Smack.
> > > > +The received ancillary data is a string containing
> > > > the security context.
> > > > -The receiver should allocate at least
> > > > +Whether the string includes a terminating null byte
> > > > +depends on the LSM;
> > >
> > > This seems to contradict the commit message. The commit message says
> > > that the string is terminated, but that the reported length might or
> > > might not be off-by-one (i.e., not count or count the '\0').
> > >
> > > This text, however, is saying that in some cases there might not be
> > > a '\0' at all.
> >
> > The TL;DR is that the byte after the returned buffer's declared length
> > can't be trusted to be 0 - it is undefined and can be clobbered.
>
> Huh! This is to me a bug. Would you mind reporting them this as a bug
> and CCing me? I'd rather get this fixed in the kernel than documented
> as broken.
>
> Especially, if they use strlen(3) internally, this sounds very much like
> a kernel bug, but even if not, it is clearly a kernel bug.
>
> In any case, if we were to document this bug, we should not use the term
> string, because anything not containing a '\0' is not a string, by
> definition.
Casey, would you be able to confirm whether this constitutes a Smack
bug or is intentional?
The TL;DR is that we came across the function smack_to_secctx() in
smack_lsm.c, which passes a Smack label string in a buffer without a
terminating null byte. This is inconsistent with what SELinux and
AppArmor do.
Before we start explaining so many corner cases in the man pages, I
wanted to check -- is this something that Smack should fix, by
including the zero byte?
I tried to double check the Smack userspace utilities but couldn't
find any use of SCM_SECURITY there. (Is the feature unused?)
> > I have not read the full kernel implementation now, but it can already
> > be seen in userspace that that adjacent byte can belong to a different
> > data structue:
> >
> >
> > ## How control messages are represented
> >
> > The security context is returned to user space as a cmsghdr structure,
> > as described in cmsg(3), where it is returned as a buffer of length
> > cmsg_len:
> >
> > struct cmsghdr {
> > size_t cmsg_len; /* data byte count including header */
> > /* some other fields */
> >
> > /* followed by
> > unsigned char cmsg_data[]; */
> > };
> >
> > Reading beyond the declared cmsg_len is undefined, and callers don't
> > get any guarantees about the byte following the csmg_data[] buffer.
> >
> >
> > ## Iterating from userspace through multiple control messages
> >
> > Iterating through the cmsgs is done with the API described in cmsg(3),
> > CMSG_NXTHDR(). This is implemented as an inlined function in
> > /usr/include/bits/socket.h. The function does a bunch of validation
> > logic and then ends in this rather simple advancement logic:
> >
> > __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
> > + CMSG_ALIGN (__cmsg->cmsg_len));
> > return __cmsg;
> >
> > So, the cmsgs with their cmsg_data[] buffers are next to each other in
> > memory. They are aligned, but that still means that the byte after
> > cmsg_data[] might be part of the next cmsg header or beyond the list
> > of control messages.
> >
> > ---
> >
> >
> > The more I think about this, the more unsure I am that this is even
> > worth documenting. In the end, anyone reading and interpreting this
> > data probably needs to read the corresponding LSM anyway, and trailing
> > null bytes are probably the least of their worries...?
>
> Not only that it's worth documenting, but this might be a vulnerability.
> > Maybe it would be better to just say something like "The format of the
> > security context is determined by the LSM responsible for it". WDYT?
>
> I'm unwilling to accept a nonstring as a valid format, unless very good
> reasons are stated. And if those reasons are stated as "that ship
> sailed long ago", the way to document this might very well be BUGS.
Point taken and agreed that it would be better to call it a "buffer"
rather than a "string" when it does not have the null terminator.
It does seem that this is used also outside of UNIX Domain Sockets:
IP_PASSSEC(2const) says:
The security context returned in the SCM_SECURITY ancillary message
is of the same format as the one described in SO_PEERSEC(2const).
And looking this format up in SO_PEERSEC(2const), we find:
The security context string may include a terminating null character
in the returned length, but is not guaranteed to do so: a security
context "foo" might be represented as either {'f','o','o'} of length
3 or {'f','o','o','\0'} of length 4, which are considered to be
interchangeable. The string is printable, does not contain non-
terminating null characters, and is in an unspecified encoding (in
particular, it is not guaranteed to be ASCII or UTF-8).
So it seems that these "buffer" (not "string") semantics exist there
as well. Maybe it is intentional then that it is treated as a buffer
rather than a string?
I'm still leaning towards documenting it as a buffer with
implementation-defined contents which are provided by a LSM. How
these buffer contents are interpreted is depending on the LSM in use
anyway.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix
2026-10-24 8:36 ` Alejandro Colomar
@ 2026-10-26 22:42 ` Günther Noack
2026-10-27 5:05 ` Kuniyuki Iwashima
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-26 22:42 UTC (permalink / raw)
To: Alejandro Colomar; +Cc: Kuniyuki Iwashima, linux-man
On Sat, Oct 24, 2026 at 10:36:33AM +0200, Alejandro Colomar wrote:
> > Date: 2026-10-24 05:02:06+0000
> > From: Kuniyuki Iwashima <kuniyu@google.com>
> > Patch 4 touches here, why not squash ?
>
> I prefer not squashing. It makes the commit messages more specific,
> which is easier to understand and review in the future.
Ack, leaving it unsquashed.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
2026-10-24 5:22 ` Kuniyuki Iwashima
@ 2026-10-26 23:02 ` Günther Noack
2026-10-27 5:06 ` Kuniyuki Iwashima
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-26 23:02 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: Alejandro Colomar, linux-man, Alexander Mikhalitsyn,
Christian Brauner, Eric Dumazet
On Sat, Oct 24, 2026 at 05:22:56AM +0000, Kuniyuki Iwashima wrote:
> On Wed, 21 Oct 2026 23:22:55 +0200, Günther Noack wrote:
> > These were added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add
> > SO_PASSPIDFD and SCM_PIDFD") and 7b26952a91cf (2023-06-12; "net: core:
> > add getsockopt SO_PEERPIDFD"), both in Linux 6.5. They are the PID
> > file descriptor counterparts of SO_PASSCRED/SCM_CREDENTIALS and
> > SO_PEERCRED.
> >
> > SO_PASSPIDFD
> > sk_setsockopt() and sk_getsockopt() in net/core/sock.c handle it
> > as a boolean flag for AF_UNIX sockets (EOPNOTSUPP otherwise).
> > Like SO_PASSCRED, it triggers autobind, which was already
> > mentioned in "Autobind feature".
> >
> > SCM_PIDFD
> > scm_pidfd_recv() in net/core/scm.c creates the PID file
> > descriptor from scm->pid, which is the PID given in the sender's
> > SCM_CREDENTIALS, or the sender's own PID by default. The fd is
> > created with O_CLOEXEC by pidfd_prepare(). If pidfd_prepare()
> > fails, its negative error number is put into the cmsg data.
> > Sending SCM_PIDFD is rejected by __scm_send() (EINVAL).
> >
> > Since Linux 6.17, with c679d17d3f2d (2025-07-04; "af_unix:
> > enable handing out pidfds for reaped tasks in SCM_PIDFD"),
> > PIDFD_STALE is passed, so this also works for reaped processes.
> > Before that, pidfd_prepare() returned -EINVAL for them.
> >
> > SO_PEERPIDFD
> > sk_getsockopt() returns a PID file descriptor for sk_peer_pid,
> > or fails with ENODATA if there is none.
> >
> > Since Linux 6.16, with 20b70e58961b (2025-04-28; "net, pidfs:
> > enable handing out pidfds for reaped sk->sk_peer_pid"), this also
> > works for reaped processes on AF_UNIX sockets. Before that, it
> > failed with EINVAL.
> >
> > Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> > Cc: Christian Brauner <brauner@kernel.org>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Cc: Eric Dumazet <edumazet@kernel.org>
> > Assisted-by: LLM
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> > man/man7/unix.7 | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 101 insertions(+)
> >
> > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > index 67dd10cc146f..a4457508fd2a 100644
> > --- a/man/man7/unix.7
> > +++ b/man/man7/unix.7
> > @@ -316,6 +316,33 @@ and returned as the result of
> > .BR getsockopt (2)
> > is an integer boolean flag.
> > .TP
> > +.BR SO_PASSPIDFD " (since Linux 6.5)"
> > +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
>
> Why does pidfd only have SHA1 ?
I'm removing it from the code and keeping it in the commit message, as
in the other commits above.
> > @@ -367,6 +394,43 @@ stream and sequenced-packet sockets, and for
> > .B AF_UNIX
> > socket pairs created using
> > .BR socketpair (2).
> > +.TP
> > +.BR SO_PEERPIDFD " (since Linux 6.5)"
> > +.\" commit 7b26952a91cf65ff1cc867a2382a8964d8c0ee7d
> > +This read-only socket option returns a new PID file descriptor
> > +(see
> > +.BR pidfd_open (2))
> > +referring to the peer process connected to this socket.
>
> Not sure if this is worth noting here, but "peer process" is
> a bit unclear.
>
> For example, if process A creates socekt A, calls listen(),
> and pass it to process B and close()s the fd, and process C
> creates socket C and connects to socket A, then getsockopt(C,
> SO_PEERPIDFD) will return process A, not B.
I think it is OK; The phrase "peer process connected to this socket"
is adapted from the description of SO_PEERCRED, and to clarify, the
next sentence refers to the description of SO_PEERCRED in the same
file:
> > +This is the process whose credentials are returned by
> > +.BR SO_PEERCRED .
^ Here
I think the SO_PEERCRED description is good:
This read-only socket option returns the credentials of the peer
process connected to this socket. The returned credentials are
those that were in effect at the time of the call to connect(2),
listen(2) or sockepair(2).
(It is good, because it puts the common use case first, where the
entire BSD socket dance is done by the same process, and then
clarifies the details for the people who need them.)
So this seems fair to me, imho. Let me know whether that seems
acceptable to you.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD
2026-10-26 21:55 ` Günther Noack
@ 2026-10-27 5:04 ` Kuniyuki Iwashima
0 siblings, 0 replies; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-27 5:04 UTC (permalink / raw)
To: Günther Noack
Cc: Alejandro Colomar, linux-man, Michael Kerrisk,
Alexander Mikhalitsyn
On Mon, 26 Oct 2026 22:55:49 +0100, Günther Noack wrote:
> On Sat, Oct 24, 2026 at 04:57:58AM +0000, Kuniyuki Iwashima wrote:
> > On Wed, 21 Oct 2026 23:22:52 +0200, Günther Noack wrote:
> > > Autobind happens if either one of SO_PASSCRED/SO_PASSPIDFD is set and
> > > either connect() or sendmsg() happens. Mention SO_PASSPIDFD and
> > > clarify that autobind does not happen immediately when setting these
> > > socket options.
> > >
> > > In linux.git net/unix/af_unix.c, unix_autobind() is called by
> > > unix_dgram_connect(), unix_stream_connect() and unix_dgram_sendmsg(),
> > > if the socket has no address and unix_may_passcred() is true.
> > >
> > > unix_may_passcred() is also true when SO_PASSPIDFD is set, which was
> > > added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add SO_PASSPIDFD and
> > > SCM_PIDFD"), Linux 6.5.
> > >
> > > Also, the old text said "not yet connected", but the condition is
> > > about the socket not being bound.
> > >
> > > Fixes: 9d1fd1157306 (1999-06-15, 2022-12-19; "man-pages 1.24")
> > > Fixes: 0cf2caa41ea6 (2010-10-10; "unix.7: Document the autobind feature")
> > > Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> > > Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> > > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > > Assisted-by: LLM
> > > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > > ---
> > >
> > > Notes:
> > > Rephrased the LLM-generated text so that the canonical description is
> > > in the "Autobind feature" section and the other place just refers to
> > > it.
> > >
> > > SO_PASSPIDFD is unfortunately not documented yet at this point in
> > > time, but it's still correct to mention it here.
> > >
> > > man/man7/unix.7 | 25 ++++++++++++++++++++-----
> > > 1 file changed, 20 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > > index a1dce8c47246..ded82768322b 100644
> > > --- a/man/man7/unix.7
> > > +++ b/man/man7/unix.7
> > > @@ -301,8 +301,14 @@ if the sender did not specify
> > > .B SCM_CREDENTIALS
> > > ancillary data.
> > > .IP
> > > -When this option is set and the socket is not yet connected,
> > > -a unique name in the abstract namespace will be generated automatically.
> > > +When this option is set on a socket that is not bound to an address,
> > > +the socket is autobound to a unique name in the abstract namespace
> > > +when
> > > +.BR connect (2)
> > > +or
> > > +.BR sendmsg (2)
> > > +is called on it;
> > > +see "Autobind feature", below.
> > > .IP
> > > The value given as an argument to
> > > .BR setsockopt (2)
> > > @@ -370,10 +376,19 @@ call specifies
> > > as
> > > .IR sizeof(sa_family_t) ,
> > > .\" i.e., sizeof(short)
> > > -or the
> > > +or if
> > > +.BR connect (2)
> > > +or
> > > +.BR sendmsg (2)
> > > +is called on a socket that was
> > > +not explicitly bound to an address
> > > +and that has the
> > > .B SO_PASSCRED
> > > -socket option was specified for a socket that was
> > > -not explicitly bound to an address,
> > > +or
> > > +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
> >
> > Do we really need this SHA1 here ?
>
> I'll drop it, since it's already pointed out in the commit message.
> It seemed like the convention in these man pages, but apparently it's
> not needed any more, as Alejandro also remarked in [1].
>
> [1] https://lore.kernel.org/all/atulJkR7fAgyKhPP@debian/
>
>
> > > +.B SO_PASSPIDFD
> > > +(since Linux 6.5)
> > > +socket option enabled,
> >
> > You will need to update here with SO_PASSPIDFD_THREAD,
> > https://lore.kernel.org/netdev/20261005-work-unix-passpidfd-v4-3-350183b6e02a@amutable.com/
>
> SO_PASSPIDFD_THREAD did not make it into Linux 7.3, and man pages
> document stable features only, so it will have to go separately at a
> later point in time.
>
>
> > but I'm not sure to what extent you want to clarify things.
> >
> > For example, is "the socket is autobound when it passes
> > credentials or pidfd but is not yet bound." too vague ?
>
> In my ears, "passing credentials" might as well mean that the current
> credentials are being *sent* over the socket, rather than received.
> We could maybe say "when it is configured to receive credentials or
> pidfd"? (But at that point, it's similarly long and less precise than
> just listing the socket options.) I'd keep it as is for now, if
> that's OK.
Fair enough :)
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix
2026-10-26 22:42 ` Günther Noack
@ 2026-10-27 5:05 ` Kuniyuki Iwashima
0 siblings, 0 replies; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-27 5:05 UTC (permalink / raw)
To: Günther Noack; +Cc: Alejandro Colomar, linux-man
On Mon, 26 Oct 2026 23:42:09 +0100, Günther Noack wrote:
> On Sat, Oct 24, 2026 at 10:36:33AM +0200, Alejandro Colomar wrote:
> > > Date: 2026-10-24 05:02:06+0000
> > > From: Kuniyuki Iwashima <kuniyu@google.com>
> > > Patch 4 touches here, why not squash ?
> >
> > I prefer not squashing. It makes the commit messages more specific,
> > which is easier to understand and review in the future.
>
> Ack, leaving it unsquashed.
Okay, then
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Thanks
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
2026-10-26 23:02 ` Günther Noack
@ 2026-10-27 5:06 ` Kuniyuki Iwashima
0 siblings, 0 replies; 35+ messages in thread
From: Kuniyuki Iwashima @ 2026-10-27 5:06 UTC (permalink / raw)
To: Günther Noack
Cc: Alejandro Colomar, linux-man, Alexander Mikhalitsyn,
Christian Brauner, Eric Dumazet
On Tue, 27 Oct 2026 00:02:04 +0100, Günther Noack wrote:
> On Sat, Oct 24, 2026 at 05:22:56AM +0000, Kuniyuki Iwashima wrote:
> > On Wed, 21 Oct 2026 23:22:55 +0200, Günther Noack wrote:
> > > These were added in linux.git 5e2ff6704a27 (2023-06-12; "scm: add
> > > SO_PASSPIDFD and SCM_PIDFD") and 7b26952a91cf (2023-06-12; "net: core:
> > > add getsockopt SO_PEERPIDFD"), both in Linux 6.5. They are the PID
> > > file descriptor counterparts of SO_PASSCRED/SCM_CREDENTIALS and
> > > SO_PEERCRED.
> > >
> > > SO_PASSPIDFD
> > > sk_setsockopt() and sk_getsockopt() in net/core/sock.c handle it
> > > as a boolean flag for AF_UNIX sockets (EOPNOTSUPP otherwise).
> > > Like SO_PASSCRED, it triggers autobind, which was already
> > > mentioned in "Autobind feature".
> > >
> > > SCM_PIDFD
> > > scm_pidfd_recv() in net/core/scm.c creates the PID file
> > > descriptor from scm->pid, which is the PID given in the sender's
> > > SCM_CREDENTIALS, or the sender's own PID by default. The fd is
> > > created with O_CLOEXEC by pidfd_prepare(). If pidfd_prepare()
> > > fails, its negative error number is put into the cmsg data.
> > > Sending SCM_PIDFD is rejected by __scm_send() (EINVAL).
> > >
> > > Since Linux 6.17, with c679d17d3f2d (2025-07-04; "af_unix:
> > > enable handing out pidfds for reaped tasks in SCM_PIDFD"),
> > > PIDFD_STALE is passed, so this also works for reaped processes.
> > > Before that, pidfd_prepare() returned -EINVAL for them.
> > >
> > > SO_PEERPIDFD
> > > sk_getsockopt() returns a PID file descriptor for sk_peer_pid,
> > > or fails with ENODATA if there is none.
> > >
> > > Since Linux 6.16, with 20b70e58961b (2025-04-28; "net, pidfs:
> > > enable handing out pidfds for reaped sk->sk_peer_pid"), this also
> > > works for reaped processes on AF_UNIX sockets. Before that, it
> > > failed with EINVAL.
> > >
> > > Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
> > > Cc: Christian Brauner <brauner@kernel.org>
> > > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > > Cc: Eric Dumazet <edumazet@kernel.org>
> > > Assisted-by: LLM
> > > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > > ---
> > > man/man7/unix.7 | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
> > > 1 file changed, 101 insertions(+)
> > >
> > > diff --git a/man/man7/unix.7 b/man/man7/unix.7
> > > index 67dd10cc146f..a4457508fd2a 100644
> > > --- a/man/man7/unix.7
> > > +++ b/man/man7/unix.7
> > > @@ -316,6 +316,33 @@ and returned as the result of
> > > .BR getsockopt (2)
> > > is an integer boolean flag.
> > > .TP
> > > +.BR SO_PASSPIDFD " (since Linux 6.5)"
> > > +.\" commit 5e2ff6704a275be009be8979af17c52361b79b89
> >
> > Why does pidfd only have SHA1 ?
>
> I'm removing it from the code and keeping it in the commit message, as
> in the other commits above.
>
>
> > > @@ -367,6 +394,43 @@ stream and sequenced-packet sockets, and for
> > > .B AF_UNIX
> > > socket pairs created using
> > > .BR socketpair (2).
> > > +.TP
> > > +.BR SO_PEERPIDFD " (since Linux 6.5)"
> > > +.\" commit 7b26952a91cf65ff1cc867a2382a8964d8c0ee7d
> > > +This read-only socket option returns a new PID file descriptor
> > > +(see
> > > +.BR pidfd_open (2))
> > > +referring to the peer process connected to this socket.
> >
> > Not sure if this is worth noting here, but "peer process" is
> > a bit unclear.
> >
> > For example, if process A creates socekt A, calls listen(),
> > and pass it to process B and close()s the fd, and process C
> > creates socket C and connects to socket A, then getsockopt(C,
> > SO_PEERPIDFD) will return process A, not B.
>
> I think it is OK; The phrase "peer process connected to this socket"
> is adapted from the description of SO_PEERCRED, and to clarify, the
> next sentence refers to the description of SO_PEERCRED in the same
> file:
>
> > > +This is the process whose credentials are returned by
> > > +.BR SO_PEERCRED .
>
> ^ Here
>
> I think the SO_PEERCRED description is good:
>
> This read-only socket option returns the credentials of the peer
> process connected to this socket. The returned credentials are
> those that were in effect at the time of the call to connect(2),
> listen(2) or sockepair(2).
>
> (It is good, because it puts the common use case first, where the
> entire BSD socket dance is done by the same process, and then
> clarifies the details for the people who need them.)
>
> So this seems fair to me, imho. Let me know whether that seems
> acceptable to you.
Probably okay as is. Maybe not many people is using socket
activation w/ systemd.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-26 22:41 ` Günther Noack
@ 2026-10-27 8:54 ` Günther Noack
2026-10-27 21:46 ` Alejandro Colomar
2026-10-27 16:32 ` Casey Schaufler
1 sibling, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-27 8:54 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> I'm still leaning towards documenting it as a buffer with
> implementation-defined contents which are provided by a LSM. How
> these buffer contents are interpreted is depending on the LSM in use
> anyway.
To make a more concrete and constructive wording proposal:
SCM_SECURITY
Receive the security context (the security label) of the peer
socket, as provided by the active Linux Security Module (LSM). The
received ancillary data is a byte buffer.
The exact format of the security context buffer is defined by the
active major LSM. For example, SELinux returns a SELinux label as a
string (including a terminating null byte).
Does that sound reasonable? Let me know what you think.
I removed the wording "There is no fixed limit ...", because it should
be a given that callers allocate enough buffer space for receiving and
check the truncation flag. (The more important part is that we remove
the previous wording which suggested that it would fit into NAME_MAX.)
Given that SCM_SECURITY on "real" networks seems to have the same
"buffer, not string" semantics, it feels fair to express it that way?
People who want to read the security context will anyway need to read
up on the exact format used by the LSM in order to attribute any
meaning to it.
–Günther
P.S.: I had a hard time finding many usage examples. The main user of
SCM_SECURITY seems to be systemd's journald, which uses it to log the
SELinux security label. That code can deal with both null terminated
strings and ones where it is missing (due to truncation), and there is
a comment indicating that they are aware of possible truncation.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-26 22:41 ` Günther Noack
2026-10-27 8:54 ` Günther Noack
@ 2026-10-27 16:32 ` Casey Schaufler
2026-10-27 21:52 ` Alejandro Colomar
1 sibling, 1 reply; 35+ messages in thread
From: Casey Schaufler @ 2026-10-27 16:32 UTC (permalink / raw)
To: Günther Noack, Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
On 10/26/2026 3:41 PM, Günther Noack wrote:
> Hello Alejandro, Casey!
>
> On Fri, Oct 23, 2026 at 08:13:22PM +0200, Alejandro Colomar wrote:
>>> Date: 2026-10-23 19:57:16+0200
>>> From: Günther Noack <gnoack3000@gmail.com>
>>> On Fri, Oct 23, 2026 at 11:57:41AM +0200, Alejandro Colomar wrote:
>>>>> Date: 2026-10-21 23:22:53+0200
>>>>> From: Günther Noack <gnoack3000@gmail.com>
>>>>>
>>>>> Reword the description of SCM_SECURITY to not be specific to SELinux.
>>>>>
>>>>> The security context is populated in scm_passec() in linux.git
>>>>> net/core/scm.c, through the security_secid_to_secctx() LSM hook, which
>>>>> is currently implemented by SELinux, Smack and AppArmor.
>>>>>
>>>>> Also clarify the properties of the returned string:
>>>>>
>>>>> * There is no NAME_MAX limit on the length; SELinux contexts can be
>>>>> longer than that. If the control buffer is too small, put_cmsg()
>>>>> truncates the data and sets MSG_CTRUNC.
>>>>>
>>>>> * Whether the string is null-terminated also depends on the LSM:
>>>>> SELinux includes the null byte in the length, but smack_to_secctx()
>>>>> in security/smack/smack_lsm.c uses strlen() and doesn't.
>>>> ...
>>> Ah, I can see that this is confusing; let me reformulate that without
>>> mentioning this strlen() implementation detail. Smack returns a
>>> buffer with a given size *without* including the null byte, roughly
>>> like this (simplified):
>>>
>>> int len = strlen(skp->smk_known);
>>> /* populate */
>>> cp->context = skp->smk_known;
>>> cp->len = len; <-- does not span the null byte
>>>
>>> Reformulating to:
>>>
>>> ...but smack_to_secctx() in security/smack/smack_lsm.c sends a
>>> security context that does not end in a null byte.
>>>
>>>>> Fixes: ffad6a017f91 (2018-07-28; "unix.7: Document SCM_SECURITY ancillary data")
>>>>> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
>>>>> Cc: Kuniyuki Iwashima <kuniyu@google.com>
>>>>> Assisted-by: LLM
>>>>> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
>>>>> ---
>>>>>
>>>>> Notes:
>>>>> This feature is also available in other LSMs. Unfortunately, they
>>>>> implemented it inconsistently and that complicates the description of
>>>>> how string boundaries are handled. Linux does indeed neither
>>>>> guarantee that this terminates with a NUL byte, nor that NAME_MAX is
>>>>> large enough to hold it.
>>>> ...
>>>>
>>>>>
>>>>> This is the verbose variant, but I am open for suggestions regarding
>>>>> what level of detail is appropriate here.
>>>>>
>>>>> man/man7/unix.7 | 25 +++++++++++++++++++------
>>>>> 1 file changed, 19 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/man/man7/unix.7 b/man/man7/unix.7
>>>>> index ded82768322b..4abd216d19c7 100644
>>>>> --- a/man/man7/unix.7
>>>>> +++ b/man/man7/unix.7
>>>>> @@ -317,7 +317,7 @@ and returned as the result of
>>>>> is an integer boolean flag.
>>>>> .TP
>>>>> .B SO_PASSSEC
>>>>> -Enables receiving of the SELinux security label of the peer socket
>>>>> +Enables receiving of the security label of the peer socket
>>>>> in an ancillary message of type
>>>>> .B SCM_SECURITY
>>>>> (see below).
>>>>> @@ -544,13 +544,26 @@ message, the
>>>>> option must be enabled on the socket.
>>>>> .TP
>>>>> .B SCM_SECURITY
>>>>> -Receive the SELinux security context (the security label)
>>>>> -of the peer socket.
>>>>> -The received ancillary data is a null-terminated string containing
>>>>> +Receive the security context (the security label)
>>>>> +of the peer socket,
>>>>> +as provided by the active Linux Security Module (LSM),
>>>>> +such as SELinux or Smack.
>>>>> +The received ancillary data is a string containing
>>>>> the security context.
>>>>> -The receiver should allocate at least
>>>>> +Whether the string includes a terminating null byte
>>>>> +depends on the LSM;
>>>> This seems to contradict the commit message. The commit message says
>>>> that the string is terminated, but that the reported length might or
>>>> might not be off-by-one (i.e., not count or count the '\0').
>>>>
>>>> This text, however, is saying that in some cases there might not be
>>>> a '\0' at all.
>>> The TL;DR is that the byte after the returned buffer's declared length
>>> can't be trusted to be 0 - it is undefined and can be clobbered.
>> Huh! This is to me a bug. Would you mind reporting them this as a bug
>> and CCing me? I'd rather get this fixed in the kernel than documented
>> as broken.
>>
>> Especially, if they use strlen(3) internally, this sounds very much like
>> a kernel bug, but even if not, it is clearly a kernel bug.
>>
>> In any case, if we were to document this bug, we should not use the term
>> string, because anything not containing a '\0' is not a string, by
>> definition.
> Casey, would you be able to confirm whether this constitutes a Smack
> bug or is intentional?
Inclusion of a null byte for C string interfaces has been a topic of
debate since about 1980. At the time this code was written my understanding
was that the data SCM_SECURITY returned could not be assumed to be a
C string. Hence, the size of the data, not the size of a string. The
null byte isn't considered a part of the string, as reported by strlen().
So, the existing behavior is intentional, but I'm willing to have it
considered a bug if (as of today) everyone thinks the data should include
a null byte.
> The TL;DR is that we came across the function smack_to_secctx() in
> smack_lsm.c, which passes a Smack label string in a buffer without a
> terminating null byte. This is inconsistent with what SELinux and
> AppArmor do.
>
> Before we start explaining so many corner cases in the man pages, I
> wanted to check -- is this something that Smack should fix, by
> including the zero byte?
>
> I tried to double check the Smack userspace utilities but couldn't
> find any use of SCM_SECURITY there. (Is the feature unused?)
The Smack userspace utilities (github.com://smackteam/smack.git)
represent a limited Smack system implementation. SCM_SECURITY is
used in at least a couple of important embedded and enterprise
implementations.
>>> I have not read the full kernel implementation now, but it can already
>>> be seen in userspace that that adjacent byte can belong to a different
>>> data structue:
>>>
>>>
>>> ## How control messages are represented
>>>
>>> The security context is returned to user space as a cmsghdr structure,
>>> as described in cmsg(3), where it is returned as a buffer of length
>>> cmsg_len:
>>>
>>> struct cmsghdr {
>>> size_t cmsg_len; /* data byte count including header */
>>> /* some other fields */
>>>
>>> /* followed by
>>> unsigned char cmsg_data[]; */
>>> };
>>>
>>> Reading beyond the declared cmsg_len is undefined, and callers don't
>>> get any guarantees about the byte following the csmg_data[] buffer.
>>>
>>>
>>> ## Iterating from userspace through multiple control messages
>>>
>>> Iterating through the cmsgs is done with the API described in cmsg(3),
>>> CMSG_NXTHDR(). This is implemented as an inlined function in
>>> /usr/include/bits/socket.h. The function does a bunch of validation
>>> logic and then ends in this rather simple advancement logic:
>>>
>>> __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
>>> + CMSG_ALIGN (__cmsg->cmsg_len));
>>> return __cmsg;
>>>
>>> So, the cmsgs with their cmsg_data[] buffers are next to each other in
>>> memory. They are aligned, but that still means that the byte after
>>> cmsg_data[] might be part of the next cmsg header or beyond the list
>>> of control messages.
>>>
>>> ---
>>>
>>>
>>> The more I think about this, the more unsure I am that this is even
>>> worth documenting. In the end, anyone reading and interpreting this
>>> data probably needs to read the corresponding LSM anyway, and trailing
>>> null bytes are probably the least of their worries...?
>> Not only that it's worth documenting, but this might be a vulnerability.
>>> Maybe it would be better to just say something like "The format of the
>>> security context is determined by the LSM responsible for it". WDYT?
>> I'm unwilling to accept a nonstring as a valid format, unless very good
>> reasons are stated. And if those reasons are stated as "that ship
>> sailed long ago", the way to document this might very well be BUGS.
> Point taken and agreed that it would be better to call it a "buffer"
> rather than a "string" when it does not have the null terminator.
>
> It does seem that this is used also outside of UNIX Domain Sockets:
> IP_PASSSEC(2const) says:
>
> The security context returned in the SCM_SECURITY ancillary message
> is of the same format as the one described in SO_PEERSEC(2const).
>
> And looking this format up in SO_PEERSEC(2const), we find:
>
> The security context string may include a terminating null character
> in the returned length, but is not guaranteed to do so: a security
> context "foo" might be represented as either {'f','o','o'} of length
> 3 or {'f','o','o','\0'} of length 4, which are considered to be
> interchangeable. The string is printable, does not contain non-
> terminating null characters, and is in an unspecified encoding (in
> particular, it is not guaranteed to be ASCII or UTF-8).
>
> So it seems that these "buffer" (not "string") semantics exist there
> as well. Maybe it is intentional then that it is treated as a buffer
> rather than a string?
I'm easy. If there is a strong desire to make SCM_SECURITY a string
Smack can be changed easily enough.
>
>
> I'm still leaning towards documenting it as a buffer with
> implementation-defined contents which are provided by a LSM. How
> these buffer contents are interpreted is depending on the LSM in use
> anyway.
>
> –Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-27 8:54 ` Günther Noack
@ 2026-10-27 21:46 ` Alejandro Colomar
2026-10-27 22:30 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-27 21:46 UTC (permalink / raw)
To: Günther Noack
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
[-- Attachment #1: Type: text/plain, Size: 2306 bytes --]
Hi Günther,
> Date: 2026-10-27 09:54:51+0100
> From: Günther Noack <gnoack3000@gmail.com>
>
> On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> > I'm still leaning towards documenting it as a buffer with
> > implementation-defined contents which are provided by a LSM. How
> > these buffer contents are interpreted is depending on the LSM in use
> > anyway.
>
> To make a more concrete and constructive wording proposal:
>
>
> SCM_SECURITY
>
> Receive the security context (the security label) of the peer
> socket, as provided by the active Linux Security Module (LSM). The
> received ancillary data is a byte buffer.
>
> The exact format of the security context buffer is defined by the
> active major LSM. For example, SELinux returns a SELinux label as a
> string (including a terminating null byte).
Let's pause the discussion of the specific text for now.
I have questions about the exact format used by each LSM. For example,
you say that SELinux guarantees a string. Does it count the '\0' as
part of the data size? Or is it guaranteed to exist but not counted?
Same question for the other LSMs.
Have a lovely night!
Alex
> Does that sound reasonable? Let me know what you think.
>
> I removed the wording "There is no fixed limit ...", because it should
> be a given that callers allocate enough buffer space for receiving and
> check the truncation flag. (The more important part is that we remove
> the previous wording which suggested that it would fit into NAME_MAX.)
>
> Given that SCM_SECURITY on "real" networks seems to have the same
> "buffer, not string" semantics, it feels fair to express it that way?
> People who want to read the security context will anyway need to read
> up on the exact format used by the LSM in order to attribute any
> meaning to it.
>
> –Günther
>
> P.S.: I had a hard time finding many usage examples. The main user of
> SCM_SECURITY seems to be systemd's journald, which uses it to log the
> SELinux security label. That code can deal with both null terminated
> strings and ones where it is missing (due to truncation), and there is
> a comment indicating that they are aware of possible truncation.
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-27 16:32 ` Casey Schaufler
@ 2026-10-27 21:52 ` Alejandro Colomar
0 siblings, 0 replies; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-27 21:52 UTC (permalink / raw)
To: Casey Schaufler
Cc: Günther Noack, linux-man, Michael Kerrisk, Kuniyuki Iwashima
[-- Attachment #1: Type: text/plain, Size: 6650 bytes --]
Hi Casey,
> Date: 2026-10-27 09:32:57-0700
> From: Casey Schaufler <casey@schaufler-ca.com>
>
[...]
> >>>> This text, however, is saying that in some cases there might not be
> >>>> a '\0' at all.
> >>> The TL;DR is that the byte after the returned buffer's declared length
> >>> can't be trusted to be 0 - it is undefined and can be clobbered.
> >> Huh! This is to me a bug. Would you mind reporting them this as a bug
> >> and CCing me? I'd rather get this fixed in the kernel than documented
> >> as broken.
> >>
> >> Especially, if they use strlen(3) internally, this sounds very much like
> >> a kernel bug, but even if not, it is clearly a kernel bug.
> >>
> >> In any case, if we were to document this bug, we should not use the term
> >> string, because anything not containing a '\0' is not a string, by
> >> definition.
> > Casey, would you be able to confirm whether this constitutes a Smack
> > bug or is intentional?
>
> Inclusion of a null byte for C string interfaces has been a topic of
> debate since about 1980. At the time this code was written my understanding
> was that the data SCM_SECURITY returned could not be assumed to be a
> C string. Hence, the size of the data, not the size of a string. The
> null byte isn't considered a part of the string, as reported by strlen().
>
> So, the existing behavior is intentional, but I'm willing to have it
> considered a bug if (as of today) everyone thinks the data should include
> a null byte.
Yup, I think the issue of strings has more or less settled towards using
C strings everywhere, with other formats --such as fixed-width buffers
from utmp(5)-- being phased out. Most of libc takes C strings, and so
using C strings everywhere is safer, as it avoids having to manually
handle the bytes.
> > The TL;DR is that we came across the function smack_to_secctx() in
> > smack_lsm.c, which passes a Smack label string in a buffer without a
> > terminating null byte. This is inconsistent with what SELinux and
> > AppArmor do.
> >
> > Before we start explaining so many corner cases in the man pages, I
> > wanted to check -- is this something that Smack should fix, by
> > including the zero byte?
> >
> > I tried to double check the Smack userspace utilities but couldn't
> > find any use of SCM_SECURITY there. (Is the feature unused?)
>
> The Smack userspace utilities (github.com://smackteam/smack.git)
> represent a limited Smack system implementation. SCM_SECURITY is
> used in at least a couple of important embedded and enterprise
> implementations.
>
> >>> I have not read the full kernel implementation now, but it can already
> >>> be seen in userspace that that adjacent byte can belong to a different
> >>> data structue:
> >>>
> >>>
> >>> ## How control messages are represented
> >>>
> >>> The security context is returned to user space as a cmsghdr structure,
> >>> as described in cmsg(3), where it is returned as a buffer of length
> >>> cmsg_len:
> >>>
> >>> struct cmsghdr {
> >>> size_t cmsg_len; /* data byte count including header */
> >>> /* some other fields */
> >>>
> >>> /* followed by
> >>> unsigned char cmsg_data[]; */
> >>> };
> >>>
> >>> Reading beyond the declared cmsg_len is undefined, and callers don't
> >>> get any guarantees about the byte following the csmg_data[] buffer.
> >>>
> >>>
> >>> ## Iterating from userspace through multiple control messages
> >>>
> >>> Iterating through the cmsgs is done with the API described in cmsg(3),
> >>> CMSG_NXTHDR(). This is implemented as an inlined function in
> >>> /usr/include/bits/socket.h. The function does a bunch of validation
> >>> logic and then ends in this rather simple advancement logic:
> >>>
> >>> __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
> >>> + CMSG_ALIGN (__cmsg->cmsg_len));
> >>> return __cmsg;
> >>>
> >>> So, the cmsgs with their cmsg_data[] buffers are next to each other in
> >>> memory. They are aligned, but that still means that the byte after
> >>> cmsg_data[] might be part of the next cmsg header or beyond the list
> >>> of control messages.
> >>>
> >>> ---
> >>>
> >>>
> >>> The more I think about this, the more unsure I am that this is even
> >>> worth documenting. In the end, anyone reading and interpreting this
> >>> data probably needs to read the corresponding LSM anyway, and trailing
> >>> null bytes are probably the least of their worries...?
> >> Not only that it's worth documenting, but this might be a vulnerability.
> >>> Maybe it would be better to just say something like "The format of the
> >>> security context is determined by the LSM responsible for it". WDYT?
> >> I'm unwilling to accept a nonstring as a valid format, unless very good
> >> reasons are stated. And if those reasons are stated as "that ship
> >> sailed long ago", the way to document this might very well be BUGS.
> > Point taken and agreed that it would be better to call it a "buffer"
> > rather than a "string" when it does not have the null terminator.
> >
> > It does seem that this is used also outside of UNIX Domain Sockets:
> > IP_PASSSEC(2const) says:
> >
> > The security context returned in the SCM_SECURITY ancillary message
> > is of the same format as the one described in SO_PEERSEC(2const).
> >
> > And looking this format up in SO_PEERSEC(2const), we find:
> >
> > The security context string may include a terminating null character
> > in the returned length, but is not guaranteed to do so: a security
> > context "foo" might be represented as either {'f','o','o'} of length
> > 3 or {'f','o','o','\0'} of length 4, which are considered to be
> > interchangeable. The string is printable, does not contain non-
> > terminating null characters, and is in an unspecified encoding (in
> > particular, it is not guaranteed to be ASCII or UTF-8).
> >
> > So it seems that these "buffer" (not "string") semantics exist there
> > as well. Maybe it is intentional then that it is treated as a buffer
> > rather than a string?
>
> I'm easy. If there is a strong desire to make SCM_SECURITY a string
> Smack can be changed easily enough.
Yup. I think it'd be good to have guarantees that the label can be
passed to strlen(3). Whether the reported size includes the '\0' or
not, that's less important, but being able to pass the buffer to
strlen(3) and any other string functions is essential for safety, IMO.
Thank you very much!
Have a lovely night!
Alex
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-27 21:46 ` Alejandro Colomar
@ 2026-10-27 22:30 ` Günther Noack
2026-10-27 22:59 ` Alejandro Colomar
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-27 22:30 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
Hello Alejandro!
On Tue, Oct 27, 2026 at 10:46:14PM +0100, Alejandro Colomar wrote:
> > Date: 2026-10-27 09:54:51+0100
> > From: Günther Noack <gnoack3000@gmail.com>
> >
> > On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> > > I'm still leaning towards documenting it as a buffer with
> > > implementation-defined contents which are provided by a LSM. How
> > > these buffer contents are interpreted is depending on the LSM in use
> > > anyway.
> >
> > To make a more concrete and constructive wording proposal:
> >
> >
> > SCM_SECURITY
> >
> > Receive the security context (the security label) of the peer
> > socket, as provided by the active Linux Security Module (LSM). The
> > received ancillary data is a byte buffer.
> >
> > The exact format of the security context buffer is defined by the
> > active major LSM. For example, SELinux returns a SELinux label as a
> > string (including a terminating null byte).
>
> Let's pause the discussion of the specific text for now.
>
> I have questions about the exact format used by each LSM. For example,
> you say that SELinux guarantees a string. Does it count the '\0' as
> part of the data size? Or is it guaranteed to exist but not counted?
>
> Same question for the other LSMs.
Yes, SELinux counts the '\0' as part of the buffer size for the
SCM_SECURITY security context.
Examples:
* If the label is "foo", it'll return {'f', 'o', 'o', '\0'} with payload size 4.
* If the reader calls recvmsg() but preallocates too little space in
the msg_control buffer, this can get truncated though, and then it
won't end with '\0':
{'e', 'x', 'a', 'm', 'p'} with payload size 5 (truncated)
Other LSMs:
* Smack excludes the null byte for SCM_SECURITY (smack_to_secctx())
(but irritatingly it does count the null byte when a label is
returned through SO_PEERSEC (smack_socket_getpeersec_stream()).
Both functions are in security/smack/smack_lsm.c.
* AppArmor excludes the null byte for SCM_SECURITY as well.
Implementation is in apparmor_label_to_secctx(), where it populates
the struct lsm_context *cp using:
len = aa_label_asxprint(&cp->context...)
and then sets
cp->len = len;
The function aa_label_asxprint() returns the length without trailing
null byte, as can be seen in its implementation.
SELinux, Smack and AppArmor are the only LSMs that implement the
secid_to_secctx() hook, which is the hook that defines the payload
contents. (For reference, the higher level common SCM logic like the
truncation is in net/core/scm.c.)
All reasoning is based on reading the code (with some AI assistance to
point me to the right places). I have not tried it out in a running
system, but it seems to check out.
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-27 22:30 ` Günther Noack
@ 2026-10-27 22:59 ` Alejandro Colomar
2026-10-28 6:19 ` Günther Noack
0 siblings, 1 reply; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-27 22:59 UTC (permalink / raw)
To: Günther Noack
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
[-- Attachment #1: Type: text/plain, Size: 3332 bytes --]
Hi Günther,
> Date: 2026-10-27 23:30:59+0100
> From: Günther Noack <gnoack3000@gmail.com>
>
> Hello Alejandro!
>
> On Tue, Oct 27, 2026 at 10:46:14PM +0100, Alejandro Colomar wrote:
> > > Date: 2026-10-27 09:54:51+0100
> > > From: Günther Noack <gnoack3000@gmail.com>
> > >
> > > On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> > > > I'm still leaning towards documenting it as a buffer with
> > > > implementation-defined contents which are provided by a LSM. How
> > > > these buffer contents are interpreted is depending on the LSM in use
> > > > anyway.
> > >
> > > To make a more concrete and constructive wording proposal:
> > >
> > >
> > > SCM_SECURITY
> > >
> > > Receive the security context (the security label) of the peer
> > > socket, as provided by the active Linux Security Module (LSM). The
> > > received ancillary data is a byte buffer.
> > >
> > > The exact format of the security context buffer is defined by the
> > > active major LSM. For example, SELinux returns a SELinux label as a
> > > string (including a terminating null byte).
> >
> > Let's pause the discussion of the specific text for now.
> >
> > I have questions about the exact format used by each LSM. For example,
> > you say that SELinux guarantees a string. Does it count the '\0' as
> > part of the data size? Or is it guaranteed to exist but not counted?
> >
> > Same question for the other LSMs.
>
> Yes, SELinux counts the '\0' as part of the buffer size for the
> SCM_SECURITY security context.
Ok.
>
> Examples:
> * If the label is "foo", it'll return {'f', 'o', 'o', '\0'} with payload size 4.
> * If the reader calls recvmsg() but preallocates too little space in
> the msg_control buffer, this can get truncated though, and then it
> won't end with '\0':
> {'e', 'x', 'a', 'm', 'p'} with payload size 5 (truncated)
Ouch! So, no string guarantees here either, actually.
> Other LSMs:
>
> * Smack excludes the null byte for SCM_SECURITY (smack_to_secctx())
> (but irritatingly it does count the null byte when a label is
> returned through SO_PEERSEC (smack_socket_getpeersec_stream()).
> Both functions are in security/smack/smack_lsm.c.
And as we've seen, no string guarantees, IIUC.
>
> * AppArmor excludes the null byte for SCM_SECURITY as well.
> Implementation is in apparmor_label_to_secctx(), where it populates
> the struct lsm_context *cp using:
>
> len = aa_label_asxprint(&cp->context...)
>
> and then sets
>
> cp->len = len;
>
> The function aa_label_asxprint() returns the length without trailing
> null byte, as can be seen in its implementation.
How does it behave if there's not enough space? Does AppArmor guarantee
a string?
Cheers,
Alex
> SELinux, Smack and AppArmor are the only LSMs that implement the
> secid_to_secctx() hook, which is the hook that defines the payload
> contents. (For reference, the higher level common SCM logic like the
> truncation is in net/core/scm.c.)
>
> All reasoning is based on reading the code (with some AI assistance to
> point me to the right places). I have not tried it out in a running
> system, but it seems to check out.
>
> –Günther
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-27 22:59 ` Alejandro Colomar
@ 2026-10-28 6:19 ` Günther Noack
2026-10-28 12:45 ` Alejandro Colomar
0 siblings, 1 reply; 35+ messages in thread
From: Günther Noack @ 2026-10-28 6:19 UTC (permalink / raw)
To: Alejandro Colomar
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
Hello Alejandro!
On Tue, Oct 27, 2026 at 11:59:15PM +0100, Alejandro Colomar wrote:
> > Date: 2026-10-27 23:30:59+0100
> > From: Günther Noack <gnoack3000@gmail.com>
> > On Tue, Oct 27, 2026 at 10:46:14PM +0100, Alejandro Colomar wrote:
> > > > Date: 2026-10-27 09:54:51+0100
> > > > From: Günther Noack <gnoack3000@gmail.com>
> > > >
> > > > On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> > > > > I'm still leaning towards documenting it as a buffer with
> > > > > implementation-defined contents which are provided by a LSM. How
> > > > > these buffer contents are interpreted is depending on the LSM in use
> > > > > anyway.
> > > >
> > > > To make a more concrete and constructive wording proposal:
> > > >
> > > >
> > > > SCM_SECURITY
> > > >
> > > > Receive the security context (the security label) of the peer
> > > > socket, as provided by the active Linux Security Module (LSM). The
> > > > received ancillary data is a byte buffer.
> > > >
> > > > The exact format of the security context buffer is defined by the
> > > > active major LSM. For example, SELinux returns a SELinux label as a
> > > > string (including a terminating null byte).
> > >
> > > Let's pause the discussion of the specific text for now.
> > >
> > > I have questions about the exact format used by each LSM. For example,
> > > you say that SELinux guarantees a string. Does it count the '\0' as
> > > part of the data size? Or is it guaranteed to exist but not counted?
> > >
> > > Same question for the other LSMs.
> >
> > Yes, SELinux counts the '\0' as part of the buffer size for the
> > SCM_SECURITY security context.
>
> Ok.
>
> >
> > Examples:
> > * If the label is "foo", it'll return {'f', 'o', 'o', '\0'} with payload size 4.
> > * If the reader calls recvmsg() but preallocates too little space in
> > the msg_control buffer, this can get truncated though, and then it
> > won't end with '\0':
> > {'e', 'x', 'a', 'm', 'p'} with payload size 5 (truncated)
>
> Ouch! So, no string guarantees here either, actually.
Correct. Callers have to deal with the possibility of truncation,
which strips away the null byte.
> > Other LSMs:
> >
> > * Smack excludes the null byte for SCM_SECURITY (smack_to_secctx())
> > (but irritatingly it does count the null byte when a label is
> > returned through SO_PEERSEC (smack_socket_getpeersec_stream()).
> > Both functions are in security/smack/smack_lsm.c.
>
> And as we've seen, no string guarantees, IIUC.
Correct.
> >
> > * AppArmor excludes the null byte for SCM_SECURITY as well.
> > Implementation is in apparmor_label_to_secctx(), where it populates
> > the struct lsm_context *cp using:
> >
> > len = aa_label_asxprint(&cp->context...)
> >
> > and then sets
> >
> > cp->len = len;
> >
> > The function aa_label_asxprint() returns the length without trailing
> > null byte, as can be seen in its implementation.
>
> How does it behave if there's not enough space? Does AppArmor guarantee
> a string?
The truncation case always strips off the null byte at the end of the
buffer. This is handled **independent of the LSM** in the common
net/core/scm.c layer one level above - it *always* kicks in when
truncation happens.
To sum it all up in a table: The only case where the null byte is
included in the buffer is in SELinux, when the generic SCM layer does
not need to do truncation:
normal case truncation case
--------------------------------------------------------------
SELinux has trailing null byte no trailing null byte
AppArmor no trailing null byte no trailing null byte
Smack no trailing null byte no trailing null byte
(other LSMs don't have the feature at all)
–Günther
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
2026-10-28 6:19 ` Günther Noack
@ 2026-10-28 12:45 ` Alejandro Colomar
0 siblings, 0 replies; 35+ messages in thread
From: Alejandro Colomar @ 2026-10-28 12:45 UTC (permalink / raw)
To: Günther Noack
Cc: linux-man, Michael Kerrisk, Kuniyuki Iwashima, Casey Schaufler
[-- Attachment #1: Type: text/plain, Size: 4900 bytes --]
Hi Günther,
> Date: 2026-10-28 07:19:28+0100
> From: Günther Noack <gnoack3000@gmail.com>
>
> Hello Alejandro!
>
> On Tue, Oct 27, 2026 at 11:59:15PM +0100, Alejandro Colomar wrote:
> > > Date: 2026-10-27 23:30:59+0100
> > > From: Günther Noack <gnoack3000@gmail.com>
> > > On Tue, Oct 27, 2026 at 10:46:14PM +0100, Alejandro Colomar wrote:
> > > > > Date: 2026-10-27 09:54:51+0100
> > > > > From: Günther Noack <gnoack3000@gmail.com>
> > > > >
> > > > > On Mon, Oct 26, 2026 at 11:41:13PM +0100, Günther Noack wrote:
> > > > > > I'm still leaning towards documenting it as a buffer with
> > > > > > implementation-defined contents which are provided by a LSM. How
> > > > > > these buffer contents are interpreted is depending on the LSM in use
> > > > > > anyway.
> > > > >
> > > > > To make a more concrete and constructive wording proposal:
> > > > >
> > > > >
> > > > > SCM_SECURITY
> > > > >
> > > > > Receive the security context (the security label) of the peer
> > > > > socket, as provided by the active Linux Security Module (LSM). The
> > > > > received ancillary data is a byte buffer.
> > > > >
> > > > > The exact format of the security context buffer is defined by the
> > > > > active major LSM. For example, SELinux returns a SELinux label as a
> > > > > string (including a terminating null byte).
> > > >
> > > > Let's pause the discussion of the specific text for now.
> > > >
> > > > I have questions about the exact format used by each LSM. For example,
> > > > you say that SELinux guarantees a string. Does it count the '\0' as
> > > > part of the data size? Or is it guaranteed to exist but not counted?
> > > >
> > > > Same question for the other LSMs.
> > >
> > > Yes, SELinux counts the '\0' as part of the buffer size for the
> > > SCM_SECURITY security context.
> >
> > Ok.
> >
> > >
> > > Examples:
> > > * If the label is "foo", it'll return {'f', 'o', 'o', '\0'} with payload size 4.
> > > * If the reader calls recvmsg() but preallocates too little space in
> > > the msg_control buffer, this can get truncated though, and then it
> > > won't end with '\0':
> > > {'e', 'x', 'a', 'm', 'p'} with payload size 5 (truncated)
> >
> > Ouch! So, no string guarantees here either, actually.
>
> Correct. Callers have to deal with the possibility of truncation,
> which strips away the null byte.
Is this true for every LSM? Do any LSMs guarantee a string even under
truncation?
> > > Other LSMs:
> > >
> > > * Smack excludes the null byte for SCM_SECURITY (smack_to_secctx())
> > > (but irritatingly it does count the null byte when a label is
> > > returned through SO_PEERSEC (smack_socket_getpeersec_stream()).
> > > Both functions are in security/smack/smack_lsm.c.
> >
> > And as we've seen, no string guarantees, IIUC.
>
> Correct.
>
> > >
> > > * AppArmor excludes the null byte for SCM_SECURITY as well.
> > > Implementation is in apparmor_label_to_secctx(), where it populates
> > > the struct lsm_context *cp using:
> > >
> > > len = aa_label_asxprint(&cp->context...)
> > >
> > > and then sets
> > >
> > > cp->len = len;
> > >
> > > The function aa_label_asxprint() returns the length without trailing
> > > null byte, as can be seen in its implementation.
> >
> > How does it behave if there's not enough space? Does AppArmor guarantee
> > a string?
>
> The truncation case always strips off the null byte at the end of the
> buffer. This is handled **independent of the LSM** in the common
> net/core/scm.c layer one level above - it *always* kicks in when
> truncation happens.
Hmmmm. I believe that layer should guarantee a null byte when it
truncates the data. It should be like strscpy(), which guarantees
a correct string even on truncation.
This seems to be another bug.
> To sum it all up in a table: The only case where the null byte is
> included in the buffer is in SELinux, when the generic SCM layer does
> not need to do truncation:
>
> normal case truncation case
> --------------------------------------------------------------
> SELinux has trailing null byte no trailing null byte
> AppArmor no trailing null byte no trailing null byte
> Smack no trailing null byte no trailing null byte
>
> (other LSMs don't have the feature at all)
Thanks for the table! This seems to me to be 3 bugs: one in AppArmor,
the same one in Smack, and one in the upper layer which corrupts the
string when truncating. I wonder if we can do better in the truncation
case, or if it's too late for that.
Would you mind CCing the maintainers of the upper layer in
net/core/scm.c?
Have a lovely day!
Alex
>
> –Günther
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2026-10-28 12:45 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21 21:22 [PATCH 0/7] unix.7: Socket Options and SCM_* fixes Günther Noack
2026-10-21 21:22 ` [PATCH 1/7] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions Günther Noack
2026-10-22 21:14 ` Alejandro Colomar
2026-10-23 16:50 ` Günther Noack
2026-10-24 4:45 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 2/7] man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message Günther Noack
2026-10-22 21:28 ` Alejandro Colomar
2026-10-23 17:09 ` Günther Noack
2026-10-21 21:22 ` [PATCH 3/7] man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD Günther Noack
2026-10-24 4:57 ` Kuniyuki Iwashima
2026-10-26 21:55 ` Günther Noack
2026-10-27 5:04 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux Günther Noack
2026-10-23 9:57 ` Alejandro Colomar
2026-10-23 17:57 ` Günther Noack
2026-10-23 18:13 ` Alejandro Colomar
2026-10-26 22:41 ` Günther Noack
2026-10-27 8:54 ` Günther Noack
2026-10-27 21:46 ` Alejandro Colomar
2026-10-27 22:30 ` Günther Noack
2026-10-27 22:59 ` Alejandro Colomar
2026-10-28 6:19 ` Günther Noack
2026-10-28 12:45 ` Alejandro Colomar
2026-10-27 16:32 ` Casey Schaufler
2026-10-27 21:52 ` Alejandro Colomar
2026-10-21 21:22 ` [PATCH 5/7] man/man7/unix.7: SO_PASSSEC: wfix Günther Noack
2026-10-24 5:02 ` Kuniyuki Iwashima
2026-10-24 8:36 ` Alejandro Colomar
2026-10-26 22:42 ` Günther Noack
2026-10-27 5:05 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 6/7] man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD Günther Noack
2026-10-24 5:22 ` Kuniyuki Iwashima
2026-10-26 23:02 ` Günther Noack
2026-10-27 5:06 ` Kuniyuki Iwashima
2026-10-21 21:22 ` [PATCH 7/7] man/man7/unix.7: Document SO_PASSRIGHTS Günther Noack
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox