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
@@ -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 */
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 <redacted>
---
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(-)
@@ -7202,7 +7202,9 @@ void selinux_complete_init(void)/* SELinux requires early initialization in order to labelallprocessesandobjectswhentheyarecreated.*/-security_initcall(selinux_init);+DEFINE_LSM(selinux)+.init=selinux_init,+END_LSM;#if defined(CONFIG_NETFILTER)
LSM initialization failures have traditionally been ignored. We should
at least WARN when something goes wrong.
Signed-off-by: Kees Cook <redacted>
---
security/security.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
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 <redacted>
---
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(+)
@@ -7203,6 +7203,7 @@ void selinux_complete_init(void)/* SELinux requires early initialization in order to labelallprocessesandobjectswhentheyarecreated.*/DEFINE_LSM(selinux)+.flags=LSM_FLAG_LEGACY_MAJOR,.init=selinux_init,END_LSM;
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 <redacted>
---
security/security.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
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 <redacted>
---
include/linux/lsm_hooks.h | 1 +
security/apparmor/lsm.c | 5 +++--
security/selinux/hooks.c | 1 +
3 files changed, 5 insertions(+), 2 deletions(-)
@@ -44,6 +44,8 @@ char *lsm_names;/* Boot-time LSM user choice */static__initdataconstchar*chosen_major_lsm;+static__initconstconstchar*constbuiltin_lsm_order=CONFIG_LSM_ORDER;+/* Ordered list of LSMs to initialize. */static__initdatastructlsm_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. */+staticvoid__initparse_lsm_order(constchar*order,constchar*origin)+{+structlsm_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){+boolfound=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. */staticvoid__initprepare_lsm_order(void){structlsm_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");}}
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 <redacted>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
security/security.c | 15 ++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
@@ -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
@@ -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. */staticvoid__initprepare_lsm_order(void){structlsm_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. */+staticint__initchoose_lsm_order(char*str)+{+chosen_lsm_order=str;+return1;+}+__setup("lsm.order=",choose_lsm_order);+/* Enable LSM order debugging. */staticint__initenable_debug(char*str){
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 <redacted>
---
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(-)
@@ -1542,12 +1542,6 @@ static int __init apparmor_init(void){interror;-if(!apparmor_enabled||!security_module_enable("apparmor")){-aa_info_message("AppArmor disabled by boot time parameter");-apparmor_enabled=false;-return0;-}-aa_secids_init();error=aa_setup_dfa_engine();
@@ -52,33 +52,70 @@ static bool debug __initdata;pr_info(__VA_ARGS__);\}while(0)+/* Mark an LSM's enabled flag, if it exists. */+staticvoid__initset_enabled(structlsm_info*lsm,boolenabled)+{+if(lsm->enabled)+*lsm->enabled=enabled;+}++/* Is an LSM allowed to be enabled? */+staticbool__initlsm_allowed(structlsm_info*lsm)+{+/* Skip if the LSM is disabled. */+if(lsm->enabled&&!*lsm->enabled)+returnfalse;++/* Skip major-specific checks if not a major LSM. */+if((lsm->flags&LSM_FLAG_LEGACY_MAJOR)==0)+returntrue;++/* Disabled if this LSM isn't the chosen one. */+if(strcmp(lsm->name,chosen_lsm)!=0)+returnfalse;++returntrue;+}++/* Check if LSM should be enabled. Mark any that are disabled. */+staticvoid__initmaybe_initialize_lsm(structlsm_info*lsm)+{+intenabled=lsm_allowed(lsm);++/* Record enablement. */+set_enabled(lsm,enabled);++/* If selected, initialize the LSM. */+if(enabled){+intret;++init_debug("initializing %s\n",lsm->name);+ret=lsm->init();+WARN(ret,"%s failed to initialize: %d\n",lsm->name,ret);+}+}+staticvoid__initordered_lsm_init(void){structlsm_info*lsm;-intret;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);}}staticvoid__initmajor_lsm_init(void){structlsm_info*lsm;-intret;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)return0;}-/**-*security_module_enable-Loadgivensecuritymoduleonboot?-*@module:thenameofthemodule-*-*EachLSMmustpassthismethodbeforeregisteringitsownoperations-*toavoidsecurityregistrationraces.Thismethodmayalsobeused-*tocheckifyourLSMiscurrentlyloadedduringkernelinitialization.-*-*Returns:-*-*trueif:-*-*-ThepassedLSMistheonechosenbyuseratboottime,-*-orthepassedLSMisconfiguredasthedefaultandtheuserdidnot-*chooseanalternateLSMatboottime.-*-*Otherwise,returnfalse.-*/-int__initsecurity_module_enable(constchar*module)-{-return!strcmp(module,chosen_lsm);-}-/***security_add_hooks-Addamoduleshookstothehooklists.*@hooks:thehookstoadd
@@ -540,8 +540,6 @@ static int __init tomoyo_init(void){structcred*cred=(structcred*)current_cred();-if(!security_module_enable("tomoyo"))-return0;/* register ourselves with the security framework */security_add_hooks(tomoyo_hooks,ARRAY_SIZE(tomoyo_hooks),"tomoyo");printk(KERN_INFO"TOMOYO Linux initialized\n");
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 <redacted>
---
security/security.c | 47 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
@@ -53,10 +53,29 @@ static bool debug __initdata;}while(0)/* Mark an LSM's enabled flag, if it exists. */+staticintlsm_enabled_true__initdata=1;+staticintlsm_enabled_false__initdata=0;staticvoid__initset_enabled(structlsm_info*lsm,boolenabled){-if(lsm->enabled)+if(!lsm->enabled){+/*+*IftheLSMhasn'tconfiguredanenableflag,we+*canuseahard-codedsettingforstoringthe+*stateourselves.+*/+if(enabled)+lsm->enabled=&lsm_enabled_true;+else+lsm->enabled=&lsm_enabled_false;+}elseif(lsm->enabled==&lsm_enabled_true){+if(!enabled)+lsm->enabled=&lsm_enabled_false;+}elseif(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 */+staticint__initenable_lsm(char*str)+{+structlsm_info*lsm;++for(lsm=__start_lsm_info;lsm<__end_lsm_info;lsm++){+if(strcmp(str,lsm->name)==0)+set_enabled(lsm,true);+}+return1;+}+__setup("lsm.enable=",enable_lsm);++/* Explicitly disable an LSM */+staticint__initdisable_lsm(char*str)+{+structlsm_info*lsm;++for(lsm=__start_lsm_info;lsm<__end_lsm_info;lsm++){+if(strcmp(str,lsm->name)==0)+set_enabled(lsm,false);+}+return1;+}+__setup("lsm.disable=",disable_lsm);+staticboolmatch_last_lsm(constchar*list,constchar*lsm){constchar*last;
@@ -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
In preparation for making LSM selections outside of the LSMs, include
the name of LSMs in struct lsm_info.
Signed-off-by: Kees Cook <redacted>
---
include/linux/lsm_hooks.h | 4 ++++
1 file changed, 4 insertions(+)
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 <redacted>
---
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(-)
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 <redacted>
---
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(-)
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 <redacted>
---
include/asm-generic/vmlinux.lds.h | 10 +++++-----
include/linux/init.h | 4 ++--
security/security.c | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)
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 <redacted>
---
security/security.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -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__initloadpin_add_hooks(void)+staticint__initloadpin_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");+return0;}+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)");
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 <redacted>
---
security/security.c | 59 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 52 insertions(+), 7 deletions(-)
@@ -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)+structsecurity_hook_headssecurity_hook_heads__lsm_ro_after_init;staticATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
@@ -41,6 +44,9 @@ char *lsm_names;/* Boot-time LSM user choice */static__initdataconstchar*chosen_major_lsm;+/* Ordered list of LSMs to initialize. */+static__initdatastructlsm_info**ordered_lsms;+staticbooldebug__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? */+staticbool__initexists_ordered_lsm(structlsm_info*lsm)+{+structlsm_info**check;++for(check=ordered_lsms;*check;check++)+if(*check==lsm)+returntrue;++returnfalse;+}++/* Append an LSM to the list of ordered LSMs to initialize. */+staticintlast_lsm__initdata;+staticvoid__initappend_ordered_lsm(structlsm_info*lsm,constchar*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. */+staticvoid__initprepare_lsm_order(void)+{+structlsm_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? */staticbool__initlsm_allowed(structlsm_info*lsm){
@@ -141,6 +182,8 @@ int __init security_init(void)for(i=0;i<sizeof(security_hook_heads)/sizeof(structhlist_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);return0;}
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 <redacted>
---
security/security.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
@@ -81,14 +81,6 @@ static bool __init lsm_allowed(struct lsm_info *lsm)if(lsm->enabled&&!*lsm->enabled)returnfalse;-/* Skip major-specific checks if not a major LSM. */-if((lsm->flags&LSM_FLAG_LEGACY_MAJOR)==0)-returntrue;--/* Disabled if this LSM isn't the chosen one. */-if(strcmp(lsm->name,chosen_major_lsm)!=0)-returnfalse;-returntrue;}
@@ -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){+structlsm_info*lsm;++/*+*Tomatchtheoriginal"security="behavior,this+*explicitlydoesNOTfallbacktoanotherLegacyMajor+*iftheselectedonewasseparatelydisabled:disable+*allnon-matchingLegacyMajorLSMs.+*/+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);+}+}/**LoadminorLSMs,withthecapabilitymodulealwaysfirst.
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 <redacted>
---
security/security.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
@@ -34,16 +34,12 @@#define MAX_LSM_EVM_XATTR 2-/* Maximum number of letters for an LSM name string */-#define SECURITY_NAME_MAX 10-structsecurity_hook_headssecurity_hook_heads__lsm_ro_after_init;staticATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);char*lsm_names;/* Boot-time LSM user choice */-static__initdatacharchosen_lsm[SECURITY_NAME_MAX+1]=-CONFIG_DEFAULT_SECURITY;+static__initdataconstchar*chosen_major_lsm;staticbooldebug__initdata;#define init_debug(...) \
@@ -90,7 +86,7 @@ static bool __init lsm_allowed(struct lsm_info *lsm)returntrue;/* Disabled if this LSM isn't the chosen one. */-if(strcmp(lsm->name,chosen_lsm)!=0)+if(strcmp(lsm->name,chosen_major_lsm)!=0)returnfalse;returntrue;
@@ -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;+/**LoadminorLSMs,withthecapabilitymodulealwaysfirst.*/
@@ -173,12 +172,12 @@ int __init security_init(void)}/* Save user chosen LSM */-staticint__initchoose_lsm(char*str)+staticint__initchoose_major_lsm(char*str){-strncpy(chosen_lsm,str,SECURITY_NAME_MAX);+chosen_major_lsm=str;return1;}-__setup("security=",choose_lsm);+__setup("security=",choose_major_lsm);/* Enable LSM order debugging. */staticint__initenable_debug(char*str)
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 <redacted>
---
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(-)
@@ -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)enumlsm_order{LSM_ORDER_FIRST=-1,/* This is only for capabilities. */
@@ -7193,7 +7193,7 @@ void selinux_complete_init(void)/* SELinux requires early initialization in order to labelallprocessesandobjectswhentheyarecreated.*/DEFINE_LSM(selinux)-.flags=LSM_FLAG_LEGACY_MAJOR,+.flags=LSM_FLAG_LEGACY_MAJOR|LSM_FLAG_EXCLUSIVE,.enabled=&selinux_enabled,.init=selinux_init,END_LSM;
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 <redacted>
---
security/Kconfig | 39 +--------------------------------------
security/security.c | 23 +----------------------
2 files changed, 2 insertions(+), 60 deletions(-)
@@ -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){structlsm_info*lsm;
@@ -275,11 +259,6 @@ int __init security_init(void)prepare_lsm_order();ordered_lsm_init();-/*-*Loadalltheremainingsecuritymodules.-*/-major_lsm_init();-kfree(ordered_lsms);return0;}
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 <redacted>
---
include/linux/lsm_hooks.h | 7 +++++++
security/security.c | 22 ++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
@@ -142,6 +147,12 @@ static void __init prepare_lsm_order(void){structlsm_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? */
From: Martin Steigerwald <hidden> Date: 2018-09-20 20:14:52
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(-)
On Thu, Sep 20, 2018 at 1:14 PM, Martin Steigerwald [off-list ref] wrote:
Kees Cook - 20.09.18, 18:23:
quoted
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
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 <redacted>
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 <redacted>
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.
@@ -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)+structsecurity_hook_headssecurity_hook_heads__lsm_ro_after_init;staticATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
@@ -41,6 +44,9 @@ char *lsm_names;/* Boot-time LSM user choice */static__initdataconstchar*chosen_major_lsm;+/* Ordered list of LSMs to initialize. */+static__initdatastructlsm_info**ordered_lsms;+staticbooldebug__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? */+staticbool__initexists_ordered_lsm(structlsm_info*lsm)+{+structlsm_info**check;++for(check=ordered_lsms;*check;check++)+if(*check==lsm)+returntrue;++returnfalse;+}++/* Append an LSM to the list of ordered LSMs to initialize. */+staticintlast_lsm__initdata;+staticvoid__initappend_ordered_lsm(structlsm_info*lsm,constchar*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. */+staticvoid__initprepare_lsm_order(void)+{+structlsm_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? */staticbool__initlsm_allowed(structlsm_info*lsm){
@@ -141,6 +182,8 @@ int __init security_init(void)for(i=0;i<sizeof(security_hook_heads)/sizeof(structhlist_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);return0;}
@@ -276,5 +276,16 @@ config DEFAULT_SECURITYdefault"apparmor"ifDEFAULT_SECURITY_APPARMORdefault""ifDEFAULT_SECURITY_DAC+configLSM_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.
quoted hunk
+
+ If unsure, leave this as the default.
+
endmenu
@@ -44,6 +44,8 @@ char *lsm_names;/* Boot-time LSM user choice */static__initdataconstchar*chosen_major_lsm;+static__initconstconstchar*constbuiltin_lsm_order=CONFIG_LSM_ORDER;+/* Ordered list of LSMs to initialize. */static__initdatastructlsm_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. */+staticvoid__initparse_lsm_order(constchar*order,constchar*origin)+{+structlsm_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){+boolfound=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. */staticvoid__initprepare_lsm_order(void){structlsm_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");}}
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 <redacted>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
security/security.c | 15 ++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
@@ -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?
quoted hunk
+
machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb
@@ -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. */staticvoid__initprepare_lsm_order(void){structlsm_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. */+staticint__initchoose_lsm_order(char*str)+{+chosen_lsm_order=str;+return1;+}+__setup("lsm.order=",choose_lsm_order);+/* Enable LSM order debugging. */staticint__initenable_debug(char*str){
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 <redacted>
---
security/Kconfig | 39 +--------------------------------------
security/security.c | 23 +----------------------
2 files changed, 2 insertions(+), 60 deletions(-)
@@ -239,46 +239,9 @@ source security/yama/Kconfigsourcesecurity/integrity/Kconfig-choice-prompt"Default security module"-defaultDEFAULT_SECURITY_SELINUXifSECURITY_SELINUX-defaultDEFAULT_SECURITY_SMACKifSECURITY_SMACK-defaultDEFAULT_SECURITY_TOMOYOifSECURITY_TOMOYO-defaultDEFAULT_SECURITY_APPARMORifSECURITY_APPARMOR-defaultDEFAULT_SECURITY_DAC--help-Selectthesecuritymodulethatwillbeusedbydefaultifthe-kernelparametersecurity=isnotspecified.--configDEFAULT_SECURITY_SELINUX-bool"SELinux"ifSECURITY_SELINUX=y--configDEFAULT_SECURITY_SMACK-bool"Simplified Mandatory Access Control"ifSECURITY_SMACK=y--configDEFAULT_SECURITY_TOMOYO-bool"TOMOYO"ifSECURITY_TOMOYO=y--configDEFAULT_SECURITY_APPARMOR-bool"AppArmor"ifSECURITY_APPARMOR=y--configDEFAULT_SECURITY_DAC-bool"Unix Discretionary Access Controls"--endchoice--configDEFAULT_SECURITY-string-default"selinux"ifDEFAULT_SECURITY_SELINUX-default"smack"ifDEFAULT_SECURITY_SMACK-default"tomoyo"ifDEFAULT_SECURITY_TOMOYO-default"apparmor"ifDEFAULT_SECURITY_APPARMOR-default""ifDEFAULT_SECURITY_DAC-configLSM_ORDERstring"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?
quoted hunk
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list will be link-order initialized
@@ -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){structlsm_info*lsm;
@@ -275,11 +259,6 @@ int __init security_init(void)prepare_lsm_order();ordered_lsm_init();-/*-*Loadalltheremainingsecuritymodules.-*/-major_lsm_init();-kfree(ordered_lsms);return0;}
On Thu, Sep 20, 2018 at 5:04 PM, Casey Schaufler [off-list ref] wrote:
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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 <redacted>
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 [off-list ref] wrote:
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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 <redacted>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
security/security.c | 15 ++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
@@ -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 [off-list ref] wrote:
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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 Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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.
quoted
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.
quoted
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.
From: John Johansen <john.johansen@canonical.com> Date: 2018-09-21 01:39:38
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
On 9/20/2018 5:45 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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
quoted
quoted
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.
quoted
quoted
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
[off-list ref] wrote:
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
quoted
On 9/20/2018 5:45 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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.
quoted
quoted
quoted
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
quoted
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?
quoted
quoted
quoted
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
From: John Johansen <john.johansen@canonical.com> Date: 2018-09-21 02:15:02
On 09/20/2018 07:05 PM, Kees Cook wrote:
On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
[off-list ref] wrote:
quoted
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
quoted
On 9/20/2018 5:45 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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.
quoted
quoted
quoted
quoted
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
quoted
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
quoted
quoted
quoted
quoted
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
[off-list ref] wrote:
On 09/20/2018 07:05 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
[off-list ref] wrote:
quoted
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
quoted
On 9/20/2018 5:45 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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).
quoted
quoted
quoted
quoted
quoted
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
quoted
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
From: John Johansen <john.johansen@canonical.com> Date: 2018-09-21 13:20:24
On 09/20/2018 08:02 PM, Kees Cook wrote:
On Thu, Sep 20, 2018 at 7:14 PM, John Johansen
[off-list ref] wrote:
quoted
On 09/20/2018 07:05 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
[off-list ref] wrote:
quoted
On 09/20/2018 06:10 PM, Casey Schaufler wrote:
quoted
On 9/20/2018 5:45 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 5:25 PM, Casey Schaufler [off-list ref] wrote:
quoted
On 9/20/2018 9:23 AM, Kees Cook wrote:
quoted
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).
quoted
quoted
quoted
quoted
quoted
quoted
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
quoted
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
On Thu, Sep 20, 2018 at 7:14 PM, John Johansen
[off-list ref] wrote:
quoted
On 09/20/2018 07:05 PM, Kees Cook wrote:
quoted
On Thu, Sep 20, 2018 at 6:39 PM, John Johansen
[off-list ref] 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.