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

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

Commit Message

Casey Schaufler Feb. 22, 2023, 8:08 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>
---
 include/linux/security.h |  2 ++
 security/security.c      | 44 ++++++++++++++++++++++++++++++++--------
 2 files changed, 38 insertions(+), 8 deletions(-)
  

Comments

kernel test robot Feb. 25, 2023, 1:37 p.m. UTC | #1
Greeting,

FYI, we noticed WARNING:at_security/security.c:#append_ordered_lsm due to commit (built with gcc-11):

commit: af5e9ce5abd1a5a2e91036acd8b340072ad840d6 ("[PATCH v6 02/11] LSM: Maintain a table of LSM attribute data")
url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
base: https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git c828441f21ddc819a28b5723a72e3c840e9de1c6
patch link: https://lore.kernel.org/all/20230222200838.8149-3-casey@schaufler-ca.com/
patch subject: [PATCH v6 02/11] LSM: Maintain a table of LSM attribute data

in testcase: boot

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

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):


If you fix the issue, kindly add following tag
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Link: https://lore.kernel.org/oe-lkp/202302251600.ad80292-oliver.sang@intel.com


[    0.397553][    T0] ------------[ cut here ]------------
[    0.398454][    T0] builtin: out of LSM slots!?
[ 0.399456][ T0] WARNING: CPU: 0 PID: 0 at security/security.c:173 append_ordered_lsm (security/security.c:173 (discriminator 1)) 
[    0.401167][    T0] Modules linked in:
[    0.402167][    T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.2.0-rc4-00030-gaf5e9ce5abd1 #1
[    0.403616][    T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-5 04/01/2014
[ 0.404678][ T0] RIP: 0010:append_ordered_lsm (security/security.c:173 (discriminator 1)) 
[ 0.405466][ T0] Code: 89 f5 53 48 89 fb e8 de fe ff ff 84 c0 75 79 48 63 05 16 8f 13 00 83 f8 03 75 13 48 89 ee 48 c7 c7 34 aa 68 82 e8 1d c2 96 fe <0f> 0b eb 5a 48 83 7b 18 00 75 08 48 c7 43 18 18 3f 65 83 8d 50 01
All code
========
   0:	89 f5                	mov    %esi,%ebp
   2:	53                   	push   %rbx
   3:	48 89 fb             	mov    %rdi,%rbx
   6:	e8 de fe ff ff       	callq  0xfffffffffffffee9
   b:	84 c0                	test   %al,%al
   d:	75 79                	jne    0x88
   f:	48 63 05 16 8f 13 00 	movslq 0x138f16(%rip),%rax        # 0x138f2c
  16:	83 f8 03             	cmp    $0x3,%eax
  19:	75 13                	jne    0x2e
  1b:	48 89 ee             	mov    %rbp,%rsi
  1e:	48 c7 c7 34 aa 68 82 	mov    $0xffffffff8268aa34,%rdi
  25:	e8 1d c2 96 fe       	callq  0xfffffffffe96c247
  2a:*	0f 0b                	ud2    		<-- trapping instruction
  2c:	eb 5a                	jmp    0x88
  2e:	48 83 7b 18 00       	cmpq   $0x0,0x18(%rbx)
  33:	75 08                	jne    0x3d
  35:	48 c7 43 18 18 3f 65 	movq   $0xffffffff83653f18,0x18(%rbx)
  3c:	83 
  3d:	8d 50 01             	lea    0x1(%rax),%edx

Code starting with the faulting instruction
===========================================
   0:	0f 0b                	ud2    
   2:	eb 5a                	jmp    0x5e
   4:	48 83 7b 18 00       	cmpq   $0x0,0x18(%rbx)
   9:	75 08                	jne    0x13
   b:	48 c7 43 18 18 3f 65 	movq   $0xffffffff83653f18,0x18(%rbx)
  12:	83 
  13:	8d 50 01             	lea    0x1(%rax),%edx
[    0.406998][    T0] RSP: 0000:ffffffff82a03e90 EFLAGS: 00010286
[    0.408167][    T0] RAX: 0000000000000000 RBX: ffffffff836fe878 RCX: c0000000ffff7fff
[    0.409589][    T0] RDX: 0000000000000000 RSI: 0000000000027ffb RDI: 0000000000000001
[    0.411167][    T0] RBP: ffffffff8266b47d R08: 0000000000000000 R09: 00000000ffff7fff
[    0.412591][    T0] R10: ffffffff82a03d40 R11: ffffffff82dd70a8 R12: ffff88810018a573
[    0.414167][    T0] R13: ffff88810018a540 R14: 0000000000000001 R15: 0000000000000000
[    0.415626][    T0] FS:  0000000000000000(0000) GS:ffff88842fc00000(0000) knlGS:0000000000000000
[    0.417170][    T0] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    0.418468][    T0] CR2: ffff88843ffff000 CR3: 0000000002a0a000 CR4: 00000000000406b0
[    0.419598][    T0] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[    0.421167][    T0] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[    0.422618][    T0] Call Trace:
[    0.423402][    T0]  <TASK>
[ 0.424169][ T0] ordered_lsm_parse (security/security.c:307) 
[ 0.425017][ T0] ordered_lsm_init (security/security.c:379) 
[ 0.425457][ T0] security_init (security/security.c:459) 
[ 0.426438][ T0] start_kernel (init/main.c:1129) 
[ 0.427441][ T0] secondary_startup_64_no_verify (arch/x86/kernel/head_64.S:358) 
[    0.428466][    T0]  </TASK>
[    0.429401][    T0] ---[ end trace 0000000000000000 ]---
[    0.430466][    T0] LSM: initializing lsm=capability,yama,integrity
[    0.431488][    T0] Yama: becoming mindful.
[    0.433189][    T0] Mount-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.434656][    T0] Mountpoint-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.436718][    T0] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[    0.437498][    T0] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[    0.439173][    T0] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization
[    0.440620][    T0] Spectre V2 : Mitigation: Retpolines
[    0.441458][    T0] Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch
[    0.443167][    T0] Spectre V2 : Spectre v2 / SpectreRSB : Filling RSB on VMEXIT
[    0.444582][    T0] Speculative Store Bypass: Vulnerable
[    0.445466][    T0] MDS: Vulnerable: Clear CPU buffers attempted, no microcode
[    0.447166][    T0] MMIO Stale Data: Unknown: No mitigations
[    0.475387][    T0] Freeing SMP alternatives memory: 44K
[    0.476416][    T1] smpboot: CPU0: Intel Xeon E312xx (Sandy Bridge) (family: 0x6, model: 0x2a, stepping: 0x1)
[    0.477947][    T1] cblist_init_generic: Setting adjustable number of callback queues.
[    0.478169][    T1] cblist_init_generic: Setting shift to 1 and lim to 1.
[    0.479233][    T1] cblist_init_generic: Setting shift to 1 and lim to 1.


To reproduce:

        # build kernel
	cd linux
	cp config-6.2.0-rc4-00030-gaf5e9ce5abd1 .config
	make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 olddefconfig prepare modules_prepare bzImage modules
	make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 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 5b67f208f7de..33ed1860b96f 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 07a8fe7f92bf..4b81734ae9bd 100644
--- a/security/security.c
+++ b/security/security.c
@@ -28,12 +28,29 @@ 
 #include <linux/backing-dev.h>
 #include <linux/string.h>
 #include <linux/msg.h>
+#include <uapi/linux/lsm.h>
 #include <net/flow.h>
 
 #define MAX_LSM_EVM_XATTR	2
 
-/* 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_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_SECURITY_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
@@ -90,7 +107,7 @@  static __initdata const char *chosen_major_lsm;
 static __initconst const char * const builtin_lsm_order = CONFIG_LSM;
 
 /* Ordered list of LSMs to initialize. */
-static __initdata struct lsm_info **ordered_lsms;
+static __initdata struct lsm_info *ordered_lsms[LSM_COUNT];
 static __initdata struct lsm_info *exclusive;
 
 static __initdata bool debug;
@@ -341,13 +358,16 @@  static void __init report_lsm_order(void)
 	pr_cont("\n");
 }
 
+/*
+ * Current index to use while initializing the lsm id list.
+ */
+u32 lsm_active_cnt __lsm_ro_after_init;
+struct lsm_id *lsm_idlist[LSM_COUNT] __lsm_ro_after_init;
+
 static void __init ordered_lsm_init(void)
 {
 	struct lsm_info **lsm;
 
-	ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
-				GFP_KERNEL);
-
 	if (chosen_lsm_order) {
 		if (chosen_major_lsm) {
 			pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
@@ -387,8 +407,6 @@  static void __init ordered_lsm_init(void)
 	lsm_early_task(current);
 	for (lsm = ordered_lsms; *lsm; lsm++)
 		initialize_lsm(*lsm);
-
-	kfree(ordered_lsms);
 }
 
 int __init early_security_init(void)
@@ -513,6 +531,16 @@  void __init security_add_hooks(struct security_hook_list *hooks, int count,
 {
 	int i;
 
+	/*
+	 * A security module may call security_add_hooks() more
+	 * than once. Landlock is one such case.
+	 */
+	if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid)
+		lsm_idlist[lsm_active_cnt++] = lsmid;
+
+	if (lsm_active_cnt > LSM_COUNT)
+		panic("%s Too many LSMs registered.\n", __func__);
+
 	for (i = 0; i < count; i++) {
 		hooks[i].lsmid = lsmid;
 		hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);