unix.7: Socket Options and SCM_* fixes
v2 cover unix.7: Socket Options and SCM_* fixes
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 of v1 and v2 of the still-joined patch set, as well as of v1 of the split patch set.
Changes in v2 (split):
* Mention commit hashes in commit messages, not in groff comments
* Reword __scm_send() code snippet in commit message
* s/the last one takes effect/the last one is sent/
* Rewrite SCM_SECURITY section to be about byte buffers and independent of the LSM
* New commit:
* Remove mentions of "namespace" in the general sense
Changes in v1 (split):
* 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.
v1: https://lore.kernel.org/all/[email protected]/
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.
Günther Noack (8):
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: Remove mentions of "namespace" in the general sense
man/man7/unix.7 | 215 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 195 insertions(+), 20 deletions(-)
Signature · 1 line
2.56.0
PATCH v2 1/8 man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
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").
---
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(-)
man/man7/unix.7 +6 -2
@@ -775,10 +775,14 @@ .SH ERRORS 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)
Signature · 1 line
2.56.0
Alejandro Colomar
AppliedRe: [PATCH v2 1/8] man/man7/unix.7: ERRORS: ETOOMANYREFS: Fix the conditions
Hi Günther,
Quoted 24 lines
Date: 2026-11-03 21:22:03+0100
From: Günther Noack <[email protected]>The ETOOMANYREFS error is detected in
too_many_unix_fds()innet/unix/af_unix.cwhen the user's (not the processes') in-flight FDs exceedRLIMIT_NOFILE, and the process has neitherCAP_SYS_RESOURCEnorCAP_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 <[email protected]>Cc Willy Tarreau <[email protected]>Cc Kuniyuki Iwashima <[email protected]>Assisted-by LLMReviewed-by Kuniyuki Iwashima <[email protected]>Reviewed-by Alejandro Colomar <[email protected]>Signed-off-by Günther Noack <[email protected]>
Quoted 1 line
---
I've applied this patch. Thanks!
Cheers,
Alex
Quoted 33 lines
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(-)man/man7/unix.7 +6
-2@@ -775,10 +775,14 @@ .SH ERRORS 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)Signature · 1 line
2.56.0
Signature · 1 line
<https://www.alejandro-colomar.es>
PATCH v2 2/8 man/man7/unix.7: Multiple same-typed SCM_* messages may be sent in one message
In reply to Günther NoackIn the 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.
---
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(-)
man/man7/unix.7 +18 -1
@@ -538,7 +538,24 @@ .SS Ancillary messages .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 is sent. .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
Signature · 1 line
2.56.0
PATCH v2 3/8 man/man7/unix.7: Autobind: Clarify when it happens, and mention SO_PASSPIDFD
In reply to Günther NoackAutobind 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.
---
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 | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
man/man7/unix.7 +19 -5
@@ -296,8 +296,14 @@ .SS Socket options .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)
@@ -365,10 +371,18 @@ .SS Autobind feature 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 +.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
Signature · 1 line
2.56.0
PATCH v2 4/8 man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
In reply to Günther NoackReword 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.
As clarified in [1], the returned security context is in the general case a byte buffer, not a null-terminated string. The only LSM that returns a buffer with trailing null byte is SELinux, but even that is not guaranteed in case that the message is truncated.
---
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.
After confirmation from Kuniyuki Iwashima, this documents it as returning a byte buffer.
I prefer this variant over the previous longer one, also because it refers to the individual LSMs for the exact format. A reader of the security context will require LSM-specific documentation anyway to interpret the security context.
This patch is still LLM-assisted, but at this point, since everything is rewritten now, the only LLM-assisted part is the discovery that this part of the documentation could be improved.
man/man7/unix.7 | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
man/man7/unix.7 +11 -8
@@ -312,7 +312,7 @@ .SS Socket options 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).
@@ -538,13 +538,16 @@ .SS Ancillary messages 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 -the security context. -The receiver should allocate at least -.B NAME_MAX -bytes in the data portion of the ancillary message for this data. +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. +.IP +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). .IP To receive the security context, the .B SO_PASSSEC
Signature · 1 line
2.56.0
PATCH v2 5/8 man/man7/unix.7: SO_PASSSEC: wfix
In reply to Günther NoackUse "security context", as in the description of SCM_SECURITY.
--- man/man7/unix.7 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
man/man7/unix.7 +1 -1
@@ -312,7 +312,7 @@ .SS Socket options 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).
Signature · 1 line
2.56.0
PATCH v2 6/8 man/man7/unix.7: Document SO_PASSPIDFD, SO_PEERPIDFD, and SCM_PIDFD
In reply to Günther NoackThese 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.
--- man/man7/unix.7 | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+)
man/man7/unix.7 +100 -0
@@ -311,6 +311,32 @@ .SS Socket options .BR getsockopt (2) is an integer boolean flag. .TP +.BR SO_PASSPIDFD " (since Linux 6.5)" +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
@@ -362,6 +388,43 @@ .SS Socket options .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
@@ -537,6 +600,42 @@ .SS Ancillary messages .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,
@@ -1252,6 +1351,7 @@ .SS Program source and .BR seccomp_unotify (2). .SH SEE ALSO +.BR pidfd_open (2), .BR recvmsg (2), .BR sendmsg (2), .BR socket (2),
Signature · 1 line
2.56.0
PATCH v2 7/8 man/man7/unix.7: Document SO_PASSRIGHTS
In reply to Günther NoackSO_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.
--- man/man7/unix.7 | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
man/man7/unix.7 +37 -0
@@ -337,6 +337,35 @@ .SS Socket options .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
@@ -871,6 +900,14 @@ .SH ERRORS 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
Signature · 1 line
2.56.0
PATCH v2 8/8 man/man7/unix.7: Remove mentions of "namespace" in the general sense
In reply to Günther NoackIn unix(7), the word "namespace" is often used in the general sense of the word, which becomes confusing now that the man page also discusses its interaction with the Linux namespace concept (see namespaces(7)).
Remove the remaining uses of the word "namespace" in the places where it is not referring to Linux namespaces.
--- man/man7/unix.7 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
man/man7/unix.7 +6 -6
@@ -24,8 +24,8 @@ .SH DESCRIPTION efficiently. Traditionally, UNIX domain sockets can be either unnamed, or bound to a filesystem pathname (marked as being of type socket). -Linux also supports an abstract namespace which is independent of the -filesystem. +Linux also supports an abstract socket addressing scheme, +which is independent of the filesystem. .P Valid socket types in the UNIX domain are: .BR SOCK_STREAM ,
@@ -135,7 +135,7 @@ .SS Address format by the fact that .I sun_path[0] is a null byte (\[aq]\[rs]0\[aq]). -The socket's address in this namespace is given by the additional +The socket's address is given by the additional bytes in .I sun_path that are covered by the specified length of the address structure.
@@ -297,7 +297,7 @@ .SS Socket options ancillary data. .IP 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 +the socket is autobound to a unique abstract socket name when .BR connect (2) or
@@ -323,7 +323,7 @@ .SS Socket options 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 +the socket is autobound to a unique abstract socket name when .BR connect (2) or
@@ -975,7 +975,7 @@ .SH ERRORS See the appropriate manual pages for more information. .SH VERSIONS .B SCM_CREDENTIALS -and the abstract namespace were introduced with Linux 2.2 and should not +and abstract sockets were introduced with Linux 2.2 and should not be used in portable programs. (Some BSD-derived systems also support credential passing, but the implementation details differ.)
Signature · 1 line
2.56.0