Bug 1220090

Summary: SELinux - Kernel command line switch to prevent enforcing to permissive transition at runtime.
Product: [openSUSE] openSUSE Tumbleweed Reporter: William Brown <william.brown>
Component: SecurityAssignee: Cathy Hu <cathy.hu>
Status: NEW --- QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P5 - None CC: cathy.hu
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description William Brown 2024-02-20 00:14:30 UTC
SELinux as a MAC provider, is a powerful and important security boundary for servers running SUSE/OpenSUSE in the future.

However, it's currently possible for an escalated user to bypass this policy with permissive move on domains or as a whole with setenforce 0. 

In high-assurance environments, we should have a method that not only prevents disabling policy at runtime, but also that it's configuration can be measured and attested with a TPM for PCRs.

In my research I have found https://unix.stackexchange.com/questions/472731/is-it-possible-to-prevent-a-change-in-selinux-status-without-a-reboot which appears to allow a post-boot mechanism that prevents enforcing being disabled. However, this needs to be run each boot, could easily be avoided, and is unlikely to be measurable with a TPM.

I would like to suggest a kernel commandline flag, similar to the current `security=selinux selinux=1` arguments. Since kernel commandline (should) be part of a TPM measurement, this means that configuration of this value will influence PCR state. It also prevents modification at runtime without a disruptive (and obvious) reboot. 

I would suggest the flag is selinux=2 or selinux=3. This implies 1 (enforcing/enabled) but also that enforcing mode may not transition to permissive at any time during the machines operation.
Comment 1 Cathy Hu 2024-03-13 13:14:47 UTC
Hi William, I had a look and I think it is a cool idea, however we could accomplish this easier probably.

What we could do right now is for these use cases suggest to permanently enable the boolean with: 
setsebool -P secure_mode_policyload on

This prevents an override during reboot.

To disable this again, you would need to boot in permissive mode and disable the boolean and then boot again in enforcing mode.

What do you think about this approach? If you are okay with that, i could ask the docs team to maybe add a section describing this
Comment 2 William Brown 2024-03-14 01:39:59 UTC
> 
> What do you think about this approach? If you are okay with that, i could
> ask the docs team to maybe add a section describing this

Well, in attempting to set this up you get:

localhost:/home/admin # setsebool -P secure_mode_policyload on
SELinux:  Could not load policy file /etc/selinux/targeted/policy/policy.33:  Permission denied
/sbin/load_policy:  Can't load policy:  Permission denied
SELinux:  Could not load policy file /etc/selinux/targeted/policy/policy.33:  Permission denied
/sbin/load_policy:  Can't load policy:  Permission denied
Failed to commit changes to booleans: No such file or directory

Running under permissive, full list of AVCs are.

----
time->Thu Mar 14 11:32:02 2024
type=USER_START msg=audit(1710379922.977:80): pid=1492 uid=1000 auid=1000 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0 msg='op=PAM:session_open grantors=pam_keyinit,pam_limits,pam_unix,pam_umask,pam_env acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'
----
time->Thu Mar 14 11:33:23 2024
type=AVC msg=audit(1710380003.440:81): avc:  denied  { setbool } for  pid=1552 comm="setsebool" scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=system_u:object_r:security_t:s0 tclass=security permissive=1
----
time->Thu Mar 14 11:33:23 2024
type=USER_MAC_POLICY_LOAD msg=audit(1710380003.487:82): pid=805 uid=498 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  op=load_policy lsm=selinux seqno=2 res=1 exe="/usr/bin/dbus-daemon" sauid=498 hostname=? addr=? terminal=?'
----
time->Thu Mar 14 11:33:24 2024
type=AVC msg=audit(1710380004.157:83): avc:  denied  { load_policy } for  pid=1565 comm="load_policy" scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=system_u:object_r:security_t:s0 tclass=security permissive=1
----
time->Thu Mar 14 11:33:24 2024
type=USER_MAC_POLICY_LOAD msg=audit(1710380004.293:84): pid=805 uid=498 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  op=load_policy lsm=selinux seqno=3 res=1 exe="/usr/bin/dbus-daemon" sauid=498 hostname=? addr=? terminal=?'
----
time->Thu Mar 14 11:33:24 2024
type=MAC_POLICY_LOAD msg=audit(1710380004.327:85): auid=1000 ses=1 lsm=selinux res=1


So the question then is: Is that intended? It means from an enforcing system you can't enable the boolean. But in reverse, it also means on an enforcing system you *can't* disable it either which is somewhat the intended behaviour.


Saying this, it doesn't actually address the issue. 

Remember, the goal here isn't just to prevent the policy changing. It's to have a way to *attest that* with PCR measurement into a TPM. The kernel command line (should) be part of that measurement, which is why having this setting as a kernel command line argument is desirable. It means that if you were to alter the command line and reboot, the TPM attestation would then deny the release of secrets.

The goal here is to have a system where we can have system components that in high security envs work if and only if selinux is enabled and enforcing, and that is a gateway to those services being able to access TPM secrets.
Comment 3 Cathy Hu 2024-03-19 14:49:12 UTC
I had a chat with the future technologies team about this, so i guess this are 2 problems:

1) the setsebool errors -> I will fix that, is on my todo

2) it seems we have the TPM measurement for the kernel boot params already in MicroOS+ALP and it can be probably also enabled in tw
Comment 4 William Brown 2024-03-19 23:17:49 UTC
> 2) it seems we have the TPM measurement for the kernel boot params already
> in MicroOS+ALP and it can be probably also enabled in tw

Yeah I know, that's why I was suggesting that it's a boot parameter to enable the selinux "can't be disable" setting to be included so it can become part of the TPM policy.