Linux Manual Pages development
 help / color / mirror / Atom feed
From: "Günther Noack" <gnoack3000@gmail.com>
To: Alejandro Colomar <alx@kernel.org>
Cc: linux-man@vger.kernel.org,
	Michael Kerrisk <mtk.manpages@gmail.com>,
	Kuniyuki Iwashima <kuniyu@google.com>,
	Casey Schaufler <casey@schaufler-ca.com>
Subject: Re: [PATCH 4/7] man/man7/unix.7: SCM_SECURITY: Generalize to other LSMs, not just SELinux
Date: Mon, 26 Oct 2026 23:41:13 +0100	[thread overview]
Message-ID: <20261026.f6d2e191a08e@gnoack.org> (raw)
In-Reply-To: <atuiuCDEpf7H7I7J@debian>

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

  reply	other threads:[~2026-10-26 22:41 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261026.f6d2e191a08e@gnoack.org \
    --to=gnoack3000@gmail.com \
    --cc=alx@kernel.org \
    --cc=casey@schaufler-ca.com \
    --cc=kuniyu@google.com \
    --cc=linux-man@vger.kernel.org \
    --cc=mtk.manpages@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox