Re: [RFC] selinux: add selinux=2 boot parameter for permissive mode through kernel cmdline

From: Stephen Smalley

Date: Fri Mar 13 2026 - 10:45:00 EST


On Fri, Mar 13, 2026 at 2:12 AM Marwan Seliem <marwanmhks@xxxxxxxxx> wrote:
>
> Hi Paul, Stephen, Ondrej,
>
> I wanted to reach out to ask whether a change like the following would be considered useful or acceptable upstream, before investing more time polishing it.
>
> Background
> ----------
> On a platform with the following Kconfig:
>
> CONFIG_SECURITY_SELINUX_DEVELOP is not set
> CONFIG_SECURITY_SELINUX_BOOTPARAM=y
>
> The only runtime options for the selinux= boot parameter are:
>
> selinux=0 -> SELinux disabled entirely
> selinux=1 -> SELinux enforcing, non-switchable
>
> There is no way to boot into permissive mode without either enabling
> CONFIG_SECURITY_SELINUX_DEVELOP (which also enables setenforce and is
> not desirable in production) or disabling SELinux entirely.

Android handles this by neverallow'ing setenforce permission in their policy.
Hence, they can enable CONFIG_SECURITY_SELINUX_DEVELOP but prohibit
any userspace setenforce beyond the initial setenforce(1) by the init
program.

> Proposal
> --------
> Introduce selinux=2 as a new boot parameter value that boots SELinux
> in a permanently permissive mode:

This seems very unintuitive; would just use enforcing=0 as with the
DEVELOP case.

>
> - SELinux is fully initialized and policy is loaded normally
> - All AVC denials are logged but never enforced
> - The permissive state is non-switchable at runtime
>
> Implementation
> --------------
> The change is minimal, touching only two files:
>
> security/selinux/hooks.c:
> - Introduce selinux_permissive_boot __ro_after_init
> - Parse selinux=2 in selinux_enabled_setup(), set the flag
>
> security/selinux/include/security.h:
> - In the non-DEVELOP enforcing_enabled() path, return
> !(selinux_permissive_boot && state->initialized)
> instead of hardcoded true
>
> The initialized gate is intentional since, enforcing_enabled()
> returns false before policy is loaded, which causes systemd to observe
> a permissive+no-policy state and stall boot.

I'm a bit confused here. Why wouldn't policy be loaded, even if
booting permissive?
Regardless, I'm not sure how this is an improvement; a kernel write
vulnerability would still allow one to flip state->initialized at
runtime.

> Use case
> ---------
> The primary use case is embedded platforms shipping with
> enforcing locked at build time, where the ABL needs a mechanism to
> boot into permissive for debugging SELinux policy issues in the field,
> and without enabling DEVELOP in production builds.
>
> Note that the ABL will be protected by secure boot in production.
>
> Would a change like this be of interest upstream, or is there an
> existing mechanism I have missed that already covers this use case?
>
> Happy to send a proper patch if there is interest.
>
> Thanks,
> Marwan Seliem