On 8/14/25 15:50, 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.

Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com>
Signed-off-by: Paul Moore <p...@paul-moore.com>

Reviewed-by: John Johansen <john.johan...@canonical.com>

---
  security/lsm.h      |  11 ++++
  security/lsm_init.c | 123 +++++++++++++++++++-------------------------
  security/security.c |   2 +
  3 files changed, 66 insertions(+), 70 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 37593805ba9e..2f7ae26fca0f 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_order[MAX_LSM_COUNT + 1];
  static __initdata struct lsm_info *lsm_exclusive;
-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);
  }
/**
@@ -239,7 +236,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);
  }
@@ -266,8 +263,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);
                        }
                }
        }
@@ -310,8 +307,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);
        }
  }
@@ -319,7 +315,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;
@@ -331,11 +327,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;
  }
/**
@@ -353,7 +350,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);
        }
  }
@@ -384,19 +383,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");
@@ -404,38 +400,25 @@ 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_pr("blob(bpf_map) size %d\n", blob_sizes.lbs_bpf_map);
+               lsm_pr("blob(bpf_prog) size %d\n", blob_sizes.lbs_bpf_prog);
+               lsm_pr("blob(bpf_token) size %d\n", blob_sizes.lbs_bpf_token);
        }
-       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);
-       init_debug("bpf map blob size    = %d\n", blob_sizes.lbs_bpf_map);
-       init_debug("bpf prog blob size   = %d\n", blob_sizes.lbs_bpf_prog);
-       init_debug("bpf token blob size  = %d\n", blob_sizes.lbs_bpf_token);
if (blob_sizes.lbs_file)
                lsm_file_cache = kmem_cache_create("lsm_file_cache",
@@ -447,9 +430,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 add46073af0c..c9642020755e 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];


Reply via email to