On 7/21/2025 4:21 PM, Paul Moore wrote: > Move away from an init specific init_debug() macro to a more general > lsm_pr()/lsm_pr_cont()/lsm_pr_dbg() set of macros that are available > both before and after init. In the process we do a number of minor > changes to improve the LSM initialization output and cleanup the code > somewhat. > > Signed-off-by: Paul Moore <p...@paul-moore.com>
Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com> > --- > security/lsm.h | 11 +++++ > security/lsm_init.c | 117 +++++++++++++++++++------------------------- > security/security.c | 2 + > 3 files changed, 63 insertions(+), 67 deletions(-) > > diff --git a/security/lsm.h b/security/lsm.h > index dbe755c45e57..8dc267977ae0 100644 > --- a/security/lsm.h > +++ b/security/lsm.h > @@ -6,9 +6,20 @@ > #ifndef _LSM_H_ > #define _LSM_H_ > > +#include <linux/printk.h> > #include <linux/lsm_hooks.h> > #include <linux/lsm_count.h> > > +/* LSM debugging */ > +extern bool lsm_debug; > +#define lsm_pr(...) pr_info(__VA_ARGS__) > +#define lsm_pr_cont(...) pr_cont(__VA_ARGS__) > +#define lsm_pr_dbg(...) > \ > + do { \ > + if (lsm_debug) \ > + pr_info(__VA_ARGS__); \ > + } while (0) > + > /* List of configured LSMs */ > extern unsigned int lsm_active_cnt; > extern const struct lsm_id *lsm_idlist[]; > diff --git a/security/lsm_init.c b/security/lsm_init.c > index 75e97f6b530c..0a8e4c725055 100644 > --- a/security/lsm_init.c > +++ b/security/lsm_init.c > @@ -30,13 +30,6 @@ static __initdata const char *lsm_order_legacy; > static __initdata struct lsm_info *lsm_exclusive; > static __initdata struct lsm_info *lsm_order[MAX_LSM_COUNT + 1]; > > -static __initdata bool debug; > -#define init_debug(...) > \ > - do { \ > - if (debug) \ > - pr_info(__VA_ARGS__); \ > - } while (0) > - > #define lsm_order_for_each(iter) \ > for ((iter) = lsm_order; *(iter); (iter)++) > #define lsm_for_each_raw(iter) > \ > @@ -77,7 +70,7 @@ __setup("lsm=", lsm_choose_lsm); > */ > static int __init lsm_debug_enable(char *str) > { > - debug = true; > + lsm_debug = true; > return 1; > } > __setup("lsm.debug", lsm_debug_enable); > @@ -143,22 +136,28 @@ static void __init lsm_order_append(struct lsm_info > *lsm, const char *src) > return; > > /* Skip explicitly disabled LSMs. */ > - if (lsm->enabled && !lsm_is_enabled(lsm)) > - goto out; > + if (lsm->enabled && !lsm_is_enabled(lsm)) { > + lsm_pr_dbg("skip previously disabled LSM %s:%s\n", > + src, lsm->id->name); > + return; > + } > > - if (WARN(lsm_active_cnt == MAX_LSM_COUNT, > - "%s: out of LSM static calls!?\n", src)) { > + if (lsm_active_cnt == MAX_LSM_COUNT) { > + pr_warn("exceeded maximum LSM count on %s:%s\n", > + src, lsm->id->name); > lsm_enabled_set(lsm, false); > - goto out; > + return; > } > > if (lsm->flags & LSM_FLAG_EXCLUSIVE) { > if (lsm_exclusive) { > - init_debug("exclusive disabled: %s\n", lsm->id->name); > + lsm_pr_dbg("skip exclusive LSM conflict %s:%s\n", > + src, lsm->id->name); > lsm_enabled_set(lsm, false); > - goto out; > + return; > } else { > - init_debug("exclusive chosen: %s\n", lsm->id->name); > + lsm_pr_dbg("select exclusive LSM %s:%s\n", > + src, lsm->id->name); > lsm_exclusive = lsm; > } > } > @@ -167,9 +166,7 @@ static void __init lsm_order_append(struct lsm_info *lsm, > const char *src) > lsm_order[lsm_active_cnt] = lsm; > lsm_idlist[lsm_active_cnt++] = lsm->id; > > -out: > - init_debug("%s ordered: %s (%s)\n", src, lsm->id->name, > - lsm_is_enabled(lsm) ? "enabled" : "disabled"); > + lsm_pr_dbg("enabling LSM %s:%s\n", src, lsm->id->name); > } > > /** > @@ -236,7 +233,7 @@ static void __init lsm_init_single(struct lsm_info *lsm) > if (!lsm_is_enabled(lsm)) > return; > > - init_debug("initializing %s\n", lsm->id->name); > + lsm_pr_dbg("initializing %s\n", lsm->id->name); > ret = lsm->init(); > WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret); > } > @@ -263,8 +260,8 @@ static void __init lsm_order_parse(const char *list, > const char *src) > if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) && > strcmp(lsm->id->name, lsm_order_legacy)) { > lsm_enabled_set(lsm, false); > - init_debug("security=%s disabled: %s (only one > legacy major LSM)\n", > - lsm_order_legacy, lsm->id->name); > + lsm_pr_dbg("skip legacy LSM conflict %s:%s\n", > + src, lsm->id->name); > } > } > } > @@ -307,8 +304,7 @@ static void __init lsm_order_parse(const char *list, > const char *src) > if (lsm_order_exists(lsm)) > continue; > lsm_enabled_set(lsm, false); > - init_debug("%s skipped: %s (not in requested order)\n", > - src, lsm->id->name); > + lsm_pr_dbg("skip disabled LSM %s:%s\n", src, lsm->id->name); > } > } > > @@ -316,7 +312,7 @@ static void __init lsm_order_parse(const char *list, > const char *src) > * lsm_static_call_init - Initialize a LSM's static calls > * @hl: LSM hook list > */ > -static void __init lsm_static_call_init(struct security_hook_list *hl) > +static int __init lsm_static_call_init(struct security_hook_list *hl) > { > struct lsm_static_call *scall = hl->scalls; > int i; > @@ -328,11 +324,12 @@ static void __init lsm_static_call_init(struct > security_hook_list *hl) > hl->hook.lsm_func_addr); > scall->hl = hl; > static_branch_enable(scall->active); > - return; > + return 0; > } > scall++; > } > - panic("%s - Ran out of static slots.\n", __func__); > + > + return -ENOSPC; > } > > /** > @@ -350,7 +347,9 @@ void __init security_add_hooks(struct security_hook_list > *hooks, int count, > > for (i = 0; i < count; i++) { > hooks[i].lsmid = lsmid; > - lsm_static_call_init(&hooks[i]); > + if (lsm_static_call_init(&hooks[i])) > + panic("exhausted LSM callback slots with LSM %s\n", > + lsmid->name); > } > } > > @@ -381,19 +380,16 @@ int __init security_init(void) > { > unsigned int cnt; > struct lsm_info **lsm; > - struct lsm_info *early; > - unsigned int first = 0; > > - init_debug("legacy security=%s\n", lsm_order_legacy ? : " > *unspecified*"); > - init_debug(" CONFIG_LSM=%s\n", lsm_order_builtin); > - init_debug("boot arg lsm=%s\n", lsm_order_cmdline ? : " *unspecified*"); > + if (lsm_debug) { > + lsm_pr("built-in LSM list: %s\n", lsm_order_builtin); > + lsm_pr("legacy LSM parameter: %s\n", lsm_order_legacy); > + lsm_pr("boot LSM parameter: %s\n", lsm_order_cmdline); > + } > > if (lsm_order_cmdline) { > - if (lsm_order_legacy) { > - pr_warn("security=%s is ignored because it is > superseded by lsm=%s\n", > - lsm_order_legacy, lsm_order_cmdline); > + if (lsm_order_legacy) > lsm_order_legacy = NULL; > - } > lsm_order_parse(lsm_order_cmdline, "cmdline"); > } else > lsm_order_parse(lsm_order_builtin, "builtin"); > @@ -401,35 +397,22 @@ int __init security_init(void) > lsm_order_for_each(lsm) > lsm_prepare(*lsm); > > - pr_info("initializing lsm="); > - lsm_early_for_each_raw(early) { > - if (lsm_is_enabled(early)) > - pr_cont("%s%s", > - first++ == 0 ? "" : ",", early->id->name); > + if (lsm_debug) { > + lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred); > + lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file); > + lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib); > + lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode); > + lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc); > + lsm_pr("blob(key) size %d\n", blob_sizes.lbs_key); > + lsm_pr("blob(msg_msg)_size %d\n", blob_sizes.lbs_msg_msg); > + lsm_pr("blob(sock) size %d\n", blob_sizes.lbs_sock); > + lsm_pr("blob(superblock) size %d\n", blob_sizes.lbs_superblock); > + lsm_pr("blob(perf_event) size %d\n", blob_sizes.lbs_perf_event); > + lsm_pr("blob(task) size %d\n", blob_sizes.lbs_task); > + lsm_pr("blob(tun_dev) size %d\n", blob_sizes.lbs_tun_dev); > + lsm_pr("blob(xattr) count %d\n", blob_sizes.lbs_xattr_count); > + lsm_pr("blob(bdev) size %d\n", blob_sizes.lbs_bdev); > } > - lsm_order_for_each(lsm) { > - if (lsm_is_enabled(*lsm)) > - pr_cont("%s%s", > - first++ == 0 ? "" : ",", (*lsm)->id->name); > - } > - pr_cont("\n"); > - > - init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); > - init_debug("file blob size = %d\n", blob_sizes.lbs_file); > - init_debug("ib blob size = %d\n", blob_sizes.lbs_ib); > - init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); > - init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); > -#ifdef CONFIG_KEYS > - init_debug("key blob size = %d\n", blob_sizes.lbs_key); > -#endif /* CONFIG_KEYS */ > - init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); > - init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); > - init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); > - init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event); > - init_debug("task blob size = %d\n", blob_sizes.lbs_task); > - init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev); > - init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count); > - init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); > > if (blob_sizes.lbs_file) > lsm_file_cache = kmem_cache_create("lsm_file_cache", > @@ -441,9 +424,9 @@ int __init security_init(void) > SLAB_PANIC, NULL); > > if (lsm_cred_alloc((struct cred *)current->cred, GFP_KERNEL)) > - panic("%s: early cred alloc failed.\n", __func__); > + panic("early LSM cred alloc failed\n"); > if (lsm_task_alloc(current)) > - panic("%s: early task alloc failed.\n", __func__); > + panic("early LSM task alloc failed\n"); > > cnt = 0; > lsm_order_for_each(lsm) { > diff --git a/security/security.c b/security/security.c > index 106f225f4a80..9dd1435f9965 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -73,6 +73,8 @@ const char *const > lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = { > [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", > }; > > +bool lsm_debug __ro_after_init; > + > unsigned int lsm_active_cnt __ro_after_init; > const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; >