All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Serge Hallyn (AMD)" <sergeh@kernel.org>
To: "Mickaël Salaün" <mic@digikod.net>
Cc: "James Morris" <jmorris@namei.org>,
	"Paul Moore" <paul@paul-moore.com>,
	"Serge Hallyn" <serge@hallyn.com>,
	"Ada Smith" <adasmithgt@gmail.com>,
	"Christian Brauner" <brauner@kernel.org>,
	"Günther Noack" <gnoack@google.com>,
	"John Johansen" <john.johansen@canonical.com>,
	"KP Singh" <kpsingh@kernel.org>,
	"Matt Bobrowski" <matt@bobrowski.net>,
	"Stephen Smalley" <stephen.smalley.work@gmail.com>,
	apparmor@lists.ubuntu.com, bpf@vger.kernel.org,
	kernel-team@cloudflare.com, linux-kernel@vger.kernel.org,
	linux-security-module@vger.kernel.org, selinux@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH 1/2] capabilities: Check PR_SET_SECUREBITS with ns_capable()
Date: Thu, 12 Nov 2026 07:02:54 -0600	[thread overview]
Message-ID: <avW4_r3IwLTNsXDg@shallyn-amd> (raw)
In-Reply-To: <20261110202811.2409395-2-mic@digikod.net>

On Tue, Nov 10, 2026 at 09:28:06PM +0100, Mickaël Salaün wrote:
> Per-process securebits were introduced with a direct cap_capable() check
> for CAP_SETPCAP.  The capable LSM hook and SELinux capability policy
> already existed, and SELinux forwarded task_prctl operations to
> commoncap.  The direct call therefore bypassed SELinux policy from the
> start.  It now also bypasses AppArmor, Landlock, and BPF LSM programs
> attached to the capable hook.
> 
> A task with CAP_SETPCAP in its effective set can consequently change
> privileged securebits despite an LSM denial.  This can alter how its
> capabilities evolve across UID and execution transitions without the
> expected LSM denial or audit record.
> 
> Use ns_capable(), as cap_prctl_drop() already does for PR_CAPBSET_DROP.
> Call it only for a no-op, which requires privilege for legacy reasons,
> or when a privileged bit changes.  Changes limited to
> SECURE_ALL_UNPRIVILEGED and their lock bits do not need the capability,
> so they must not invoke an LSM check or set PF_SUPERPRIV.  Successful
> privileged checks now set PF_SUPERPRIV, as other ns_capable() callers
> do.  Without other LSMs, the same requests remain allowed as before.
> 
> The check now reaches every capable hook before commoncap commits the
> new credentials.  A later task_prctl hook cannot provide equivalent
> mediation because commoncap runs first and commits the change itself.
> 
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Günther Noack <gnoack@google.com>
> Cc: James Morris <jmorris@namei.org>
> Cc: John Johansen <john.johansen@canonical.com>
> Cc: KP Singh <kpsingh@kernel.org>
> Cc: Matt Bobrowski <matt@bobrowski.net>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: Serge Hallyn <serge@hallyn.com>

The commit message is a bit wordy.  All it really needed to say was
that 1. s/cap_capable/ns_capable to query other lsms, and 2. move
the check to a concise helper.  I really do not relish looking through
a git log where every commit message re-litigates the full history of
any code that is touched or moved.

But it looks good, thanks.

Reviewed-by: Serge Hallyn (AMD) <sergeh@kernel.org>

> Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
> Cc: stable@vger.kernel.org
> Reported-by: Ada Smith <adasmithgt@gmail.com>
> Fixes: 3898b1b4ebff ("capabilities: implement per-process securebits")
> Signed-off-by: Mickaël Salaün <mic@digikod.net>
> ---
>  security/commoncap.c | 42 ++++++++++++++++++++----------------------
>  1 file changed, 20 insertions(+), 22 deletions(-)
> 
> diff --git a/security/commoncap.c b/security/commoncap.c
> index d47ab3022343..1947128396e2 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -1283,6 +1283,23 @@ static int cap_prctl_drop(unsigned long cap)
>  	return commit_creds(new);
>  }
>  
> +/*
> + * Doing anything with securebits requires privilege (go read about the
> + * "sendmail capabilities bug"), except for unprivileged bits.  Indeed, the
> + * SECURE_ALL_UNPRIVILEGED bits are not restrictions enforced by the kernel but
> + * by user space on itself.  For legacy reasons, a non-change requires
> + * privilege too.  Only checking CAP_SETPCAP when it is needed keeps LSMs from
> + * seeing (and logging) a capability check for unprivileged changes.
> + */
> +static bool securebits_need_setpcap(unsigned long old, unsigned long new)
> +{
> +	const unsigned long unpriv_and_locks = SECURE_ALL_UNPRIVILEGED |
> +					       SECURE_ALL_UNPRIVILEGED << 1;
> +	const unsigned long changed = old ^ new;
> +

FWIW, I think the code was clearer when the !changed was separate with a
one line comment above it, than rolled into this return.

> +	return !changed || (changed & ~unpriv_and_locks);
> +}
> +
>  /**
>   * cap_task_prctl - Implement process control functions for this security module
>   * @option: The process control function requested
> @@ -1346,28 +1363,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
>  			/* cannot change a locked bit */
>  			return -EPERM;
>  
> -		/*
> -		 * Doing anything requires privilege (go read about the
> -		 * "sendmail capabilities bug"), except for unprivileged bits.
> -		 * Indeed, the SECURE_ALL_UNPRIVILEGED bits are not
> -		 * restrictions enforced by the kernel but by user space on
> -		 * itself.
> -		 */
> -		if (cap_capable(current_cred(), current_cred()->user_ns,
> -				CAP_SETPCAP, CAP_OPT_NONE) != 0) {
> -			const unsigned long unpriv_and_locks =
> -				SECURE_ALL_UNPRIVILEGED |
> -				SECURE_ALL_UNPRIVILEGED << 1;
> -			const unsigned long changed = old->securebits ^ arg2;
> -
> -			/* For legacy reason, denies non-change. */
> -			if (!changed)
> -				return -EPERM;
> -
> -			/* Denies privileged changes. */
> -			if (changed & ~unpriv_and_locks)
> -				return -EPERM;
> -		}
> +		if (securebits_need_setpcap(old->securebits, arg2) &&
> +		    !ns_capable(current_user_ns(), CAP_SETPCAP))
> +			return -EPERM;
>  
>  		new = prepare_creds();
>  		if (!new)
> -- 
> 2.56.0
> 

  parent reply	other threads:[~2026-11-12 13:03 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 20:28 [PATCH 0/2] Fix LSM mediation of PR_SET_SECUREBITS Mickaël Salaün
2026-11-10 20:28 ` [PATCH 1/2] capabilities: Check PR_SET_SECUREBITS with ns_capable() Mickaël Salaün
2026-11-11  1:58   ` sashiko-bot
2026-11-12 13:02   ` Serge Hallyn (AMD) [this message]
2026-11-10 20:28 ` [PATCH 2/2] selftests/landlock: Test PR_SET_SECUREBITS mediation Mickaël Salaün
2026-11-11  2:06   ` sashiko-bot

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=avW4_r3IwLTNsXDg@shallyn-amd \
    --to=sergeh@kernel.org \
    --cc=adasmithgt@gmail.com \
    --cc=apparmor@lists.ubuntu.com \
    --cc=bpf@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=gnoack@google.com \
    --cc=jmorris@namei.org \
    --cc=john.johansen@canonical.com \
    --cc=kernel-team@cloudflare.com \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=matt@bobrowski.net \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=selinux@vger.kernel.org \
    --cc=serge@hallyn.com \
    --cc=stable@vger.kernel.org \
    --cc=stephen.smalley.work@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.