v2:
- add "lsm.order=" and CONFIG_LSM_ORDER instead of overloading "security="
- reorganize introduction of ordering logic code
Updated cover letter:
This refactors the LSM registration and initialization infrastructure
to more centrally support different LSM types. What was considered a
"major" LSM is kept for legacy use of the "security=" boot parameter,
and now overlaps with the new class of "exclusive" LSMs for the future
blob sharing (to be added later). The "minor" LSMs become more well
defined as a result of the refactoring.
Instead of continuing to (somewhat improperly) overload the kernel's
initcall system, this changes the LSM infrastructure to store a
registration structure (struct lsm_info) table instead, where metadata
about each LSM can be recorded (name, flags, order, enable flag, init
function). This can be extended in the future to include things like
required blob size for the coming "blob sharing" LSMs.
The "major" LSMs had to individually negotiate which of them should be
enabled. This didn't provide a way to negotiate combinations of other
LSMs (as will be needed for "blob sharing" LSMs). This is solved by
providing the LSM infrastructure with all the details needed to make
the choice (exposing the per-LSM "enabled" flag, if used, the LSM
characteristics, and ordering expectations).
As a result of the refactoring, the "minor" LSMs are able to remove
the open-coded security_add_hooks() calls for "capability", "yama",
and "loadpin", and to redefine "integrity" properly as a general LSM.
(Note that "integrity" actually defined _no_ hooks, but needs the early
initialization).
With all LSMs being proessed centrally, it was possible to implement
a new boot parameter "lsm.order=" to provide explicit ordering, which
is helpful for the future "blob sharing" LSMs. Matching this is the
new CONFIG_LSM_ORDER, which replaces CONFIG_DEFAULT_SECURITY, as it
provides a higher granularity of control.
To better show LSMs activation some debug reporting was added (enabled
with the "lsm.debug" boot commandline option).
Finally, I added a WARN() around LSM initialization failures, which
appear to have always been silently ignored. (Realistically any LSM init
failures would have only been due to catastrophic kernel issues that
would render a system unworkable anyway, but it'd be better to expose
the problem as early as possible.)
-Kees
Kees Cook (26):
LSM: Correctly announce start of LSM initialization
vmlinux.lds.h: Avoid copy/paste of security_init section
LSM: Rename .security_initcall section to .lsm_info
LSM: Remove initcall tracing
LSM: Convert from initcall to struct lsm_info
vmlinux.lds.h: Move LSM_TABLE into INIT_DATA
LSM: Convert security_initcall() into DEFINE_LSM()
LSM: Record LSM name in struct lsm_info
LSM: Provide init debugging infrastructure
LSM: Don't ignore initialization failures
LSM: Introduce LSM_FLAG_LEGACY_MAJOR
LSM: Provide separate ordered initialization
LSM: Plumb visibility into optional "enabled" state
LSM: Lift LSM selection out of individual LSMs
LSM: Introduce lsm.enable= and lsm.disable=
LSM: Prepare for reorganizing "security=" logic
LSM: Refactor "security=" in terms of enable/disable
LSM: Build ordered list of ordered LSMs for init
LSM: Introduce CONFIG_LSM_ORDER
LSM: Introduce "lsm.order=" for boottime ordering
LoadPin: Initialize as ordered LSM
Yama: Initialize as ordered LSM
LSM: Introduce enum lsm_order
capability: Mark as LSM_ORDER_FIRST
LSM: Separate idea of "major" LSM from "exclusive" LSM
LSM: Add all exclusive LSMs to ordered initialization
.../admin-guide/kernel-parameters.txt | 7 +
arch/arc/kernel/vmlinux.lds.S | 1 -
arch/arm/kernel/vmlinux-xip.lds.S | 1 -
arch/arm64/kernel/vmlinux.lds.S | 1 -
arch/h8300/kernel/vmlinux.lds.S | 1 -
arch/microblaze/kernel/vmlinux.lds.S | 2 -
arch/powerpc/kernel/vmlinux.lds.S | 2 -
arch/um/include/asm/common.lds.S | 2 -
arch/xtensa/kernel/vmlinux.lds.S | 1 -
include/asm-generic/vmlinux.lds.h | 25 +-
include/linux/init.h | 2 -
include/linux/lsm_hooks.h | 43 ++-
include/linux/module.h | 1 -
security/Kconfig | 42 +--
security/apparmor/lsm.c | 16 +-
security/commoncap.c | 8 +-
security/integrity/iint.c | 5 +-
security/loadpin/loadpin.c | 10 +-
security/security.c | 304 ++++++++++++++----
security/selinux/hooks.c | 16 +-
security/smack/smack_lsm.c | 8 +-
security/tomoyo/tomoyo.c | 7 +-
security/yama/yama_lsm.c | 7 +-
23 files changed, 348 insertions(+), 164 deletions(-)
--
2.17.1
Provide a way to reorder LSM initialization using the new "lsm.order="
comma-separated list of LSMs. Any LSMs not listed will be added in builtin
order.
Signed-off-by: Kees Cook <[email protected]>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
security/security.c | 15 ++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 32d323ee9218..5ac4c1056ffa 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2276,6 +2276,11 @@
lsm.debug [SECURITY] Enable LSM initialization debugging output.
+ lsm.order=lsm1,...,lsmN
+ [SECURITY] Choose order of LSM initialization. Any
+ builtin LSMs not listed here will be implicitly
+ added to the list in builtin order.
+
machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb
diff --git a/security/security.c b/security/security.c
index 063ee2466e58..4db194f81419 100644
--- a/security/security.c
+++ b/security/security.c
@@ -43,6 +43,7 @@ static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
char *lsm_names;
/* Boot-time LSM user choice */
static __initdata const char *chosen_major_lsm;
+static __initdata const char *chosen_lsm_order;
static __initconst const char * const builtin_lsm_order = CONFIG_LSM_ORDER;
@@ -136,11 +137,15 @@ static void __init parse_lsm_order(const char *order, const char *origin)
kfree(sep);
}
-/* Populate ordered LSMs list from builtin list of LSMs. */
+/* Populate ordered LSMs list from commandline and builtin list of LSMs. */
static void __init prepare_lsm_order(void)
{
struct lsm_info *lsm;
+ /* Parse order from commandline, if present. */
+ if (chosen_lsm_order)
+ parse_lsm_order(chosen_lsm_order, "cmdline");
+
/* Parse order from builtin list. */
parse_lsm_order(builtin_lsm_order, "builtin");
@@ -264,6 +269,14 @@ static int __init choose_major_lsm(char *str)
}
__setup("security=", choose_major_lsm);
+/* Explicitly choose LSM initialization order. */
+static int __init choose_lsm_order(char *str)
+{
+ chosen_lsm_order = str;
+ return 1;
+}
+__setup("lsm.order=", choose_lsm_order);
+
/* Enable LSM order debugging. */
static int __init enable_debug(char *str)
{
--
2.17.1
In preparation for lifting the "is this LSM enabled?" logic out of the
individual LSMs, pass in any special enabled state tracking (as needed
for SELinux, AppArmor, and LoadPin). This must be an "int" to include
handling cases where "enabled" is exposed via sysctl which has no "bool"
type (i.e. LoadPin's use).
LoadPin's "enabled" tracking will be added later when it gets added to
the "ordered LSM" stack.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 1 +
security/apparmor/lsm.c | 5 +++--
security/selinux/hooks.c | 1 +
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 38cbefabff71..118e12f678df 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2044,6 +2044,7 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count,
struct lsm_info {
const char *name; /* Populated automatically. */
unsigned long flags; /* Optional: flags describing LSM */
+ int *enabled; /* Optional: NULL means enabled. */
int (*init)(void);
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 4c5f63e9aeba..d03133a267f2 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1303,8 +1303,8 @@ bool aa_g_paranoid_load = true;
module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO);
/* Boot time disable flag */
-static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-module_param_named(enabled, apparmor_enabled, bool, S_IRUGO);
+static int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_named(enabled, apparmor_enabled, int, 0444);
static int __init apparmor_enabled_setup(char *str)
{
@@ -1608,5 +1608,6 @@ static int __init apparmor_init(void)
DEFINE_LSM(apparmor)
.flags = LSM_FLAG_LEGACY_MAJOR,
+ .enabled = &apparmor_enabled,
.init = apparmor_init,
END_LSM;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 615cf6498c0f..3f999ed98cfd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7204,6 +7204,7 @@ void selinux_complete_init(void)
all processes and objects when they are created. */
DEFINE_LSM(selinux)
.flags = LSM_FLAG_LEGACY_MAJOR,
+ .enabled = &selinux_enabled,
.init = selinux_init,
END_LSM;
--
2.17.1
This has identical functionality to the existing per-LSM enable handling,
but provides a centralized place to perform it. If multiple instances
of a parameter (either with the custom LSM-specific parameter or the
"lsm.{enable,disable}" parameter) for a specific LSM are on the boot
command line, the last one takes precedent.
Disabling an LSM means it will not be considered when performing
initializations. Enabling an LSM means either undoing a previous disabling
or a undoing a default-disabled CONFIG setting.
For example: "lsm.disable=apparmor apparmor.enabled=1" will leave
AppArmor enabled. "selinux.enabled=0 lsm.enable=selinux" will leave
SELinux enabled.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 47 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/security/security.c b/security/security.c
index 85533d4e534a..72d1ef2fc4cc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -53,10 +53,29 @@ static bool debug __initdata;
} while (0)
/* Mark an LSM's enabled flag, if it exists. */
+static int lsm_enabled_true __initdata = 1;
+static int lsm_enabled_false __initdata = 0;
static void __init set_enabled(struct lsm_info *lsm, bool enabled)
{
- if (lsm->enabled)
+ if (!lsm->enabled) {
+ /*
+ * If the LSM hasn't configured an enable flag, we
+ * can use a hard-coded setting for storing the
+ * state ourselves.
+ */
+ if (enabled)
+ lsm->enabled = &lsm_enabled_true;
+ else
+ lsm->enabled = &lsm_enabled_false;
+ } else if (lsm->enabled == &lsm_enabled_true) {
+ if (!enabled)
+ lsm->enabled = &lsm_enabled_false;
+ } else if (lsm->enabled == &lsm_enabled_false) {
+ if (enabled)
+ lsm->enabled = &lsm_enabled_true;
+ } else {
*lsm->enabled = enabled;
+ }
}
/* Is an LSM allowed to be enabled? */
@@ -169,6 +188,32 @@ static int __init enable_debug(char *str)
}
__setup("lsm.debug", enable_debug);
+/* Explicitly enable an LSM */
+static int __init enable_lsm(char *str)
+{
+ struct lsm_info *lsm;
+
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if (strcmp(str, lsm->name) == 0)
+ set_enabled(lsm, true);
+ }
+ return 1;
+}
+__setup("lsm.enable=", enable_lsm);
+
+/* Explicitly disable an LSM */
+static int __init disable_lsm(char *str)
+{
+ struct lsm_info *lsm;
+
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if (strcmp(str, lsm->name) == 0)
+ set_enabled(lsm, false);
+ }
+ return 1;
+}
+__setup("lsm.disable=", disable_lsm);
+
static bool match_last_lsm(const char *list, const char *lsm)
{
const char *last;
--
2.17.1
This adds a flag for the current "major" LSMs to distinguish them when
we have a universal method for ordering all LSMs. It's called "legacy"
since the distinction of "major" will go away in the blob-sharing world.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 3 +++
security/apparmor/lsm.c | 1 +
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
security/tomoyo/tomoyo.c | 1 +
5 files changed, 7 insertions(+)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 543636f18152..38cbefabff71 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2039,8 +2039,11 @@ extern char *lsm_names;
extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
+#define LSM_FLAG_LEGACY_MAJOR (1 << 0)
+
struct lsm_info {
const char *name; /* Populated automatically. */
+ unsigned long flags; /* Optional: flags describing LSM */
int (*init)(void);
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 7fa7b4464cf4..4c5f63e9aeba 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1607,5 +1607,6 @@ static int __init apparmor_init(void)
}
DEFINE_LSM(apparmor)
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.init = apparmor_init,
END_LSM;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 469a90806bc6..615cf6498c0f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7203,6 +7203,7 @@ void selinux_complete_init(void)
/* SELinux requires early initialization in order to label
all processes and objects when they are created. */
DEFINE_LSM(selinux)
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.init = selinux_init,
END_LSM;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1e1ace718e75..4aef844fc0e2 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4883,5 +4883,6 @@ static __init int smack_init(void)
* all processes and objects when they are created.
*/
DEFINE_LSM(smack)
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.init = smack_init,
END_LSM;
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index a280d4eab456..528b6244a648 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -551,5 +551,6 @@ static int __init tomoyo_init(void)
}
DEFINE_LSM(tomoyo)
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.init = tomoyo_init,
END_LSM;
--
2.17.1
LSM initialization failures have traditionally been ignored. We should
at least WARN when something goes wrong.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/security/security.c b/security/security.c
index ee49b921d750..1f055936a746 100644
--- a/security/security.c
+++ b/security/security.c
@@ -55,10 +55,12 @@ static bool debug __initdata;
static void __init major_lsm_init(void)
{
struct lsm_info *lsm;
+ int ret;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
init_debug("initializing %s\n", lsm->name);
- lsm->init();
+ ret = lsm->init();
+ WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
}
}
--
2.17.1
Booting with "lsm.debug" will report future details on how LSM ordering
decisions are being made.
Signed-off-by: Kees Cook <[email protected]>
---
.../admin-guide/kernel-parameters.txt | 2 ++
security/security.c | 18 ++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 9871e649ffef..32d323ee9218 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2274,6 +2274,8 @@
ltpc= [NET]
Format: <io>,<irq>,<dma>
+ lsm.debug [SECURITY] Enable LSM initialization debugging output.
+
machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb
diff --git a/security/security.c b/security/security.c
index e74f46fba591..ee49b921d750 100644
--- a/security/security.c
+++ b/security/security.c
@@ -12,6 +12,8 @@
* (at your option) any later version.
*/
+#define pr_fmt(fmt) "LSM: " fmt
+
#include <linux/bpf.h>
#include <linux/capability.h>
#include <linux/dcache.h>
@@ -43,11 +45,19 @@ char *lsm_names;
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
+static bool debug __initdata;
+#define init_debug(...) \
+ do { \
+ if (debug) \
+ pr_info(__VA_ARGS__); \
+ } while (0)
+
static void __init major_lsm_init(void)
{
struct lsm_info *lsm;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ init_debug("initializing %s\n", lsm->name);
lsm->init();
}
}
@@ -91,6 +101,14 @@ static int __init choose_lsm(char *str)
}
__setup("security=", choose_lsm);
+/* Enable LSM order debugging. */
+static int __init enable_debug(char *str)
+{
+ debug = true;
+ return 1;
+}
+__setup("lsm.debug", enable_debug);
+
static bool match_last_lsm(const char *list, const char *lsm)
{
const char *last;
--
2.17.1
In preparation for making LSM selections outside of the LSMs, include
the name of LSMs in struct lsm_info.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 02ec717189f9..543636f18152 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2040,16 +2040,20 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
struct lsm_info {
+ const char *name; /* Populated automatically. */
int (*init)(void);
};
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
#define DEFINE_LSM(lsm) \
+ static const char __lsm_name_##lsm[] __initconst \
+ __aligned(1) = #lsm; \
static struct lsm_info __lsm_##lsm \
__used __section(.lsm_info.init) \
__aligned(sizeof(unsigned long)) \
= { \
+ .name = __lsm_name_##lsm, \
#define END_LSM }
--
2.17.1
This provides a place for ordered LSMs to be initialized, separate from
the "major" LSMs. This is mainly a copy/paste from major_lsm_init() to
ordered_lsm_init(), but it will change drastically in later patches.
What is not obvious in the patch is that this change moves the integrity
LSM from major_lsm_init() into ordered_lsm_init(), since it is not marked
with the LSM_FLAG_LEGACY_MAJOR. As it is the only LSM in the "ordered"
list, there is no reordering yet created.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/security/security.c b/security/security.c
index 1f055936a746..a886a978214a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -52,12 +52,30 @@ static bool debug __initdata;
pr_info(__VA_ARGS__); \
} while (0)
+static void __init ordered_lsm_init(void)
+{
+ struct lsm_info *lsm;
+ int ret;
+
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
+ continue;
+
+ init_debug("initializing %s\n", lsm->name);
+ ret = lsm->init();
+ WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+ }
+}
+
static void __init major_lsm_init(void)
{
struct lsm_info *lsm;
int ret;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+ continue;
+
init_debug("initializing %s\n", lsm->name);
ret = lsm->init();
WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
@@ -87,6 +105,9 @@ int __init security_init(void)
yama_add_hooks();
loadpin_add_hooks();
+ /* Load LSMs in specified order. */
+ ordered_lsm_init();
+
/*
* Load all the remaining security modules.
*/
--
2.17.1
Since the struct lsm_info table is not an initcall, we can just move it
into INIT_DATA like all the other tables.
Signed-off-by: Kees Cook <[email protected]>
---
arch/arc/kernel/vmlinux.lds.S | 1 -
arch/arm/kernel/vmlinux-xip.lds.S | 1 -
arch/arm64/kernel/vmlinux.lds.S | 1 -
arch/h8300/kernel/vmlinux.lds.S | 1 -
arch/microblaze/kernel/vmlinux.lds.S | 2 --
arch/powerpc/kernel/vmlinux.lds.S | 2 --
arch/um/include/asm/common.lds.S | 2 --
arch/xtensa/kernel/vmlinux.lds.S | 1 -
include/asm-generic/vmlinux.lds.h | 24 +++++++++++-------------
9 files changed, 11 insertions(+), 24 deletions(-)
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..8fb16bdabdcf 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
INIT_SETUP(L1_CACHE_BYTES)
INIT_CALLS
CON_INITCALL
- SECURITY_INITCALL
}
.init.arch.info : {
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 3593d5c1acd2..8c74037ade22 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -96,7 +96,6 @@ SECTIONS
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
- SECURITY_INITCALL
INIT_RAM_FS
}
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 605d1b60469c..7d23d591b03c 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -166,7 +166,6 @@ SECTIONS
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
- SECURITY_INITCALL
INIT_RAM_FS
*(.init.rodata.* .init.bss) /* from the EFI stub */
}
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index 35716a3048de..49f716c0a1df 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -56,7 +56,6 @@ SECTIONS
__init_begin = .;
INIT_TEXT_SECTION(4)
INIT_DATA_SECTION(4)
- SECURITY_INIT
__init_end = .;
_edata = . ;
_begin_data = LOADADDR(.data);
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..e1f3e8741292 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -117,8 +117,6 @@ SECTIONS {
CON_INITCALL
}
- SECURITY_INIT
-
__init_end_before_initramfs = .;
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 07ae018e550e..105a976323aa 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -212,8 +212,6 @@ SECTIONS
CON_INITCALL
}
- SECURITY_INIT
-
. = ALIGN(8);
__ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
__start___ftr_fixup = .;
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index 7adb4e6b658a..4049f2c46387 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -53,8 +53,6 @@
CON_INITCALL
}
- SECURITY_INIT
-
.exitcall : {
__exitcall_begin = .;
*(.exitcall.exit)
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index a1c3edb8ad56..b727b18a68ac 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -197,7 +197,6 @@ SECTIONS
INIT_SETUP(XCHAL_ICACHE_LINESIZE)
INIT_CALLS
CON_INITCALL
- SECURITY_INITCALL
INIT_RAM_FS
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 5079a969e612..b31ea8bdfef9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -203,6 +203,15 @@
#define EARLYCON_TABLE()
#endif
+#ifdef CONFIG_SECURITY
+#define LSM_TABLE() . = ALIGN(8); \
+ __start_lsm_info = .; \
+ KEEP(*(.lsm_info.init)) \
+ __end_lsm_info = .;
+#else
+#define LSM_TABLE()
+#endif
+
#define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name)
#define __OF_TABLE(cfg, name) ___OF_TABLE(cfg, name)
#define OF_TABLE(cfg, name) __OF_TABLE(IS_ENABLED(cfg), name)
@@ -597,7 +606,8 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(timer) \
- EARLYCON_TABLE()
+ EARLYCON_TABLE() \
+ LSM_TABLE()
#define INIT_TEXT \
*(.init.text .init.text.*) \
@@ -786,17 +796,6 @@
KEEP(*(.con_initcall.init)) \
__con_initcall_end = .;
-#define SECURITY_INITCALL \
- __start_lsm_info = .; \
- KEEP(*(.lsm_info.init)) \
- __end_lsm_info = .;
-
-/* Older linker script style for security init. */
-#define SECURITY_INIT \
- .lsm_info.init : AT(ADDR(.lsm_info.init) - LOAD_OFFSET) { \
- LSM_INFO \
- }
-
#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(4); \
@@ -963,7 +962,6 @@
INIT_SETUP(initsetup_align) \
INIT_CALLS \
CON_INITCALL \
- SECURITY_INITCALL \
INIT_RAM_FS \
}
--
2.17.1
This provides a way to declare LSM initialization order via Kconfig.
Signed-off-by: Kees Cook <[email protected]>
---
security/Kconfig | 11 +++++++++++
security/security.c | 38 +++++++++++++++++++++++++++++++++++---
2 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/security/Kconfig b/security/Kconfig
index 27d8b2688f75..de8202886c1d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -276,5 +276,16 @@ config DEFAULT_SECURITY
default "apparmor" if DEFAULT_SECURITY_APPARMOR
default "" if DEFAULT_SECURITY_DAC
+config LSM_ORDER
+ string "Default initialization order of builtin LSMs"
+ default "integrity"
+ help
+ A comma-separated list of LSMs, in initialization order.
+ Any LSMs left off this list will be link-order initialized
+ after any listed LSMs. Any LSMs listed here but not built in
+ the kernel will be ignored.
+
+ If unsure, leave this as the default.
+
endmenu
diff --git a/security/security.c b/security/security.c
index 2541a512a0f7..063ee2466e58 100644
--- a/security/security.c
+++ b/security/security.c
@@ -44,6 +44,8 @@ char *lsm_names;
/* Boot-time LSM user choice */
static __initdata const char *chosen_major_lsm;
+static __initconst const char * const builtin_lsm_order = CONFIG_LSM_ORDER;
+
/* Ordered list of LSMs to initialize. */
static __initdata struct lsm_info **ordered_lsms;
@@ -108,14 +110,44 @@ static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
(!lsm->enabled || *lsm->enabled) ? "en" : "dis");
}
-/* Populate ordered LSMs list from hard-coded list of LSMs. */
+/* Populate ordered LSMs list from given string. */
+static void __init parse_lsm_order(const char *order, const char *origin)
+{
+ struct lsm_info *lsm;
+ char *sep, *name, *next;
+
+ sep = kstrdup(order, GFP_KERNEL);
+ next = sep;
+ /* Walk the list, looking for matching LSMs. */
+ while ((name = strsep(&next, ",")) != NULL) {
+ bool found = false;
+
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
+ strcmp(lsm->name, name) == 0) {
+ append_ordered_lsm(lsm, origin);
+ found = true;
+ }
+ }
+
+ if (!found)
+ init_debug("%s ignored: %s\n", origin, name);
+ }
+ kfree(sep);
+}
+
+/* Populate ordered LSMs list from builtin list of LSMs. */
static void __init prepare_lsm_order(void)
{
struct lsm_info *lsm;
+ /* Parse order from builtin list. */
+ parse_lsm_order(builtin_lsm_order, "builtin");
+
+ /* Add any missing LSMs, in link order. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if (strcmp(lsm->name, "integrity") == 0)
- append_ordered_lsm(lsm, "builtin");
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+ append_ordered_lsm(lsm, "link-time");
}
}
--
2.17.1
Instead of using argument-based initializers, switch to defining the
contents of struct lsm_info on a per-LSM basis. This also drops
the final use of the now inaccurate "initcall" naming.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 6 ++++--
security/apparmor/lsm.c | 4 +++-
security/integrity/iint.c | 4 +++-
security/selinux/hooks.c | 4 +++-
security/smack/smack_lsm.c | 4 +++-
security/tomoyo/tomoyo.c | 4 +++-
6 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index ad04761e5587..02ec717189f9 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2045,11 +2045,13 @@ struct lsm_info {
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
-#define security_initcall(lsm) \
+#define DEFINE_LSM(lsm) \
static struct lsm_info __lsm_##lsm \
__used __section(.lsm_info.init) \
__aligned(sizeof(unsigned long)) \
- = { .init = lsm, }
+ = { \
+
+#define END_LSM }
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
/*
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8b8b70620bbe..7fa7b4464cf4 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1606,4 +1606,6 @@ static int __init apparmor_init(void)
return error;
}
-security_initcall(apparmor_init);
+DEFINE_LSM(apparmor)
+ .init = apparmor_init,
+END_LSM;
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 70d21b566955..20e60df929a3 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -175,7 +175,9 @@ static int __init integrity_iintcache_init(void)
0, SLAB_PANIC, init_once);
return 0;
}
-security_initcall(integrity_iintcache_init);
+DEFINE_LSM(integrity)
+ .init = integrity_iintcache_init,
+END_LSM;
/*
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad9a9b8e9979..469a90806bc6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7202,7 +7202,9 @@ void selinux_complete_init(void)
/* SELinux requires early initialization in order to label
all processes and objects when they are created. */
-security_initcall(selinux_init);
+DEFINE_LSM(selinux)
+ .init = selinux_init,
+END_LSM;
#if defined(CONFIG_NETFILTER)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 340fc30ad85d..1e1ace718e75 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4882,4 +4882,6 @@ static __init int smack_init(void)
* Smack requires early initialization in order to label
* all processes and objects when they are created.
*/
-security_initcall(smack_init);
+DEFINE_LSM(smack)
+ .init = smack_init,
+END_LSM;
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 9f932e2d6852..a280d4eab456 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -550,4 +550,6 @@ static int __init tomoyo_init(void)
return 0;
}
-security_initcall(tomoyo_init);
+DEFINE_LSM(tomoyo)
+ .init = tomoyo_init,
+END_LSM;
--
2.17.1
In preparation for doing more interesting LSM init probing, this converts
the existing initcall system into an explicit call into a function pointer
from a section-collected struct lsm_info array.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/init.h | 2 --
include/linux/lsm_hooks.h | 12 ++++++++++++
include/linux/module.h | 1 -
security/integrity/iint.c | 1 +
security/security.c | 14 +++++---------
5 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/include/linux/init.h b/include/linux/init.h
index 77636539e77c..9c2aba1dbabf 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -133,7 +133,6 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
#endif
extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
-extern initcall_entry_t __start_lsm_info[], __end_lsm_info[];
/* Used for contructor calls. */
typedef void (*ctor_fn_t)(void);
@@ -236,7 +235,6 @@ extern bool initcall_debug;
static exitcall_t __exitcall_##fn __exit_call = fn
#define console_initcall(fn) ___define_initcall(fn,, .con_initcall)
-#define security_initcall(fn) ___define_initcall(fn,, .lsm_info)
struct obs_kernel_param {
const char *str;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 97a020c616ad..ad04761e5587 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2039,6 +2039,18 @@ extern char *lsm_names;
extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
+struct lsm_info {
+ int (*init)(void);
+};
+
+extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
+
+#define security_initcall(lsm) \
+ static struct lsm_info __lsm_##lsm \
+ __used __section(.lsm_info.init) \
+ __aligned(sizeof(unsigned long)) \
+ = { .init = lsm, }
+
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
/*
* Assuring the safety of deleting a security module is up to
diff --git a/include/linux/module.h b/include/linux/module.h
index f807f15bebbe..264979283756 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -123,7 +123,6 @@ extern void cleanup_module(void);
#define late_initcall_sync(fn) module_init(fn)
#define console_initcall(fn) module_init(fn)
-#define security_initcall(fn) module_init(fn)
/* Each module must use one module_init(). */
#define module_init(initfn) \
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 5a6810041e5c..70d21b566955 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -22,6 +22,7 @@
#include <linux/file.h>
#include <linux/uaccess.h>
#include <linux/security.h>
+#include <linux/lsm_hooks.h>
#include "integrity.h"
static struct rb_root integrity_iint_tree = RB_ROOT;
diff --git a/security/security.c b/security/security.c
index 41a5da2c7faf..e74f46fba591 100644
--- a/security/security.c
+++ b/security/security.c
@@ -43,16 +43,12 @@ char *lsm_names;
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
-static void __init do_security_initcalls(void)
+static void __init major_lsm_init(void)
{
- initcall_t call;
- initcall_entry_t *ce;
+ struct lsm_info *lsm;
- ce = __start_lsm_info;
- while (ce < __end_lsm_info) {
- call = initcall_from_entry(ce);
- call();
- ce++;
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ lsm->init();
}
}
@@ -82,7 +78,7 @@ int __init security_init(void)
/*
* Load all the remaining security modules.
*/
- do_security_initcalls();
+ major_lsm_init();
return 0;
}
--
2.17.1
As a prerequisite to adjusting LSM selection logic in the future, this
moves the selection logic up out of the individual major LSMs, making
their init functions only run when actually enabled.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 1 -
security/apparmor/lsm.c | 6 ---
security/security.c | 76 ++++++++++++++++++++++----------------
security/selinux/hooks.c | 10 -----
security/smack/smack_lsm.c | 3 --
security/tomoyo/tomoyo.c | 2 -
6 files changed, 45 insertions(+), 53 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 118e12f678df..ec1c0a97dfe3 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2091,7 +2091,6 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
#define __lsm_ro_after_init __ro_after_init
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
-extern int __init security_module_enable(const char *module);
extern void __init capability_add_hooks(void);
#ifdef CONFIG_SECURITY_YAMA
extern void __init yama_add_hooks(void);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index d03133a267f2..5399c2f03536 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1542,12 +1542,6 @@ static int __init apparmor_init(void)
{
int error;
- if (!apparmor_enabled || !security_module_enable("apparmor")) {
- aa_info_message("AppArmor disabled by boot time parameter");
- apparmor_enabled = false;
- return 0;
- }
-
aa_secids_init();
error = aa_setup_dfa_engine();
diff --git a/security/security.c b/security/security.c
index a886a978214a..85533d4e534a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -52,33 +52,70 @@ static bool debug __initdata;
pr_info(__VA_ARGS__); \
} while (0)
+/* Mark an LSM's enabled flag, if it exists. */
+static void __init set_enabled(struct lsm_info *lsm, bool enabled)
+{
+ if (lsm->enabled)
+ *lsm->enabled = enabled;
+}
+
+/* Is an LSM allowed to be enabled? */
+static bool __init lsm_allowed(struct lsm_info *lsm)
+{
+ /* Skip if the LSM is disabled. */
+ if (lsm->enabled && !*lsm->enabled)
+ return false;
+
+ /* Skip major-specific checks if not a major LSM. */
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+ return true;
+
+ /* Disabled if this LSM isn't the chosen one. */
+ if (strcmp(lsm->name, chosen_lsm) != 0)
+ return false;
+
+ return true;
+}
+
+/* Check if LSM should be enabled. Mark any that are disabled. */
+static void __init maybe_initialize_lsm(struct lsm_info *lsm)
+{
+ int enabled = lsm_allowed(lsm);
+
+ /* Record enablement. */
+ set_enabled(lsm, enabled);
+
+ /* If selected, initialize the LSM. */
+ if (enabled) {
+ int ret;
+
+ init_debug("initializing %s\n", lsm->name);
+ ret = lsm->init();
+ WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+ }
+}
+
static void __init ordered_lsm_init(void)
{
struct lsm_info *lsm;
- int ret;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
continue;
- init_debug("initializing %s\n", lsm->name);
- ret = lsm->init();
- WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+ maybe_initialize_lsm(lsm);
}
}
static void __init major_lsm_init(void)
{
struct lsm_info *lsm;
- int ret;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
continue;
- init_debug("initializing %s\n", lsm->name);
- ret = lsm->init();
- WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+ maybe_initialize_lsm(lsm);
}
}
@@ -168,29 +205,6 @@ static int lsm_append(char *new, char **result)
return 0;
}
-/**
- * security_module_enable - Load given security module on boot ?
- * @module: the name of the module
- *
- * Each LSM must pass this method before registering its own operations
- * to avoid security registration races. This method may also be used
- * to check if your LSM is currently loaded during kernel initialization.
- *
- * Returns:
- *
- * true if:
- *
- * - The passed LSM is the one chosen by user at boot time,
- * - or the passed LSM is configured as the default and the user did not
- * choose an alternate LSM at boot time.
- *
- * Otherwise, return false.
- */
-int __init security_module_enable(const char *module)
-{
- return !strcmp(module, chosen_lsm);
-}
-
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3f999ed98cfd..409a9252aeb6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7133,16 +7133,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
static __init int selinux_init(void)
{
- if (!security_module_enable("selinux")) {
- selinux_enabled = 0;
- return 0;
- }
-
- if (!selinux_enabled) {
- pr_info("SELinux: Disabled at boot.\n");
- return 0;
- }
-
pr_info("SELinux: Initializing.\n");
memset(&selinux_state, 0, sizeof(selinux_state));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 4aef844fc0e2..e79fad43a8e3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4834,9 +4834,6 @@ static __init int smack_init(void)
struct cred *cred;
struct task_smack *tsp;
- if (!security_module_enable("smack"))
- return 0;
-
smack_inode_cache = KMEM_CACHE(inode_smack, 0);
if (!smack_inode_cache)
return -ENOMEM;
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 528b6244a648..39bb994ebe09 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -540,8 +540,6 @@ static int __init tomoyo_init(void)
{
struct cred *cred = (struct cred *) current_cred();
- if (!security_module_enable("tomoyo"))
- return 0;
/* register ourselves with the security framework */
security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
printk(KERN_INFO "TOMOYO Linux initialized\n");
--
2.17.1
This partially reverts commit 58eacfffc417 ("init, tracing: instrument
security and console initcall trace events") since security init calls
are about to no longer resemble regular init calls.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/security/security.c b/security/security.c
index 892fe6b691cf..41a5da2c7faf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -30,8 +30,6 @@
#include <linux/string.h>
#include <net/flow.h>
-#include <trace/events/initcall.h>
-
#define MAX_LSM_EVM_XATTR 2
/* Maximum number of letters for an LSM name string */
@@ -47,17 +45,13 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
static void __init do_security_initcalls(void)
{
- int ret;
initcall_t call;
initcall_entry_t *ce;
ce = __start_lsm_info;
- trace_initcall_level("security");
while (ce < __end_lsm_info) {
call = initcall_from_entry(ce);
- trace_initcall_start(call);
- ret = call();
- trace_initcall_finish(call, ret);
+ call();
ce++;
}
}
--
2.17.1
For a while now, the LSM core has said it was "initializED", rather than
"initializING". This adjust the report to be more accurate (i.e. before
this was reported before any LSMs had been initialized.)
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/security.c b/security/security.c
index 736e78da1ab9..4cbcf244a965 100644
--- a/security/security.c
+++ b/security/security.c
@@ -72,10 +72,11 @@ int __init security_init(void)
int i;
struct hlist_head *list = (struct hlist_head *) &security_hook_heads;
+ pr_info("Security Framework initializing\n");
+
for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
i++)
INIT_HLIST_HEAD(&list[i]);
- pr_info("Security Framework initialized\n");
/*
* Load minor LSMs, with the capability module always first.
--
2.17.1
Avoid copy/paste by defining SECURITY_INIT in terms of SECURITY_INITCALL.
Signed-off-by: Kees Cook <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 7b75ff6e2fce..934a45395547 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -473,13 +473,6 @@
#define RODATA RO_DATA_SECTION(4096)
#define RO_DATA(align) RO_DATA_SECTION(align)
-#define SECURITY_INIT \
- .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
- __security_initcall_start = .; \
- KEEP(*(.security_initcall.init)) \
- __security_initcall_end = .; \
- }
-
/*
* .text section. Map to function alignment to avoid address changes
* during second ld run in second ld pass when generating System.map
@@ -798,6 +791,12 @@
KEEP(*(.security_initcall.init)) \
__security_initcall_end = .;
+/* Older linker script style for security init. */
+#define SECURITY_INIT \
+ .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
+ SECURITY_INITCALL \
+ }
+
#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(4); \
--
2.17.1
In preparation for switching from initcall to just a regular set of
pointers in a section, rename the internal section name.
Signed-off-by: Kees Cook <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 10 +++++-----
include/linux/init.h | 4 ++--
security/security.c | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 934a45395547..5079a969e612 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -787,14 +787,14 @@
__con_initcall_end = .;
#define SECURITY_INITCALL \
- __security_initcall_start = .; \
- KEEP(*(.security_initcall.init)) \
- __security_initcall_end = .;
+ __start_lsm_info = .; \
+ KEEP(*(.lsm_info.init)) \
+ __end_lsm_info = .;
/* Older linker script style for security init. */
#define SECURITY_INIT \
- .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
- SECURITY_INITCALL \
+ .lsm_info.init : AT(ADDR(.lsm_info.init) - LOAD_OFFSET) { \
+ LSM_INFO \
}
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/include/linux/init.h b/include/linux/init.h
index 2538d176dd1f..77636539e77c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -133,7 +133,7 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
#endif
extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
-extern initcall_entry_t __security_initcall_start[], __security_initcall_end[];
+extern initcall_entry_t __start_lsm_info[], __end_lsm_info[];
/* Used for contructor calls. */
typedef void (*ctor_fn_t)(void);
@@ -236,7 +236,7 @@ extern bool initcall_debug;
static exitcall_t __exitcall_##fn __exit_call = fn
#define console_initcall(fn) ___define_initcall(fn,, .con_initcall)
-#define security_initcall(fn) ___define_initcall(fn,, .security_initcall)
+#define security_initcall(fn) ___define_initcall(fn,, .lsm_info)
struct obs_kernel_param {
const char *str;
diff --git a/security/security.c b/security/security.c
index 4cbcf244a965..892fe6b691cf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -51,9 +51,9 @@ static void __init do_security_initcalls(void)
initcall_t call;
initcall_entry_t *ce;
- ce = __security_initcall_start;
+ ce = __start_lsm_info;
trace_initcall_level("security");
- while (ce < __security_initcall_end) {
+ while (ce < __end_lsm_info) {
call = initcall_from_entry(ce);
trace_initcall_start(call);
ret = call();
--
2.17.1
This moves the string handling for "security=" boot parameter into
a stored pointer instead of a string duplicate. This will allow
easier handling of the string when switching logic to use the coming
enable/disable infrastructure.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/security/security.c b/security/security.c
index 72d1ef2fc4cc..5cacbcefbc32 100644
--- a/security/security.c
+++ b/security/security.c
@@ -34,16 +34,12 @@
#define MAX_LSM_EVM_XATTR 2
-/* Maximum number of letters for an LSM name string */
-#define SECURITY_NAME_MAX 10
-
struct security_hook_heads security_hook_heads __lsm_ro_after_init;
static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
char *lsm_names;
/* Boot-time LSM user choice */
-static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
- CONFIG_DEFAULT_SECURITY;
+static __initdata const char *chosen_major_lsm;
static bool debug __initdata;
#define init_debug(...) \
@@ -90,7 +86,7 @@ static bool __init lsm_allowed(struct lsm_info *lsm)
return true;
/* Disabled if this LSM isn't the chosen one. */
- if (strcmp(lsm->name, chosen_lsm) != 0)
+ if (strcmp(lsm->name, chosen_major_lsm) != 0)
return false;
return true;
@@ -154,6 +150,9 @@ int __init security_init(void)
i++)
INIT_HLIST_HEAD(&list[i]);
+ if (!chosen_major_lsm)
+ chosen_major_lsm = CONFIG_DEFAULT_SECURITY;
+
/*
* Load minor LSMs, with the capability module always first.
*/
@@ -173,12 +172,12 @@ int __init security_init(void)
}
/* Save user chosen LSM */
-static int __init choose_lsm(char *str)
+static int __init choose_major_lsm(char *str)
{
- strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
+ chosen_major_lsm = str;
return 1;
}
-__setup("security=", choose_lsm);
+__setup("security=", choose_major_lsm);
/* Enable LSM order debugging. */
static int __init enable_debug(char *str)
--
2.17.1
For what are marked as the Legacy Major LSMs, make them effectively
exclusive when selected on the "security=" boot parameter, to handle
the future case of when a previously major LSMs become non-exclusive
(e.g. when TOMOYO starts blob-sharing).
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/security/security.c b/security/security.c
index 5cacbcefbc32..25a019cc4a2b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -81,14 +81,6 @@ static bool __init lsm_allowed(struct lsm_info *lsm)
if (lsm->enabled && !*lsm->enabled)
return false;
- /* Skip major-specific checks if not a major LSM. */
- if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
- return true;
-
- /* Disabled if this LSM isn't the chosen one. */
- if (strcmp(lsm->name, chosen_major_lsm) != 0)
- return false;
-
return true;
}
@@ -150,8 +142,24 @@ int __init security_init(void)
i++)
INIT_HLIST_HEAD(&list[i]);
+ /* Process "security=", if given. */
if (!chosen_major_lsm)
chosen_major_lsm = CONFIG_DEFAULT_SECURITY;
+ if (chosen_major_lsm) {
+ struct lsm_info *lsm;
+
+ /*
+ * To match the original "security=" behavior, this
+ * explicitly does NOT fallback to another Legacy Major
+ * if the selected one was separately disabled: disable
+ * all non-matching Legacy Major LSMs.
+ */
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) &&
+ strcmp(lsm->name, chosen_major_lsm) != 0)
+ set_enabled(lsm, false);
+ }
+ }
/*
* Load minor LSMs, with the capability module always first.
--
2.17.1
This removes CONFIG_DEFAULT_SECURITY in favor of the explicit build-time
ordering offered by CONFIG_LSM_ORDER, and adds all the exclusive LSMs
to the ordered LSM initialization.
Signed-off-by: Kees Cook <[email protected]>
---
security/Kconfig | 39 +--------------------------------------
security/security.c | 23 +----------------------
2 files changed, 2 insertions(+), 60 deletions(-)
diff --git a/security/Kconfig b/security/Kconfig
index 33c9ac3cb759..a2e365420919 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -239,46 +239,9 @@ source security/yama/Kconfig
source security/integrity/Kconfig
-choice
- prompt "Default security module"
- default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
- default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
- default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
- default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
- default DEFAULT_SECURITY_DAC
-
- help
- Select the security module that will be used by default if the
- kernel parameter security= is not specified.
-
- config DEFAULT_SECURITY_SELINUX
- bool "SELinux" if SECURITY_SELINUX=y
-
- config DEFAULT_SECURITY_SMACK
- bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y
-
- config DEFAULT_SECURITY_TOMOYO
- bool "TOMOYO" if SECURITY_TOMOYO=y
-
- config DEFAULT_SECURITY_APPARMOR
- bool "AppArmor" if SECURITY_APPARMOR=y
-
- config DEFAULT_SECURITY_DAC
- bool "Unix Discretionary Access Controls"
-
-endchoice
-
-config DEFAULT_SECURITY
- string
- default "selinux" if DEFAULT_SECURITY_SELINUX
- default "smack" if DEFAULT_SECURITY_SMACK
- default "tomoyo" if DEFAULT_SECURITY_TOMOYO
- default "apparmor" if DEFAULT_SECURITY_APPARMOR
- default "" if DEFAULT_SECURITY_DAC
-
config LSM_ORDER
string "Default initialization order of builtin LSMs"
- default "yama,loadpin,integrity"
+ default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list will be link-order initialized
diff --git a/security/security.c b/security/security.c
index f076fdc6b451..628e62fda5fe 100644
--- a/security/security.c
+++ b/security/security.c
@@ -130,7 +130,6 @@ static void __init parse_lsm_order(const char *order, const char *origin)
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (lsm->order == LSM_ORDER_MUTABLE &&
- (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
strcmp(lsm->name, name) == 0) {
append_ordered_lsm(lsm, origin);
found = true;
@@ -163,8 +162,7 @@ static void __init prepare_lsm_order(void)
/* Add any missing LSMs, in link order. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if (lsm->order == LSM_ORDER_MUTABLE &&
- (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+ if (lsm->order == LSM_ORDER_MUTABLE)
append_ordered_lsm(lsm, "link-time");
}
@@ -222,18 +220,6 @@ static void __init ordered_lsm_init(void)
maybe_initialize_lsm(*lsm);
}
-static void __init major_lsm_init(void)
-{
- struct lsm_info *lsm;
-
- for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
- continue;
-
- maybe_initialize_lsm(lsm);
- }
-}
-
/**
* security_init - initializes the security framework
*
@@ -253,8 +239,6 @@ int __init security_init(void)
GFP_KERNEL);
/* Process "security=", if given. */
- if (!chosen_major_lsm)
- chosen_major_lsm = CONFIG_DEFAULT_SECURITY;
if (chosen_major_lsm) {
struct lsm_info *lsm;
@@ -275,11 +259,6 @@ int __init security_init(void)
prepare_lsm_order();
ordered_lsm_init();
- /*
- * Load all the remaining security modules.
- */
- major_lsm_init();
-
kfree(ordered_lsms);
return 0;
}
--
2.17.1
In order to both support old "security=" Legacy Major LSM selection, and
handling real exclusivity, this creates LSM_FLAG_EXCLUSIVE and updates
the selection logic to handle them.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 1 +
security/apparmor/lsm.c | 2 +-
security/security.c | 12 ++++++++++++
security/selinux/hooks.c | 2 +-
security/smack/smack_lsm.c | 2 +-
security/tomoyo/tomoyo.c | 2 +-
6 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 8e843eaacffb..7d9c94d31279 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2040,6 +2040,7 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
#define LSM_FLAG_LEGACY_MAJOR (1 << 0)
+#define LSM_FLAG_EXCLUSIVE (2 << 0)
enum lsm_order {
LSM_ORDER_FIRST = -1, /* This is only for capabilities. */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 5399c2f03536..d68bc931d388 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1601,7 +1601,7 @@ static int __init apparmor_init(void)
}
DEFINE_LSM(apparmor)
- .flags = LSM_FLAG_LEGACY_MAJOR,
+ .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.enabled = &apparmor_enabled,
.init = apparmor_init,
END_LSM;
diff --git a/security/security.c b/security/security.c
index a40e938db1b0..f076fdc6b451 100644
--- a/security/security.c
+++ b/security/security.c
@@ -49,6 +49,7 @@ static __initconst const char * const builtin_lsm_order = CONFIG_LSM_ORDER;
/* Ordered list of LSMs to initialize. */
static __initdata struct lsm_info **ordered_lsms;
+static __initdata struct lsm_info *exclusive;
static bool debug __initdata;
#define init_debug(...) \
@@ -181,6 +182,12 @@ static bool __init lsm_allowed(struct lsm_info *lsm)
if (lsm->enabled && !*lsm->enabled)
return false;
+ /* Not allowed if another exclusive LSM already initialized. */
+ if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) {
+ init_debug("exclusive disabled: %s\n", lsm->name);
+ return false;
+ }
+
return true;
}
@@ -196,6 +203,11 @@ static void __init maybe_initialize_lsm(struct lsm_info *lsm)
if (enabled) {
int ret;
+ if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
+ exclusive = lsm;
+ init_debug("exclusive: %s\n", lsm->name);
+ }
+
init_debug("initializing %s\n", lsm->name);
ret = lsm->init();
WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 409a9252aeb6..5461d54fcd99 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7193,7 +7193,7 @@ void selinux_complete_init(void)
/* SELinux requires early initialization in order to label
all processes and objects when they are created. */
DEFINE_LSM(selinux)
- .flags = LSM_FLAG_LEGACY_MAJOR,
+ .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.enabled = &selinux_enabled,
.init = selinux_init,
END_LSM;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e79fad43a8e3..e46c1ea8cf84 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4880,6 +4880,6 @@ static __init int smack_init(void)
* all processes and objects when they are created.
*/
DEFINE_LSM(smack)
- .flags = LSM_FLAG_LEGACY_MAJOR,
+ .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.init = smack_init,
END_LSM;
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 39bb994ebe09..cc39eb8df61a 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -549,6 +549,6 @@ static int __init tomoyo_init(void)
}
DEFINE_LSM(tomoyo)
- .flags = LSM_FLAG_LEGACY_MAJOR,
+ .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.init = tomoyo_init,
END_LSM;
--
2.17.1
This constructs a list of ordered LSMs to initialize, using a hard-coded
list of only "integrity": minor LSMs continue to have direct hook calls,
and major LSMs continue to initialize separately.
Signed-off-by: Kees Cook <[email protected]>
---
security/security.c | 59 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 52 insertions(+), 7 deletions(-)
diff --git a/security/security.c b/security/security.c
index 25a019cc4a2b..2541a512a0f7 100644
--- a/security/security.c
+++ b/security/security.c
@@ -34,6 +34,9 @@
#define MAX_LSM_EVM_XATTR 2
+/* How many LSMs were built into the kernel? */
+#define LSM_COUNT (__end_lsm_info - __start_lsm_info)
+
struct security_hook_heads security_hook_heads __lsm_ro_after_init;
static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
@@ -41,6 +44,9 @@ char *lsm_names;
/* Boot-time LSM user choice */
static __initdata const char *chosen_major_lsm;
+/* Ordered list of LSMs to initialize. */
+static __initdata struct lsm_info **ordered_lsms;
+
static bool debug __initdata;
#define init_debug(...) \
do { \
@@ -74,6 +80,45 @@ static void __init set_enabled(struct lsm_info *lsm, bool enabled)
}
}
+/* Is an LSM already listed in the ordered LSMs list? */
+static bool __init exists_ordered_lsm(struct lsm_info *lsm)
+{
+ struct lsm_info **check;
+
+ for (check = ordered_lsms; *check; check++)
+ if (*check == lsm)
+ return true;
+
+ return false;
+}
+
+/* Append an LSM to the list of ordered LSMs to initialize. */
+static int last_lsm __initdata;
+static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
+{
+ /* Ignore duplicate selections. */
+ if (exists_ordered_lsm(lsm))
+ return;
+
+ if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from))
+ return;
+
+ ordered_lsms[last_lsm++] = lsm;
+ init_debug("%s ordering: %s (%sabled)\n", from, lsm->name,
+ (!lsm->enabled || *lsm->enabled) ? "en" : "dis");
+}
+
+/* Populate ordered LSMs list from hard-coded list of LSMs. */
+static void __init prepare_lsm_order(void)
+{
+ struct lsm_info *lsm;
+
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if (strcmp(lsm->name, "integrity") == 0)
+ append_ordered_lsm(lsm, "builtin");
+ }
+}
+
/* Is an LSM allowed to be enabled? */
static bool __init lsm_allowed(struct lsm_info *lsm)
{
@@ -104,14 +149,10 @@ static void __init maybe_initialize_lsm(struct lsm_info *lsm)
static void __init ordered_lsm_init(void)
{
- struct lsm_info *lsm;
-
- for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
- continue;
+ struct lsm_info **lsm;
- maybe_initialize_lsm(lsm);
- }
+ for (lsm = ordered_lsms; *lsm; lsm++)
+ maybe_initialize_lsm(*lsm);
}
static void __init major_lsm_init(void)
@@ -141,6 +182,8 @@ int __init security_init(void)
for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
i++)
INIT_HLIST_HEAD(&list[i]);
+ ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
+ GFP_KERNEL);
/* Process "security=", if given. */
if (!chosen_major_lsm)
@@ -169,6 +212,7 @@ int __init security_init(void)
loadpin_add_hooks();
/* Load LSMs in specified order. */
+ prepare_lsm_order();
ordered_lsm_init();
/*
@@ -176,6 +220,7 @@ int __init security_init(void)
*/
major_lsm_init();
+ kfree(ordered_lsms);
return 0;
}
--
2.17.1
In preparation for distinguishing the "capability" LSM from other LSMs,
it must be ordered first. This introduces LSM_ORDER_MUTABLE for the
general LSMs, LSM_ORDER_FIRST for capabilities, and LSM_ORDER_LAST for
anything that must run last (e.g. Landlock may use this in the future).
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 7 +++++++
security/security.c | 22 ++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index d75a42eb3ddd..bf29851baf47 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2041,8 +2041,15 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count,
#define LSM_FLAG_LEGACY_MAJOR (1 << 0)
+enum lsm_order {
+ LSM_ORDER_FIRST = -1, /* This is only for capabilities. */
+ LSM_ORDER_MUTABLE = 0,
+ LSM_ORDER_LAST,
+};
+
struct lsm_info {
const char *name; /* Populated automatically. */
+ enum lsm_order order; /* Optional: default is LSM_ORDER_MUTABLE */
unsigned long flags; /* Optional: flags describing LSM */
int *enabled; /* Optional: NULL means enabled. */
int (*init)(void);
diff --git a/security/security.c b/security/security.c
index 3fba28de789b..d649e7dea4c4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -62,6 +62,10 @@ static int lsm_enabled_true __initdata = 1;
static int lsm_enabled_false __initdata = 0;
static void __init set_enabled(struct lsm_info *lsm, bool enabled)
{
+ /* First LSM cannot have enablement changed. */
+ if (lsm->order == LSM_ORDER_FIRST)
+ return;
+
if (!lsm->enabled) {
/*
* If the LSM hasn't configured an enable flag, we
@@ -124,7 +128,8 @@ static void __init parse_lsm_order(const char *order, const char *origin)
bool found = false;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
+ if (lsm->order == LSM_ORDER_MUTABLE &&
+ (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
strcmp(lsm->name, name) == 0) {
append_ordered_lsm(lsm, origin);
found = true;
@@ -142,6 +147,12 @@ static void __init prepare_lsm_order(void)
{
struct lsm_info *lsm;
+ /* LSM_ORDER_FIRST is always first. */
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if (lsm->order == LSM_ORDER_FIRST)
+ append_ordered_lsm(lsm, "first");
+ }
+
/* Parse order from commandline, if present. */
if (chosen_lsm_order)
parse_lsm_order(chosen_lsm_order, "cmdline");
@@ -151,9 +162,16 @@ static void __init prepare_lsm_order(void)
/* Add any missing LSMs, in link order. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
- if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+ if (lsm->order == LSM_ORDER_MUTABLE &&
+ (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
append_ordered_lsm(lsm, "link-time");
}
+
+ /* LSM_ORDER_LAST is always last. */
+ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+ if (lsm->order == LSM_ORDER_LAST)
+ append_ordered_lsm(lsm, "last");
+ }
}
/* Is an LSM allowed to be enabled? */
--
2.17.1
This converts LoadPin from being a direct "minor" LSM into an ordered LSM.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 5 -----
security/Kconfig | 2 +-
security/loadpin/loadpin.c | 10 ++++++++--
security/security.c | 1 -
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index ec1c0a97dfe3..7a38ffdd690f 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2097,10 +2097,5 @@ extern void __init yama_add_hooks(void);
#else
static inline void __init yama_add_hooks(void) { }
#endif
-#ifdef CONFIG_SECURITY_LOADPIN
-void __init loadpin_add_hooks(void);
-#else
-static inline void loadpin_add_hooks(void) { };
-#endif
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/Kconfig b/security/Kconfig
index de8202886c1d..f2003bd03ef6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -278,7 +278,7 @@ config DEFAULT_SECURITY
config LSM_ORDER
string "Default initialization order of builtin LSMs"
- default "integrity"
+ default "loadpin,integrity"
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list will be link-order initialized
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 0716af28808a..e638fba7363d 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -184,12 +184,18 @@ static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
};
-void __init loadpin_add_hooks(void)
+static int __init loadpin_init(void)
{
- pr_info("ready to pin (currently %sabled)", enabled ? "en" : "dis");
+ pr_info("ready to pin\n");
security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
+ return 0;
}
+DEFINE_LSM(loadpin)
+ .enabled = &enabled,
+ .init = loadpin_init,
+END_LSM;
+
/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
module_param(enabled, int, 0);
MODULE_PARM_DESC(enabled, "Pin module/firmware loading (default: true)");
diff --git a/security/security.c b/security/security.c
index 4db194f81419..9ffb76b7655b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -246,7 +246,6 @@ int __init security_init(void)
*/
capability_add_hooks();
yama_add_hooks();
- loadpin_add_hooks();
/* Load LSMs in specified order. */
prepare_lsm_order();
--
2.17.1
This converts Yama from being a direct "minor" LSM into an ordered LSM.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 5 -----
security/Kconfig | 2 +-
security/security.c | 1 -
security/yama/yama_lsm.c | 7 ++++++-
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7a38ffdd690f..d75a42eb3ddd 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2092,10 +2092,5 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
extern void __init capability_add_hooks(void);
-#ifdef CONFIG_SECURITY_YAMA
-extern void __init yama_add_hooks(void);
-#else
-static inline void __init yama_add_hooks(void) { }
-#endif
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/Kconfig b/security/Kconfig
index f2003bd03ef6..33c9ac3cb759 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -278,7 +278,7 @@ config DEFAULT_SECURITY
config LSM_ORDER
string "Default initialization order of builtin LSMs"
- default "loadpin,integrity"
+ default "yama,loadpin,integrity"
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list will be link-order initialized
diff --git a/security/security.c b/security/security.c
index 9ffb76b7655b..3fba28de789b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -245,7 +245,6 @@ int __init security_init(void)
* Load minor LSMs, with the capability module always first.
*/
capability_add_hooks();
- yama_add_hooks();
/* Load LSMs in specified order. */
prepare_lsm_order();
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index ffda91a4a1aa..f2b1f47f98e8 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -477,9 +477,14 @@ static void __init yama_init_sysctl(void)
static inline void yama_init_sysctl(void) { }
#endif /* CONFIG_SYSCTL */
-void __init yama_add_hooks(void)
+static int __init yama_init(void)
{
pr_info("Yama: becoming mindful.\n");
security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
yama_init_sysctl();
+ return 0;
}
+
+DEFINE_LSM(yama)
+ .init = yama_init,
+END_LSM;
--
2.17.1
This converts capabilities to use the new LSM_ORDER_FIRST position.
Signed-off-by: Kees Cook <[email protected]>
---
include/linux/lsm_hooks.h | 2 --
security/commoncap.c | 8 +++++++-
security/security.c | 5 -----
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index bf29851baf47..8e843eaacffb 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2098,6 +2098,4 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
#define __lsm_ro_after_init __ro_after_init
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
-extern void __init capability_add_hooks(void);
-
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/commoncap.c b/security/commoncap.c
index 2e489d6a3ac8..7a6abaec65de 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1366,10 +1366,16 @@ struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
};
-void __init capability_add_hooks(void)
+static int __init capability_init(void)
{
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
"capability");
+ return 0;
}
+DEFINE_LSM(capability)
+ .order = LSM_ORDER_FIRST,
+ .init = capability_init,
+END_LSM;
+
#endif /* CONFIG_SECURITY */
diff --git a/security/security.c b/security/security.c
index d649e7dea4c4..a40e938db1b0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -259,11 +259,6 @@ int __init security_init(void)
}
}
- /*
- * Load minor LSMs, with the capability module always first.
- */
- capability_add_hooks();
-
/* Load LSMs in specified order. */
prepare_lsm_order();
ordered_lsm_init();
--
2.17.1
Kees Cook - 20.09.18, 18:23:
> v2:
> - add "lsm.order=" and CONFIG_LSM_ORDER instead of overloading
> "security=" - reorganize introduction of ordering logic code
>
> Updated cover letter:
>
> This refactors the LSM registration and initialization infrastructure
> to more centrally support different LSM types. What was considered a
> "major" LSM is kept for legacy use of the "security=" boot parameter,
> and now overlaps with the new class of "exclusive" LSMs for the future
> blob sharing (to be added later). The "minor" LSMs become more well
> defined as a result of the refactoring.
>
> Instead of continuing to (somewhat improperly) overload the kernel's
> initcall system, this changes the LSM infrastructure to store a
> registration structure (struct lsm_info) table instead, where metadata
> about each LSM can be recorded (name, flags, order, enable flag, init
> function). This can be extended in the future to include things like
> required blob size for the coming "blob sharing" LSMs.
I read the cover letter and still don?t know what this is about. Now I
am certainly not engaged deeply with LSM. I bet my main missing piece
is: What is a "blob sharing" LSM.
I think it would improve the cover letter greatly if it explains briefly
what is a major LSM, what is a minor LSM and what is a "blob sharing"
LSM.
Why those are all needed? What is the actual security or end user
benefit of this work? The questions are not to question your work. I bet
it makes all perfect sense. I just did not understand its sense from
reading the cover letter.
> The "major" LSMs had to individually negotiate which of them should be
> enabled. This didn't provide a way to negotiate combinations of other
> LSMs (as will be needed for "blob sharing" LSMs). This is solved by
> providing the LSM infrastructure with all the details needed to make
> the choice (exposing the per-LSM "enabled" flag, if used, the LSM
> characteristics, and ordering expectations).
>
> As a result of the refactoring, the "minor" LSMs are able to remove
> the open-coded security_add_hooks() calls for "capability", "yama",
> and "loadpin", and to redefine "integrity" properly as a general LSM.
> (Note that "integrity" actually defined _no_ hooks, but needs the
> early initialization).
>
> With all LSMs being proessed centrally, it was possible to implement
> a new boot parameter "lsm.order=" to provide explicit ordering, which
> is helpful for the future "blob sharing" LSMs. Matching this is the
> new CONFIG_LSM_ORDER, which replaces CONFIG_DEFAULT_SECURITY, as it
> provides a higher granularity of control.
>
> To better show LSMs activation some debug reporting was added (enabled
> with the "lsm.debug" boot commandline option).
>
> Finally, I added a WARN() around LSM initialization failures, which
> appear to have always been silently ignored. (Realistically any LSM
> init failures would have only been due to catastrophic kernel issues
> that would render a system unworkable anyway, but it'd be better to
> expose the problem as early as possible.)
>
> -Kees
>
> Kees Cook (26):
> LSM: Correctly announce start of LSM initialization
> vmlinux.lds.h: Avoid copy/paste of security_init section
> LSM: Rename .security_initcall section to .lsm_info
> LSM: Remove initcall tracing
> LSM: Convert from initcall to struct lsm_info
> vmlinux.lds.h: Move LSM_TABLE into INIT_DATA
> LSM: Convert security_initcall() into DEFINE_LSM()
> LSM: Record LSM name in struct lsm_info
> LSM: Provide init debugging infrastructure
> LSM: Don't ignore initialization failures
> LSM: Introduce LSM_FLAG_LEGACY_MAJOR
> LSM: Provide separate ordered initialization
> LSM: Plumb visibility into optional "enabled" state
> LSM: Lift LSM selection out of individual LSMs
> LSM: Introduce lsm.enable= and lsm.disable=
> LSM: Prepare for reorganizing "security=" logic
> LSM: Refactor "security=" in terms of enable/disable
> LSM: Build ordered list of ordered LSMs for init
> LSM: Introduce CONFIG_LSM_ORDER
> LSM: Introduce "lsm.order=" for boottime ordering
> LoadPin: Initialize as ordered LSM
> Yama: Initialize as ordered LSM
> LSM: Introduce enum lsm_order
> capability: Mark as LSM_ORDER_FIRST
> LSM: Separate idea of "major" LSM from "exclusive" LSM
> LSM: Add all exclusive LSMs to ordered initialization
>
> .../admin-guide/kernel-parameters.txt | 7 +
> arch/arc/kernel/vmlinux.lds.S | 1 -
> arch/arm/kernel/vmlinux-xip.lds.S | 1 -
> arch/arm64/kernel/vmlinux.lds.S | 1 -
> arch/h8300/kernel/vmlinux.lds.S | 1 -
> arch/microblaze/kernel/vmlinux.lds.S | 2 -
> arch/powerpc/kernel/vmlinux.lds.S | 2 -
> arch/um/include/asm/common.lds.S | 2 -
> arch/xtensa/kernel/vmlinux.lds.S | 1 -
> include/asm-generic/vmlinux.lds.h | 25 +-
> include/linux/init.h | 2 -
> include/linux/lsm_hooks.h | 43 ++-
> include/linux/module.h | 1 -
> security/Kconfig | 42 +--
> security/apparmor/lsm.c | 16 +-
> security/commoncap.c | 8 +-
> security/integrity/iint.c | 5 +-
> security/loadpin/loadpin.c | 10 +-
> security/security.c | 304
> ++++++++++++++---- security/selinux/hooks.c |
> 16 +-
> security/smack/smack_lsm.c | 8 +-
> security/tomoyo/tomoyo.c | 7 +-
> security/yama/yama_lsm.c | 7 +-
> 23 files changed, 348 insertions(+), 164 deletions(-)
--
Martin
On Thu, Sep 20, 2018 at 1:14 PM, Martin Steigerwald <[email protected]> wrote:
> Kees Cook - 20.09.18, 18:23:
>> v2:
>> - add "lsm.order=" and CONFIG_LSM_ORDER instead of overloading
>> "security=" - reorganize introduction of ordering logic code
>>
>> Updated cover letter:
>>
>> This refactors the LSM registration and initialization infrastructure
>> to more centrally support different LSM types. What was considered a
>> "major" LSM is kept for legacy use of the "security=" boot parameter,
>> and now overlaps with the new class of "exclusive" LSMs for the future
>> blob sharing (to be added later). The "minor" LSMs become more well
>> defined as a result of the refactoring.
>>
>> Instead of continuing to (somewhat improperly) overload the kernel's
>> initcall system, this changes the LSM infrastructure to store a
>> registration structure (struct lsm_info) table instead, where metadata
>> about each LSM can be recorded (name, flags, order, enable flag, init
>> function). This can be extended in the future to include things like
>> required blob size for the coming "blob sharing" LSMs.
>
> I read the cover letter and still don´t know what this is about. Now I
> am certainly not engaged deeply with LSM. I bet my main missing piece
> is: What is a "blob sharing" LSM.
>
> I think it would improve the cover letter greatly if it explains briefly
> what is a major LSM, what is a minor LSM and what is a "blob sharing"
> LSM.
>
> Why those are all needed? What is the actual security or end user
> benefit of this work? The questions are not to question your work. I bet
> it makes all perfect sense. I just did not understand its sense from
> reading the cover letter.
Sure, thanks! I'll include more details for any later versions. This
is mainly related to some internal refactoring the LSM is doing to
support additional LSM that need more extensive "stacking" of the
kernel internals. I aimed this at linux-doc@ and linux-arch@ to get
feedback on the Documentation/ and linker script changes,
respectively. In theory, users don't need to know anything about
minor/major nor blob-sharing, as that should normally be all an
internal issue.
Thanks!
-Kees
--
Kees Cook
Pixel Security
On 9/20/2018 9:23 AM, Kees Cook wrote:
> For a while now, the LSM core has said it was "initializED", rather than
> "initializING". This adjust the report to be more accurate (i.e. before
> this was reported before any LSMs had been initialized.)
>
> Signed-off-by: Kees Cook <[email protected]>
Reviewed-by: Casey Schaufler <[email protected]>
> ---
> security/security.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/security/security.c b/security/security.c
> index 736e78da1ab9..4cbcf244a965 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -72,10 +72,11 @@ int __init security_init(void)
> int i;
> struct hlist_head *list = (struct hlist_head *) &security_hook_heads;
>
> + pr_info("Security Framework initializing\n");
> +
> for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
> i++)
> INIT_HLIST_HEAD(&list[i]);
> - pr_info("Security Framework initialized\n");
>
> /*
> * Load minor LSMs, with the capability module always first.
On 9/20/2018 9:23 AM, Kees Cook wrote:
> This constructs a list of ordered LSMs to initialize, using a hard-coded
> list of only "integrity": minor LSMs continue to have direct hook calls,
> and major LSMs continue to initialize separately.
>
> Signed-off-by: Kees Cook <[email protected]>
Do you think that this mechanism will be sufficiently
flexible to accommodate dynamically loaded security modules
in the future? While I am not personally an advocate of
dynamically loaded security modules I have been working to
ensure that I haven't done anything that would actively
interfere with someone who did.
> ---
> security/security.c | 59 +++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 52 insertions(+), 7 deletions(-)
>
> diff --git a/security/security.c b/security/security.c
> index 25a019cc4a2b..2541a512a0f7 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -34,6 +34,9 @@
>
> #define MAX_LSM_EVM_XATTR 2
>
> +/* How many LSMs were built into the kernel? */
> +#define LSM_COUNT (__end_lsm_info - __start_lsm_info)
> +
> struct security_hook_heads security_hook_heads __lsm_ro_after_init;
> static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
>
> @@ -41,6 +44,9 @@ char *lsm_names;
> /* Boot-time LSM user choice */
> static __initdata const char *chosen_major_lsm;
>
> +/* Ordered list of LSMs to initialize. */
> +static __initdata struct lsm_info **ordered_lsms;
> +
> static bool debug __initdata;
> #define init_debug(...) \
> do { \
> @@ -74,6 +80,45 @@ static void __init set_enabled(struct lsm_info *lsm, bool enabled)
> }
> }
>
> +/* Is an LSM already listed in the ordered LSMs list? */
> +static bool __init exists_ordered_lsm(struct lsm_info *lsm)
> +{
> + struct lsm_info **check;
> +
> + for (check = ordered_lsms; *check; check++)
> + if (*check == lsm)
> + return true;
> +
> + return false;
> +}
> +
> +/* Append an LSM to the list of ordered LSMs to initialize. */
> +static int last_lsm __initdata;
> +static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
> +{
> + /* Ignore duplicate selections. */
> + if (exists_ordered_lsm(lsm))
> + return;
> +
> + if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from))
> + return;
> +
> + ordered_lsms[last_lsm++] = lsm;
> + init_debug("%s ordering: %s (%sabled)\n", from, lsm->name,
> + (!lsm->enabled || *lsm->enabled) ? "en" : "dis");
> +}
> +
> +/* Populate ordered LSMs list from hard-coded list of LSMs. */
> +static void __init prepare_lsm_order(void)
> +{
> + struct lsm_info *lsm;
> +
> + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> + if (strcmp(lsm->name, "integrity") == 0)
> + append_ordered_lsm(lsm, "builtin");
> + }
> +}
> +
> /* Is an LSM allowed to be enabled? */
> static bool __init lsm_allowed(struct lsm_info *lsm)
> {
> @@ -104,14 +149,10 @@ static void __init maybe_initialize_lsm(struct lsm_info *lsm)
>
> static void __init ordered_lsm_init(void)
> {
> - struct lsm_info *lsm;
> -
> - for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> - if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
> - continue;
> + struct lsm_info **lsm;
>
> - maybe_initialize_lsm(lsm);
> - }
> + for (lsm = ordered_lsms; *lsm; lsm++)
> + maybe_initialize_lsm(*lsm);
> }
>
> static void __init major_lsm_init(void)
> @@ -141,6 +182,8 @@ int __init security_init(void)
> for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
> i++)
> INIT_HLIST_HEAD(&list[i]);
> + ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
> + GFP_KERNEL);
>
> /* Process "security=", if given. */
> if (!chosen_major_lsm)
> @@ -169,6 +212,7 @@ int __init security_init(void)
> loadpin_add_hooks();
>
> /* Load LSMs in specified order. */
> + prepare_lsm_order();
> ordered_lsm_init();
>
> /*
> @@ -176,6 +220,7 @@ int __init security_init(void)
> */
> major_lsm_init();
>
> + kfree(ordered_lsms);
> return 0;
> }
>
On 9/20/2018 9:23 AM, Kees Cook wrote:
> This provides a way to declare LSM initialization order via Kconfig.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> security/Kconfig | 11 +++++++++++
> security/security.c | 38 +++++++++++++++++++++++++++++++++++---
> 2 files changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/security/Kconfig b/security/Kconfig
> index 27d8b2688f75..de8202886c1d 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -276,5 +276,16 @@ config DEFAULT_SECURITY
> default "apparmor" if DEFAULT_SECURITY_APPARMOR
> default "" if DEFAULT_SECURITY_DAC
>
> +config LSM_ORDER
> + string "Default initialization order of builtin LSMs"
> + default "integrity"
I would like to see the default spelled out rather than
provided implicitly.
+ default "integrity,yama,loadpin,selinux,smack,apparmor,tomoyo"
> + help
> + A comma-separated list of LSMs, in initialization order.
> + Any LSMs left off this list will be link-order initialized
> + after any listed LSMs. Any LSMs listed here but not built in
> + the kernel will be ignored.
This should also describe what will happen if you include multiple
major modules in the list.
> +
> + If unsure, leave this as the default.
> +
> endmenu
>
> diff --git a/security/security.c b/security/security.c
> index 2541a512a0f7..063ee2466e58 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -44,6 +44,8 @@ char *lsm_names;
> /* Boot-time LSM user choice */
> static __initdata const char *chosen_major_lsm;
>
> +static __initconst const char * const builtin_lsm_order = CONFIG_LSM_ORDER;
> +
> /* Ordered list of LSMs to initialize. */
> static __initdata struct lsm_info **ordered_lsms;
>
> @@ -108,14 +110,44 @@ static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
> (!lsm->enabled || *lsm->enabled) ? "en" : "dis");
> }
>
> -/* Populate ordered LSMs list from hard-coded list of LSMs. */
> +/* Populate ordered LSMs list from given string. */
> +static void __init parse_lsm_order(const char *order, const char *origin)
> +{
> + struct lsm_info *lsm;
> + char *sep, *name, *next;
> +
> + sep = kstrdup(order, GFP_KERNEL);
> + next = sep;
> + /* Walk the list, looking for matching LSMs. */
> + while ((name = strsep(&next, ",")) != NULL) {
> + bool found = false;
> +
> + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> + if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
> + strcmp(lsm->name, name) == 0) {
> + append_ordered_lsm(lsm, origin);
> + found = true;
> + }
> + }
> +
> + if (!found)
> + init_debug("%s ignored: %s\n", origin, name);
> + }
> + kfree(sep);
> +}
> +
> +/* Populate ordered LSMs list from builtin list of LSMs. */
> static void __init prepare_lsm_order(void)
> {
> struct lsm_info *lsm;
>
> + /* Parse order from builtin list. */
> + parse_lsm_order(builtin_lsm_order, "builtin");
> +
> + /* Add any missing LSMs, in link order. */
> for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> - if (strcmp(lsm->name, "integrity") == 0)
> - append_ordered_lsm(lsm, "builtin");
> + if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
> + append_ordered_lsm(lsm, "link-time");
> }
> }
>
On 9/20/2018 9:23 AM, Kees Cook wrote:
> Provide a way to reorder LSM initialization using the new "lsm.order="
> comma-separated list of LSMs. Any LSMs not listed will be added in builtin
> order.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> Documentation/admin-guide/kernel-parameters.txt | 5 +++++
> security/security.c | 15 ++++++++++++++-
> 2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 32d323ee9218..5ac4c1056ffa 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -2276,6 +2276,11 @@
>
> lsm.debug [SECURITY] Enable LSM initialization debugging output.
>
> + lsm.order=lsm1,...,lsmN
> + [SECURITY] Choose order of LSM initialization. Any
> + builtin LSMs not listed here will be implicitly
> + added to the list in builtin order.
Added at the end of the list, or beginning of the list?
> +
> machvec= [IA-64] Force the use of a particular machine-vector
> (machvec) in a generic kernel.
> Example: machvec=hpzx1_swiotlb
> diff --git a/security/security.c b/security/security.c
> index 063ee2466e58..4db194f81419 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -43,6 +43,7 @@ static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
> char *lsm_names;
> /* Boot-time LSM user choice */
> static __initdata const char *chosen_major_lsm;
> +static __initdata const char *chosen_lsm_order;
>
> static __initconst const char * const builtin_lsm_order = CONFIG_LSM_ORDER;
>
> @@ -136,11 +137,15 @@ static void __init parse_lsm_order(const char *order, const char *origin)
> kfree(sep);
> }
>
> -/* Populate ordered LSMs list from builtin list of LSMs. */
> +/* Populate ordered LSMs list from commandline and builtin list of LSMs. */
> static void __init prepare_lsm_order(void)
> {
> struct lsm_info *lsm;
>
> + /* Parse order from commandline, if present. */
> + if (chosen_lsm_order)
> + parse_lsm_order(chosen_lsm_order, "cmdline");
> +
> /* Parse order from builtin list. */
> parse_lsm_order(builtin_lsm_order, "builtin");
>
> @@ -264,6 +269,14 @@ static int __init choose_major_lsm(char *str)
> }
> __setup("security=", choose_major_lsm);
>
> +/* Explicitly choose LSM initialization order. */
> +static int __init choose_lsm_order(char *str)
> +{
> + chosen_lsm_order = str;
> + return 1;
> +}
> +__setup("lsm.order=", choose_lsm_order);
> +
> /* Enable LSM order debugging. */
> static int __init enable_debug(char *str)
> {
On 9/20/2018 5:10 PM, Casey Schaufler wrote:
> On 9/20/2018 9:23 AM, Kees Cook wrote:
>> This provides a way to declare LSM initialization order via Kconfig.
>>
>> Signed-off-by: Kees Cook <[email protected]>
>> ---
>> security/Kconfig | 11 +++++++++++
>> security/security.c | 38 +++++++++++++++++++++++++++++++++++---
>> 2 files changed, 46 insertions(+), 3 deletions(-)
>>
>> diff --git a/security/Kconfig b/security/Kconfig
>> index 27d8b2688f75..de8202886c1d 100644
>> --- a/security/Kconfig
>> +++ b/security/Kconfig
>> @@ -276,5 +276,16 @@ config DEFAULT_SECURITY
>> default "apparmor" if DEFAULT_SECURITY_APPARMOR
>> default "" if DEFAULT_SECURITY_DAC
>>
>> +config LSM_ORDER
>> + string "Default initialization order of builtin LSMs"
>> + default "integrity"
> I would like to see the default spelled out rather than
> provided implicitly.
>
> + default "integrity,yama,loadpin,selinux,smack,apparmor,tomoyo"
I see now that comes later in the patch set. Never mind.
On 9/20/2018 9:23 AM, Kees Cook wrote:
> This removes CONFIG_DEFAULT_SECURITY in favor of the explicit build-time
> ordering offered by CONFIG_LSM_ORDER, and adds all the exclusive LSMs
> to the ordered LSM initialization.
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> security/Kconfig | 39 +--------------------------------------
> security/security.c | 23 +----------------------
> 2 files changed, 2 insertions(+), 60 deletions(-)
>
> diff --git a/security/Kconfig b/security/Kconfig
> index 33c9ac3cb759..a2e365420919 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -239,46 +239,9 @@ source security/yama/Kconfig
>
> source security/integrity/Kconfig
>
> -choice
> - prompt "Default security module"
> - default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
> - default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
> - default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
> - default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
> - default DEFAULT_SECURITY_DAC
> -
> - help
> - Select the security module that will be used by default if the
> - kernel parameter security= is not specified.
> -
> - config DEFAULT_SECURITY_SELINUX
> - bool "SELinux" if SECURITY_SELINUX=y
> -
> - config DEFAULT_SECURITY_SMACK
> - bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y
> -
> - config DEFAULT_SECURITY_TOMOYO
> - bool "TOMOYO" if SECURITY_TOMOYO=y
> -
> - config DEFAULT_SECURITY_APPARMOR
> - bool "AppArmor" if SECURITY_APPARMOR=y
> -
> - config DEFAULT_SECURITY_DAC
> - bool "Unix Discretionary Access Controls"
> -
> -endchoice
> -
> -config DEFAULT_SECURITY
> - string
> - default "selinux" if DEFAULT_SECURITY_SELINUX
> - default "smack" if DEFAULT_SECURITY_SMACK
> - default "tomoyo" if DEFAULT_SECURITY_TOMOYO
> - default "apparmor" if DEFAULT_SECURITY_APPARMOR
> - default "" if DEFAULT_SECURITY_DAC
> -
> config LSM_ORDER
> string "Default initialization order of builtin LSMs"
> - default "yama,loadpin,integrity"
> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
If I want to compile all the major modules into my kernel and use
AppArmor by default would I use
default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
or
default "yama,loadpin,integrity,apparmor"
When we have "blob-sharing" how could I compile in tomoyo,
but exclude it without a boot line option?
When we have full stacking, how could I compile in selinux
but exclude it?
> help
> A comma-separated list of LSMs, in initialization order.
> Any LSMs left off this list will be link-order initialized
> diff --git a/security/security.c b/security/security.c
> index f076fdc6b451..628e62fda5fe 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -130,7 +130,6 @@ static void __init parse_lsm_order(const char *order, const char *origin)
>
> for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> if (lsm->order == LSM_ORDER_MUTABLE &&
> - (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0 &&
> strcmp(lsm->name, name) == 0) {
> append_ordered_lsm(lsm, origin);
> found = true;
> @@ -163,8 +162,7 @@ static void __init prepare_lsm_order(void)
>
> /* Add any missing LSMs, in link order. */
> for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> - if (lsm->order == LSM_ORDER_MUTABLE &&
> - (lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
> + if (lsm->order == LSM_ORDER_MUTABLE)
> append_ordered_lsm(lsm, "link-time");
> }
>
> @@ -222,18 +220,6 @@ static void __init ordered_lsm_init(void)
> maybe_initialize_lsm(*lsm);
> }
>
> -static void __init major_lsm_init(void)
> -{
> - struct lsm_info *lsm;
> -
> - for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
> - if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
> - continue;
> -
> - maybe_initialize_lsm(lsm);
> - }
> -}
> -
> /**
> * security_init - initializes the security framework
> *
> @@ -253,8 +239,6 @@ int __init security_init(void)
> GFP_KERNEL);
>
> /* Process "security=", if given. */
> - if (!chosen_major_lsm)
> - chosen_major_lsm = CONFIG_DEFAULT_SECURITY;
> if (chosen_major_lsm) {
> struct lsm_info *lsm;
>
> @@ -275,11 +259,6 @@ int __init security_init(void)
> prepare_lsm_order();
> ordered_lsm_init();
>
> - /*
> - * Load all the remaining security modules.
> - */
> - major_lsm_init();
> -
> kfree(ordered_lsms);
> return 0;
> }
On Thu, Sep 20, 2018 at 5:04 PM, Casey Schaufler <[email protected]> wrote:
> On 9/20/2018 9:23 AM, Kees Cook wrote:
>> This constructs a list of ordered LSMs to initialize, using a hard-coded
>> list of only "integrity": minor LSMs continue to have direct hook calls,
>> and major LSMs continue to initialize separately.
>>
>> Signed-off-by: Kees Cook <[email protected]>
>
> Do you think that this mechanism will be sufficiently
> flexible to accommodate dynamically loaded security modules
> in the future? While I am not personally an advocate of
> dynamically loaded security modules I have been working to
> ensure that I haven't done anything that would actively
> interfere with someone who did.
I don't think it does, no. This is all just the boot time
initialization order, so a dynamic LSM would be unchanged: it would
initialize at module load time. :)
-Kees
--
Kees Cook
Pixel Security
On Thu, Sep 20, 2018 at 5:12 PM, Casey Schaufler <[email protected]> wrote:
> On 9/20/2018 9:23 AM, Kees Cook wrote:
>> Provide a way to reorder LSM initialization using the new "lsm.order="
>> comma-separated list of LSMs. Any LSMs not listed will be added in builtin
>> order.
>>
>> Signed-off-by: Kees Cook <[email protected]>
>> ---
>> Documentation/admin-guide/kernel-parameters.txt | 5 +++++
>> security/security.c | 15 ++++++++++++++-
>> 2 files changed, 19 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index 32d323ee9218..5ac4c1056ffa 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -2276,6 +2276,11 @@
>>
>> lsm.debug [SECURITY] Enable LSM initialization debugging output.
>>
>> + lsm.order=lsm1,...,lsmN
>> + [SECURITY] Choose order of LSM initialization. Any
>> + builtin LSMs not listed here will be implicitly
>> + added to the list in builtin order.
>
> Added at the end of the list, or beginning of the list?
Whoops, I had an earlier version that was more clear. I meant to say
"appended" instead of "added" here. Fixed for the next version.
-Kees
--
Kees Cook
Pixel Security
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
> On 9/20/2018 9:23 AM, Kees Cook wrote:
>> config LSM_ORDER
>> string "Default initialization order of builtin LSMs"
>> - default "yama,loadpin,integrity"
>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>
> If I want to compile all the major modules into my kernel and use
> AppArmor by default would I use
>
> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>
> or
>
> default "yama,loadpin,integrity,apparmor"
I was expecting the former, but the latter will have the same result.
> When we have "blob-sharing" how could I compile in tomoyo,
> but exclude it without a boot line option?
Ooh, yes, this series has no way to do that. Perhaps
CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
totally remove LoadPin's CONFIG for this in favor it.
> When we have full stacking, how could I compile in selinux
> but exclude it?
Yup, same problem. Same suggested solution?
Should lsm.enable/disable= also become a comma-separated list, or
should I leave it as a multi-instance thing like I have it?
-Kees
--
Kees Cook
Pixel Security
On 9/20/2018 5:45 PM, Kees Cook wrote:
> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>> config LSM_ORDER
>>> string "Default initialization order of builtin LSMs"
>>> - default "yama,loadpin,integrity"
>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>> If I want to compile all the major modules into my kernel and use
>> AppArmor by default would I use
>>
>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>
>> or
>>
>> default "yama,loadpin,integrity,apparmor"
> I was expecting the former, but the latter will have the same result.
>
>> When we have "blob-sharing" how could I compile in tomoyo,
>> but exclude it without a boot line option?
> Ooh, yes, this series has no way to do that. Perhaps
> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
> totally remove LoadPin's CONFIG for this in favor it.
I would generally prefer an optional CONFIG_LSM_ENABLE to
CONFIG_LSM_DISABLE, but I understand the logic behind your
approach. I would be looking for something like
CONFIG LSM_ENABLE
string "Default set of enabled LSMs"
default ""
as opposed to
CONFIG LSM_DISABLE
string "Default set of disabled LSMs"
default ""
where an empty string is interpreted as "use 'em all"
in either case.
>> When we have full stacking, how could I compile in selinux
>> but exclude it?
> Yup, same problem. Same suggested solution?
>
> Should lsm.enable/disable= also become a comma-separated list, or
> should I leave it as a multi-instance thing like I have it?
I prefer the multi-instance
lsm.disable=selinux lsm.disable=yama
to the list
lsm.disable=selinux,yama
but at this point I don't really care all that much.
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
> On 9/20/2018 5:45 PM, Kees Cook wrote:
>> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>>> config LSM_ORDER
>>>> string "Default initialization order of builtin LSMs"
>>>> - default "yama,loadpin,integrity"
>>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>>> If I want to compile all the major modules into my kernel and use
>>> AppArmor by default would I use
>>>
>>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>>
>>> or
>>>
>>> default "yama,loadpin,integrity,apparmor"
>> I was expecting the former, but the latter will have the same result.
t find having the two be equivalent violates expectations. At least
when considering the end goal of full/extreme stacking, its trivially
the same with current major lsms being exclusive
>>
>>> When we have "blob-sharing" how could I compile in tomoyo,
>>> but exclude it without a boot line option?
>> Ooh, yes, this series has no way to do that. Perhaps
>> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
>> totally remove LoadPin's CONFIG for this in favor it.
>
> I would generally prefer an optional CONFIG_LSM_ENABLE to
> CONFIG_LSM_DISABLE, but I understand the logic behind your
> approach. I would be looking for something like
>
+1 on the CONFIG_LSM_ENABLE ove DISABLE
> CONFIG LSM_ENABLE
> string "Default set of enabled LSMs"
> default ""
>
> as opposed to
>
> CONFIG LSM_DISABLE
> string "Default set of disabled LSMs"
> default ""
>
> where an empty string is interpreted as "use 'em all"
> in either case.
>
>>> When we have full stacking, how could I compile in selinux
>>> but exclude it?
>> Yup, same problem. Same suggested solution?
>>
>> Should lsm.enable/disable= also become a comma-separated list, or
>> should I leave it as a multi-instance thing like I have it?
>
> I prefer the multi-instance
> lsm.disable=selinux lsm.disable=yama
> to the list
> lsm.disable=selinux,yama
>
> but at this point I don't really care all that much.
>
the comma separated list however is consistent with what is being
done for default order
On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
<[email protected]> wrote:
> On 09/20/2018 06:10 PM, Casey Schaufler wrote:
>> On 9/20/2018 5:45 PM, Kees Cook wrote:
>>> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>>>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>>>> config LSM_ORDER
>>>>> string "Default initialization order of builtin LSMs"
>>>>> - default "yama,loadpin,integrity"
>>>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>>>> If I want to compile all the major modules into my kernel and use
>>>> AppArmor by default would I use
>>>>
>>>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>>>
>>>> or
>>>>
>>>> default "yama,loadpin,integrity,apparmor"
>>> I was expecting the former, but the latter will have the same result.
>
> t find having the two be equivalent violates expectations. At least
> when considering the end goal of full/extreme stacking, its trivially
> the same with current major lsms being exclusive
This mixes "enablement" with "ordering", though, and I think the past
threads have shown this to be largely problematic.
However, with CONFIG_LSM_ENABLED, we get the effect you're looking for, IIUC.
>>>> When we have "blob-sharing" how could I compile in tomoyo,
>>>> but exclude it without a boot line option?
>>> Ooh, yes, this series has no way to do that. Perhaps
>>> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
>>> totally remove LoadPin's CONFIG for this in favor it.
>>
>> I would generally prefer an optional CONFIG_LSM_ENABLE to
>> CONFIG_LSM_DISABLE, but I understand the logic behind your
>> approach. I would be looking for something like
>>
> +1 on the CONFIG_LSM_ENABLE ove DISABLE
>
>> CONFIG LSM_ENABLE
>> string "Default set of enabled LSMs"
>> default ""
>>
>> as opposed to
>>
>> CONFIG LSM_DISABLE
>> string "Default set of disabled LSMs"
>> default ""
>>
>> where an empty string is interpreted as "use 'em all"
>> in either case.
Yes, I like CONFIG_LSM_ENABLE if "empty" means "enable all". Should
CONFIG_LSM_ENABLE replace all the other CONFIG-based LSM
enabling/disabling?
>>>> When we have full stacking, how could I compile in selinux
>>>> but exclude it?
>>> Yup, same problem. Same suggested solution?
>>>
>>> Should lsm.enable/disable= also become a comma-separated list, or
>>> should I leave it as a multi-instance thing like I have it?
>>
>> I prefer the multi-instance
>> lsm.disable=selinux lsm.disable=yama
>> to the list
>> lsm.disable=selinux,yama
>>
>> but at this point I don't really care all that much.
>
> the comma separated list however is consistent with what is being
> done for default order
Yeah, and it would match the new CONFIG_LSM_ENABLE.
FWIW, it was tedious to type "lsm.enable" and "lsm.disable" over and
over when doing testing, so I almost prefer the comma separated list
at the end of the day. I'll ponder this a bit.
-Kees
--
Kees Cook
Pixel Security
On 09/20/2018 07:05 PM, Kees Cook wrote:
> On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
> <[email protected]> wrote:
>> On 09/20/2018 06:10 PM, Casey Schaufler wrote:
>>> On 9/20/2018 5:45 PM, Kees Cook wrote:
>>>> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>>>>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>>>>> config LSM_ORDER
>>>>>> string "Default initialization order of builtin LSMs"
>>>>>> - default "yama,loadpin,integrity"
>>>>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>>>>> If I want to compile all the major modules into my kernel and use
>>>>> AppArmor by default would I use
>>>>>
>>>>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>>>>
>>>>> or
>>>>>
>>>>> default "yama,loadpin,integrity,apparmor"
>>>> I was expecting the former, but the latter will have the same result.
>>
>> t find having the two be equivalent violates expectations. At least
>> when considering the end goal of full/extreme stacking, its trivially
>> the same with current major lsms being exclusive
>
> This mixes "enablement" with "ordering", though, and I think the past
> threads have shown this to be largely problematic.
>
> However, with CONFIG_LSM_ENABLED, we get the effect you're looking for, IIUC.
no, I was just stating in a world where we have full stacking those two
are not equivalent, as I would assume the order of any lsm not listed
may end up being different.
>
>>>>> When we have "blob-sharing" how could I compile in tomoyo,
>>>>> but exclude it without a boot line option?
>>>> Ooh, yes, this series has no way to do that. Perhaps
>>>> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
>>>> totally remove LoadPin's CONFIG for this in favor it.
>>>
>>> I would generally prefer an optional CONFIG_LSM_ENABLE to
>>> CONFIG_LSM_DISABLE, but I understand the logic behind your
>>> approach. I would be looking for something like
>>>
>> +1 on the CONFIG_LSM_ENABLE ove DISABLE
>>
>>> CONFIG LSM_ENABLE
>>> string "Default set of enabled LSMs"
>>> default ""
>>>
>>> as opposed to
>>>
>>> CONFIG LSM_DISABLE
>>> string "Default set of disabled LSMs"
>>> default ""
>>>
>>> where an empty string is interpreted as "use 'em all"
>>> in either case.
>
> Yes, I like CONFIG_LSM_ENABLE if "empty" means "enable all". Should
> CONFIG_LSM_ENABLE replace all the other CONFIG-based LSM
> enabling/disabling?
I don't particularly like "empty" being "enable all". With that
how would I disable all builtin lsms so that I just boot with
capability.
An option of all or even * is more explicit and leaves the empty
set to mean disable everything
>
>>>>> When we have full stacking, how could I compile in selinux
>>>>> but exclude it?
>>>> Yup, same problem. Same suggested solution?
>>>>
>>>> Should lsm.enable/disable= also become a comma-separated list, or
>>>> should I leave it as a multi-instance thing like I have it?
>>>
>>> I prefer the multi-instance
>>> lsm.disable=selinux lsm.disable=yama
>>> to the list
>>> lsm.disable=selinux,yama
>>>
>>> but at this point I don't really care all that much.
>>
>> the comma separated list however is consistent with what is being
>> done for default order
>
> Yeah, and it would match the new CONFIG_LSM_ENABLE.
>
> FWIW, it was tedious to type "lsm.enable" and "lsm.disable" over and
> over when doing testing, so I almost prefer the comma separated list
> at the end of the day. I'll ponder this a bit.
>
> -Kees
>
On Thu, Sep 20, 2018 at 7:14 PM, John Johansen
<[email protected]> wrote:
> On 09/20/2018 07:05 PM, Kees Cook wrote:
>> On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
>> <[email protected]> wrote:
>>> On 09/20/2018 06:10 PM, Casey Schaufler wrote:
>>>> On 9/20/2018 5:45 PM, Kees Cook wrote:
>>>>> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>>>>>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>>>>>> config LSM_ORDER
>>>>>>> string "Default initialization order of builtin LSMs"
>>>>>>> - default "yama,loadpin,integrity"
>>>>>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>>>>>> If I want to compile all the major modules into my kernel and use
>>>>>> AppArmor by default would I use
>>>>>>
>>>>>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>>>>>
>>>>>> or
>>>>>>
>>>>>> default "yama,loadpin,integrity,apparmor"
>>>>> I was expecting the former, but the latter will have the same result.
>>>
>>> t find having the two be equivalent violates expectations. At least
>>> when considering the end goal of full/extreme stacking, its trivially
>>> the same with current major lsms being exclusive
>>
>> This mixes "enablement" with "ordering", though, and I think the past
>> threads have shown this to be largely problematic.
>>
>> However, with CONFIG_LSM_ENABLED, we get the effect you're looking for, IIUC.
>
> no, I was just stating in a world where we have full stacking those two
> are not equivalent, as I would assume the order of any lsm not listed
> may end up being different.
Right, the ordering would be defined first by runtime (lsm.order=)
followed any missing LSMs then ordered by their order in
CONFIG_LSM_ORDER=, followed by any still missing LSMs then ordered by
their order at link-time (which *may* be Makefile order, but could
change with LTO, etc).
>>>>>> When we have "blob-sharing" how could I compile in tomoyo,
>>>>>> but exclude it without a boot line option?
>>>>> Ooh, yes, this series has no way to do that. Perhaps
>>>>> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
>>>>> totally remove LoadPin's CONFIG for this in favor it.
>>>>
>>>> I would generally prefer an optional CONFIG_LSM_ENABLE to
>>>> CONFIG_LSM_DISABLE, but I understand the logic behind your
>>>> approach. I would be looking for something like
>>>>
>>> +1 on the CONFIG_LSM_ENABLE ove DISABLE
>>>
>>>> CONFIG LSM_ENABLE
>>>> string "Default set of enabled LSMs"
>>>> default ""
>>>>
>>>> as opposed to
>>>>
>>>> CONFIG LSM_DISABLE
>>>> string "Default set of disabled LSMs"
>>>> default ""
>>>>
>>>> where an empty string is interpreted as "use 'em all"
>>>> in either case.
>>
>> Yes, I like CONFIG_LSM_ENABLE if "empty" means "enable all". Should
>> CONFIG_LSM_ENABLE replace all the other CONFIG-based LSM
>> enabling/disabling?
>
> I don't particularly like "empty" being "enable all". With that
> how would I disable all builtin lsms so that I just boot with
> capability.
>
> An option of all or even * is more explicit and leaves the empty
> set to mean disable everything
Okay, that works. I prefer "all" FWIW.
-Kees
--
Kees Cook
Pixel Security
On 09/20/2018 08:02 PM, Kees Cook wrote:
> On Thu, Sep 20, 2018 at 7:14 PM, John Johansen
> <[email protected]> wrote:
>> On 09/20/2018 07:05 PM, Kees Cook wrote:
>>> On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
>>> <[email protected]> wrote:
>>>> On 09/20/2018 06:10 PM, Casey Schaufler wrote:
>>>>> On 9/20/2018 5:45 PM, Kees Cook wrote:
>>>>>> On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler <[email protected]> wrote:
>>>>>>> On 9/20/2018 9:23 AM, Kees Cook wrote:
>>>>>>>> config LSM_ORDER
>>>>>>>> string "Default initialization order of builtin LSMs"
>>>>>>>> - default "yama,loadpin,integrity"
>>>>>>>> + default "yama,loadpin,integrity,selinux,smack,tomoyo,apparmor"
>>>>>>> If I want to compile all the major modules into my kernel and use
>>>>>>> AppArmor by default would I use
>>>>>>>
>>>>>>> default "yama,loadpin,integrity,apparmor,selinux,smack,tomoyo"
>>>>>>>
>>>>>>> or
>>>>>>>
>>>>>>> default "yama,loadpin,integrity,apparmor"
>>>>>> I was expecting the former, but the latter will have the same result.
>>>>
>>>> t find having the two be equivalent violates expectations. At least
>>>> when considering the end goal of full/extreme stacking, its trivially
>>>> the same with current major lsms being exclusive
>>>
>>> This mixes "enablement" with "ordering", though, and I think the past
>>> threads have shown this to be largely problematic.
>>>
>>> However, with CONFIG_LSM_ENABLED, we get the effect you're looking for, IIUC.
>>
>> no, I was just stating in a world where we have full stacking those two
>> are not equivalent, as I would assume the order of any lsm not listed
>> may end up being different.
>
> Right, the ordering would be defined first by runtime (lsm.order=)
> followed any missing LSMs then ordered by their order in
> CONFIG_LSM_ORDER=, followed by any still missing LSMs then ordered by
> their order at link-time (which *may* be Makefile order, but could
> change with LTO, etc).
>
>>>>>>> When we have "blob-sharing" how could I compile in tomoyo,
>>>>>>> but exclude it without a boot line option?
>>>>>> Ooh, yes, this series has no way to do that. Perhaps
>>>>>> CONFIG_LSM_DISABLE in the same form as CONFIG_LSM_ORDER? I would
>>>>>> totally remove LoadPin's CONFIG for this in favor it.
>>>>>
>>>>> I would generally prefer an optional CONFIG_LSM_ENABLE to
>>>>> CONFIG_LSM_DISABLE, but I understand the logic behind your
>>>>> approach. I would be looking for something like
>>>>>
>>>> +1 on the CONFIG_LSM_ENABLE ove DISABLE
>>>>
>>>>> CONFIG LSM_ENABLE
>>>>> string "Default set of enabled LSMs"
>>>>> default ""
>>>>>
>>>>> as opposed to
>>>>>
>>>>> CONFIG LSM_DISABLE
>>>>> string "Default set of disabled LSMs"
>>>>> default ""
>>>>>
>>>>> where an empty string is interpreted as "use 'em all"
>>>>> in either case.
>>>
>>> Yes, I like CONFIG_LSM_ENABLE if "empty" means "enable all". Should
>>> CONFIG_LSM_ENABLE replace all the other CONFIG-based LSM
>>> enabling/disabling?
>>
>> I don't particularly like "empty" being "enable all". With that
>> how would I disable all builtin lsms so that I just boot with
>> capability.
>>
>> An option of all or even * is more explicit and leaves the empty
>> set to mean disable everything
>
> Okay, that works. I prefer "all" FWIW.
>
me too, I was just trying to throw out options.
On 9/21/2018 6:19 AM, John Johansen wrote:
> On 09/20/2018 08:02 PM, Kees Cook wrote:
>> On Thu, Sep 20, 2018 at 7:14 PM, John Johansen
>> <[email protected]> wrote:
>>> On 09/20/2018 07:05 PM, Kees Cook wrote:
>>>> On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
>>>> <[email protected]> wrote:
>>>>
>>>> Yes, I like CONFIG_LSM_ENABLE if "empty" means "enable all". Should
>>>> CONFIG_LSM_ENABLE replace all the other CONFIG-based LSM
>>>> enabling/disabling?
>>> I don't particularly like "empty" being "enable all". With that
>>> how would I disable all builtin lsms so that I just boot with
>>> capability.
>>>
>>> An option of all or even * is more explicit and leaves the empty
>>> set to mean disable everything
>> Okay, that works. I prefer "all" FWIW.
>>
> me too, I was just trying to throw out options.
I'll buy that. "all" is fine by me, although it means we
can't have an LSM named "all". :) We should also allow "none"
to mean no LSMs. I know lots of people who love using security=none.