[v11,02/11] LSM: Maintain a table of LSM attribute data

Message ID 20230616165055.4705-3-casey@schaufler-ca.com
State New
Headers
Series LSM: Three basic syscalls |

Commit Message

Casey Schaufler June 16, 2023, 4:50 p.m. UTC
  As LSMs are registered add their lsm_id pointers to a table.
This will be used later for attribute reporting.

Determine the number of possible security modules based on
their respective CONFIG options. This allows the number to be
known at build time. This allows data structures and tables
to use the constant.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 include/linux/security.h |  2 ++
 security/security.c      | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
  

Comments

kernel test robot June 26, 2023, 2:11 p.m. UTC | #1
Hello,

kernel test robot noticed "Kernel_panic-not_syncing:security_add_hooks_Too_many_LSMs_registered" on:

commit: 17e790c80fd532e2f5381ab9bc30a911229ec560 ("[PATCH v11 02/11] LSM: Maintain a table of LSM attribute data")
url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Identify-modules-by-more-than-name/20230617-005918
base: https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git 228020b490eda9133c9cb6f59a5ee1278d8c463f
patch link: https://lore.kernel.org/all/20230616165055.4705-3-casey@schaufler-ca.com/
patch subject: [PATCH v11 02/11] LSM: Maintain a table of LSM attribute data

in testcase: boot

compiler: gcc-12
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)



If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202306262112.c14a7466-oliver.sang@intel.com



[    3.070161][    T0] LSM: initializing lsm=lockdown,capability,landlock
[    3.072793][    T0] Kernel panic - not syncing: security_add_hooks Too many LSMs registered.
[    3.074648][    T0] CPU: 0 PID: 0 Comm: swapper Not tainted 6.4.0-rc1-00008-g17e790c80fd5 #1
[    3.076714][    T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[    3.076714][    T0] Call Trace:
[    3.076714][    T0]  dump_stack_lvl+0x50/0x65
[    3.076714][    T0]  dump_stack+0xd/0x12
[    3.076714][    T0]  panic+0xe3/0x238
[    3.076714][    T0]  security_add_hooks+0xe1/0xef
[    3.076714][    T0]  landlock_add_ptrace_hooks+0x1c/0x24
[    3.076714][    T0]  landlock_init+0x12/0x2c
[    3.076714][    T0]  initialize_lsm+0x31/0x50
[    3.076714][    T0]  ordered_lsm_init+0x296/0x2b3
[    3.076714][    T0]  security_init+0xbf/0xca
[    3.076714][    T0]  start_kernel+0x2ed/0x329
[    3.076714][    T0]  i386_start_kernel+0x47/0x47
[    3.076714][    T0]  startup_32_smp+0x151/0x154



To reproduce:

        # build kernel
	cd linux
	cp config-6.4.0-rc1-00008-g17e790c80fd5 .config
	make HOSTCC=gcc-12 CC=gcc-12 ARCH=i386 olddefconfig prepare modules_prepare bzImage modules
	make HOSTCC=gcc-12 CC=gcc-12 ARCH=i386 INSTALL_MOD_PATH=<mod-install-dir> modules_install
	cd <mod-install-dir>
	find lib/ | cpio -o -H newc --quiet | gzip > modules.cgz


        git clone https://github.com/intel/lkp-tests.git
        cd lkp-tests
        bin/lkp qemu -k <bzImage> -m modules.cgz job-script # job-script is attached in this email

        # if come across any failure that blocks the test,
        # please remove ~/.lkp and /lkp dir to run from a clean state.
  

Patch

diff --git a/include/linux/security.h b/include/linux/security.h
index e2734e9e44d5..569b1d8ab002 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -138,6 +138,8 @@  enum lockdown_reason {
 };
 
 extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
+extern u32 lsm_active_cnt;
+extern struct lsm_id *lsm_idlist[];
 
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
diff --git a/security/security.c b/security/security.c
index e56714ef045a..39c5225603cf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -36,6 +36,25 @@ 
 /* How many LSMs were built into the kernel? */
 #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
 
+/*
+ * How many LSMs are built into the kernel as determined at
+ * build time. Used to determine fixed array sizes.
+ * The capability module is accounted for by CONFIG_SECURITY
+ */
+#define LSM_CONFIG_COUNT ( \
+	(IS_ENABLED(CONFIG_SECURITY) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_TOMOYO) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_IMA) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_YAMA) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_LOADPIN) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \
+	(IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0))
+
 /*
  * These are descriptions of the reasons that can be passed to the
  * security_locked_down() LSM hook. Placing this array here allows
@@ -245,6 +264,12 @@  static void __init initialize_lsm(struct lsm_info *lsm)
 	}
 }
 
+/*
+ * Current index to use while initializing the lsm id list.
+ */
+u32 lsm_active_cnt __ro_after_init;
+struct lsm_id *lsm_idlist[LSM_CONFIG_COUNT] __ro_after_init;
+
 /* Populate ordered LSMs list from comma-separated LSM name list. */
 static void __init ordered_lsm_parse(const char *order, const char *origin)
 {
@@ -521,6 +546,17 @@  void __init security_add_hooks(struct security_hook_list *hooks, int count,
 {
 	int i;
 
+	if (lsm_active_cnt >= LSM_CONFIG_COUNT)
+		panic("%s Too many LSMs registered.\n", __func__);
+	/*
+	 * A security module may call security_add_hooks() more
+	 * than once during initialization, and LSM initialization
+	 * is serialized. Landlock is one such case.
+	 * Look at the previous entry, if there is one, for duplication.
+	 */
+	if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid)
+		lsm_idlist[lsm_active_cnt++] = lsmid;
+
 	for (i = 0; i < count; i++) {
 		hooks[i].lsmid = lsmid;
 		hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);