Re: [PATCH v3 1/1] security: Add CONFIG_LSM_AUTO to handle default LSM stack ordering

From: Kees Cook
Date: Mon Oct 17 2022 - 15:27:21 EST


[*double thread necromancy*]

On Mon, Feb 22, 2021 at 02:46:24PM -0800, Casey Schaufler wrote:
> It wouldn't. But compiling the new LSM mynewlsm doesn't add it to
> the list, either. Today no one should expect a LSM to be active if
> it hasn't been added to the CONFIG_LSM list. The proposed addition
> of CONFIG_LSM_AUTO would change that. "make oldconfig" would add
> security modules that are built to the list. This is unnecessary
> since whoever changed CONFIG_SECURITY_MYNEWLSM to "y" could easily
> have added it to CONFIG_LSM. In the right place.

Having CONFIG_LSM/lsm= is to support the migration away from having a
"default major LSM", but still provide a way to separate "built" vs
"enabled". As such, it needs to provide ordering. (So we have three
concepts here: "built" at all, "enabled" by default, and in a specific
"order".) And not being listed in CONFIG_LSM/lsm= means an LSM is
disabled.

I don't disagree about "anyone who enables a new LSM config can add it to
CONFIG_LSM", but really I think the question is why require an _ordering_
choice. Most distros and builders don't care beyond having the current
"default major LSM" come first, which leaves only the "enabled by
default" choice.

To review, security= currently only enables/disables apparmor, selinux,
smack, and tomoyo. It will go away once the full implementation of
stacking is finished.

I personally think it's reasonable that a "built" LSM be "enabled" by
default, however, this is not universally held to be true. :) The need
remains that enablement be configurable. The current solution here is
to add/remove it from CONFIG_LSM/lsm=. What remains problematic, though,
is a mismatch between lack of ordering causing disabling, but enabling
doesn't specify ordering. Ordering only matters for the legacy major
LSMs, which is controlled by CONFIG_DEFAULT_SECURITY_*.

Here is a reasonable overview of the main "lsm=" thread...
https://lore.kernel.org/all/CAGXu5jKqXNbEvPr1axQtGCCnWsGhDgjynW5u326mcx4vZ1oH8g@xxxxxxxxxxxxxx/
https://lore.kernel.org/all/abe03d09-4dcb-2b02-4102-5e108d617a42@xxxxxxxxxxxxx/
https://lore.kernel.org/all/CAGXu5jJtC1gkJ0ZKDFroL8UzvjiPfmC+6EsrzyB0j0oETdSQQg@xxxxxxxxxxxxxx/
https://lore.kernel.org/all/7741e4c1-cc54-4d04-a064-cb5388817058@xxxxxxxxxxxxx/
https://lore.kernel.org/all/CAGXu5jLKgrdhah-5TtAXDL-odbLGeyAUH2=PkAU769AkEnZFfQ@xxxxxxxxxxxxxx/
https://lore.kernel.org/all/5955f5ce-b803-4f58-8b07-54c291e33da5@xxxxxxxxxxxxx/
https://lore.kernel.org/all/CAGXu5jLBHN=YSs3Uh49bBJ1SRA1Km2UUD4j37GJJXiKhQq+KPA@xxxxxxxxxxxxxx/
https://lore.kernel.org/all/CAGXu5jJJit8bDNvgXaFkuvFPy7NWtJW2oRWFbG-6iWk0+A1qng@xxxxxxxxxxxxxx/
https://lore.kernel.org/all/88b0cc69-cd42-1798-6ce4-d3cfbbc79d83@xxxxxxxxxxxxx/
https://lore.kernel.org/all/alpine.LRH.2.21.1810051449110.2590@xxxxxxxxx/

I *still* think there should be a way to leave ordering alone and have
separate enable/disable control. And I think the growth of additional
LSMs that need explicit ordering supports this proposal.

What has become clear is that allowing _ordering_ to be generically
mutable is a mistake (and we had hints of this due to the standing
exceptions for "capability"). How about making these changes:

1) make ordering be source/"built"-controlled (i.e. similar to what
CONFIG_LSM_AUTO proposes)
2) have CONFIG_LSM/lsm= control only enable/disable and NOT ordering except
for the "major" LSMs.
3) introduce "lsm=+foo,-bar" that will enable/disable the given LSMs without
changing relative order.

I think of it like this. LSMs declare their ordering position (btw,
capability remains an exception to the existing logic, and this change
would begin to regularize it, IMO):

first: capability (cannot be disabled)
early: landlock,lockdown,yama,loadpin,safesetid,integrity
mutable: selinux,apparmor,smack,tomoyo
late: bpf
last: ...empty...

And "lsm=" can only change the order of the "mutable" ordering LSMs.

As an example:

Assuming The "built" order for all LSMs was defined as:
capability,landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,apparmor,smack,tomoyo,bfp

If CONFIG_LSM was: yama,integrity,apparmor,selinux,bpf,lockdown

a) without boot param
result would be: lsm=capability,yama,integrity,lockdown,apparmor,selinux,bpf

b) with boot param: lsm=selinux,lockdown,yama
result would be: lsm=capability,yama,lockdown,selinux

c) with boot param: lsm=-lockdown
result would be: lsm=capability,yama,lockdown,integrity,apparmor,selinux,bpf

d) with boot param: lsm=+setsetid
result would be: lsm=capability,yama,safesetid,integrity,lockdown,apparmor,selinux,bpf

Thoughts?

--
Kees Cook