From 4408e300a67ab2ce2505087986a9fe922c800ffd Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 22 Aug 2018 13:52:40 +0200 Subject: [PATCH 01/15] security/capabilities: remove check for -EINVAL bprm_caps_from_vfs_caps() never returned -EINVAL so remove the rc == -EINVAL check. Signed-off-by: Christian Brauner Reviewed-by: Serge Hallyn Signed-off-by: James Morris --- security/commoncap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index f4c33abd9959..6012f0cd8157 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -684,9 +684,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_f } rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_fcap); - if (rc == -EINVAL) - printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", - __func__, rc, bprm->filename); out: if (rc) From dbdb75bd087954aaf9b3248109cb85748b62c21d Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Tue, 4 Sep 2018 16:41:39 +0800 Subject: [PATCH 02/15] security: tomoyo: Fix obsolete function simple_strtoul is obsolete, and use kstrtouint instead Signed-off-by: Ding Xiang Acked-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 03923a138ef5..9b38f94b5dd0 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1660,7 +1660,8 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) head->r.eof = true; if (tomoyo_str_starts(&buf, "global-pid ")) global_pid = true; - pid = (unsigned int) simple_strtoul(buf, NULL, 10); + if (kstrtouint(buf, 10, &pid)) + return; rcu_read_lock(); if (global_pid) p = find_task_by_pid_ns(pid, &init_pid_ns); From 0d42d73a37ff91028785e42a6bf12fc020a277c1 Mon Sep 17 00:00:00 2001 From: Igor Stoppa Date: Wed, 5 Sep 2018 23:34:43 +0300 Subject: [PATCH 03/15] seccomp: remove unnecessary unlikely() WARN_ON() already contains an unlikely(), so it's not necessary to wrap it into another. Signed-off-by: Igor Stoppa Acked-by: Kees Cook Cc: linux-security-module@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: James Morris --- kernel/seccomp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index fd023ac24e10..5a2a9af4663e 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -195,7 +195,7 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd, READ_ONCE(current->seccomp.filter); /* Ensure unexpected behavior doesn't result in failing open. */ - if (unlikely(WARN_ON(f == NULL))) + if (WARN_ON(f == NULL)) return SECCOMP_RET_KILL_PROCESS; if (!sd) { @@ -297,7 +297,7 @@ static inline pid_t seccomp_can_sync_threads(void) /* Return the first thread that cannot be synchronized. */ failed = task_pid_vnr(thread); /* If the pid cannot be resolved, then return -ESRCH */ - if (unlikely(WARN_ON(failed == 0))) + if (WARN_ON(failed == 0)) failed = -ESRCH; return failed; } From 2ecefa0a15fd0ef88b9cd5d15ceb813008136431 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 28 Sep 2018 00:51:20 +0100 Subject: [PATCH 04/15] keys: Fix the use of the C++ keyword "private" in uapi/linux/keyctl.h The keyctl_dh_params struct in uapi/linux/keyctl.h contains the symbol "private" which means that the header file will cause compilation failure if #included in to a C++ program. Further, the patch that added the same struct to the keyutils package named the symbol "priv", not "private". The previous attempt to fix this (commit 8a2336e549d3) did so by simply renaming the kernel's copy of the field to dh_private, but this then breaks existing userspace and as such has been reverted (commit 8c0f9f5b309d). [And note, to those who think that wrapping the struct in extern "C" {} will work: it won't; that only changes how symbol names are presented to the assembler and linker.]. Instead, insert an anonymous union around the "private" member and add a second member in there with the name "priv" to match the one in the keyutils package. The "private" member is then wrapped in !__cplusplus cpp-conditionals to hide it from C++. Fixes: ddbb41148724 ("KEYS: Add KEYCTL_DH_COMPUTE command") Fixes: 8a2336e549d3 ("uapi/linux/keyctl.h: don't use C++ reserved keyword as a struct member name") Signed-off-by: David Howells cc: Randy Dunlap cc: Lubomir Rintel cc: James Morris cc: Mat Martineau cc: Stephan Mueller cc: Andrew Morton cc: Linus Torvalds cc: stable@vger.kernel.org Signed-off-by: James Morris --- include/uapi/linux/keyctl.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index 7b8c9e19bad1..0f3cb13db8e9 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -65,7 +65,12 @@ /* keyctl structures */ struct keyctl_dh_params { - __s32 private; + union { +#ifndef __cplusplus + __s32 private; +#endif + __s32 priv; + }; __s32 prime; __s32 base; }; From e6123c524064a571616ec978b1317f1696eff0ae Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 8 Oct 2018 17:46:04 -0700 Subject: [PATCH 05/15] security: fix LSM description location Acked-by: Kees Cook Fix Documentation location reference for where LSM descriptions should be placed. Suggested-by: Kees Cook Signed-off-by: Randy Dunlap Cc: James Morris Cc: "Serge E. Hallyn" Cc: linux-security-module@vger.kernel.org Signed-off-by: James Morris --- Documentation/security/LSM.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/security/LSM.rst b/Documentation/security/LSM.rst index 98522e0e1ee2..8b9ee597e9d0 100644 --- a/Documentation/security/LSM.rst +++ b/Documentation/security/LSM.rst @@ -5,7 +5,7 @@ Linux Security Module Development Based on https://lkml.org/lkml/2007/10/26/215, a new LSM is accepted into the kernel when its intent (a description of what it tries to protect against and in what cases one would expect to -use it) has been appropriately documented in ``Documentation/security/LSM.rst``. +use it) has been appropriately documented in ``Documentation/admin-guide/LSM/``. This allows an LSM's code to be easily compared to its goals, and so that end users and distros can make a more informed decision about which LSMs suit their requirements. From 98d291708cbaab06efec195d0810a7ef60f7603a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:17 -0700 Subject: [PATCH 06/15] LSM: Correctly announce start of LSM initialization 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 Reviewed-by: Casey Schaufler Reviewed-by: James Morris Reviewed-by: John Johansen Signed-off-by: James Morris --- security/security.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/security.c b/security/security.c index 736e78da1ab9..4cbcf244a965 100644 --- a/security/security.c +++ b/security/security.c @@ -72,10 +72,11 @@ int __init security_init(void) int i; struct hlist_head *list = (struct hlist_head *) &security_hook_heads; + pr_info("Security Framework initializing\n"); + for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head); i++) INIT_HLIST_HEAD(&list[i]); - pr_info("Security Framework initialized\n"); /* * Load minor LSMs, with the capability module always first. From 1e80cd1672bc77c96fa72205ba6db78dc10825b4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:18 -0700 Subject: [PATCH 07/15] vmlinux.lds.h: Avoid copy/paste of security_init section Avoid copy/paste by defining SECURITY_INIT in terms of SECURITY_INITCALL. Signed-off-by: Kees Cook Reviewed-by: Casey Schaufler Reviewed-by: James Morris Reviewed-by: John Johansen Signed-off-by: James Morris --- include/asm-generic/vmlinux.lds.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 7b75ff6e2fce..934a45395547 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -473,13 +473,6 @@ #define RODATA RO_DATA_SECTION(4096) #define RO_DATA(align) RO_DATA_SECTION(align) -#define SECURITY_INIT \ - .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ - __security_initcall_start = .; \ - KEEP(*(.security_initcall.init)) \ - __security_initcall_end = .; \ - } - /* * .text section. Map to function alignment to avoid address changes * during second ld run in second ld pass when generating System.map @@ -798,6 +791,12 @@ KEEP(*(.security_initcall.init)) \ __security_initcall_end = .; +/* Older linker script style for security init. */ +#define SECURITY_INIT \ + .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ + SECURITY_INITCALL \ + } + #ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ From b048ae6e6c7062809e4398f4d0bfe80870715d3c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:19 -0700 Subject: [PATCH 08/15] LSM: Rename .security_initcall section to .lsm_info 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 Reviewed-by: Casey Schaufler Reviewed-by: James Morris Reviewed-by: John Johansen Signed-off-by: James Morris --- include/asm-generic/vmlinux.lds.h | 10 +++++----- include/linux/init.h | 4 ++-- security/security.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 934a45395547..5079a969e612 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -787,14 +787,14 @@ __con_initcall_end = .; #define SECURITY_INITCALL \ - __security_initcall_start = .; \ - KEEP(*(.security_initcall.init)) \ - __security_initcall_end = .; + __start_lsm_info = .; \ + KEEP(*(.lsm_info.init)) \ + __end_lsm_info = .; /* Older linker script style for security init. */ #define SECURITY_INIT \ - .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ - SECURITY_INITCALL \ + .lsm_info.init : AT(ADDR(.lsm_info.init) - LOAD_OFFSET) { \ + LSM_INFO \ } #ifdef CONFIG_BLK_DEV_INITRD diff --git a/include/linux/init.h b/include/linux/init.h index 2538d176dd1f..77636539e77c 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -133,7 +133,7 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry) #endif extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; -extern initcall_entry_t __security_initcall_start[], __security_initcall_end[]; +extern initcall_entry_t __start_lsm_info[], __end_lsm_info[]; /* Used for contructor calls. */ typedef void (*ctor_fn_t)(void); @@ -236,7 +236,7 @@ extern bool initcall_debug; static exitcall_t __exitcall_##fn __exit_call = fn #define console_initcall(fn) ___define_initcall(fn,, .con_initcall) -#define security_initcall(fn) ___define_initcall(fn,, .security_initcall) +#define security_initcall(fn) ___define_initcall(fn,, .lsm_info) struct obs_kernel_param { const char *str; diff --git a/security/security.c b/security/security.c index 4cbcf244a965..892fe6b691cf 100644 --- a/security/security.c +++ b/security/security.c @@ -51,9 +51,9 @@ static void __init do_security_initcalls(void) initcall_t call; initcall_entry_t *ce; - ce = __security_initcall_start; + ce = __start_lsm_info; trace_initcall_level("security"); - while (ce < __security_initcall_end) { + while (ce < __end_lsm_info) { call = initcall_from_entry(ce); trace_initcall_start(call); ret = call(); From 6907e3746fa1b9b685230098266bbeba99b93c7d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:20 -0700 Subject: [PATCH 09/15] LSM: Remove initcall tracing This partially reverts commit 58eacfffc417 ("init, tracing: instrument security and console initcall trace events") since security init calls are about to no longer resemble regular init calls. Signed-off-by: Kees Cook Reviewed-by: Casey Schaufler Reviewed-by: James Morris Signed-off-by: James Morris --- security/security.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/security/security.c b/security/security.c index 892fe6b691cf..41a5da2c7faf 100644 --- a/security/security.c +++ b/security/security.c @@ -30,8 +30,6 @@ #include #include -#include - #define MAX_LSM_EVM_XATTR 2 /* Maximum number of letters for an LSM name string */ @@ -47,17 +45,13 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = static void __init do_security_initcalls(void) { - int ret; initcall_t call; initcall_entry_t *ce; ce = __start_lsm_info; - trace_initcall_level("security"); while (ce < __end_lsm_info) { call = initcall_from_entry(ce); - trace_initcall_start(call); - ret = call(); - trace_initcall_finish(call, ret); + call(); ce++; } } From 5b89c1bd4c7e5c5ca8c5374fde35ecee6e16496c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:21 -0700 Subject: [PATCH 10/15] LSM: Convert from initcall to struct lsm_info 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 Reviewed-by: Casey Schaufler Reviewed-by: James Morris Reviewed-by: John Johansen Signed-off-by: James Morris --- 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(-) diff --git a/include/linux/init.h b/include/linux/init.h index 77636539e77c..9c2aba1dbabf 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -133,7 +133,6 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry) #endif extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; -extern initcall_entry_t __start_lsm_info[], __end_lsm_info[]; /* Used for contructor calls. */ typedef void (*ctor_fn_t)(void); @@ -236,7 +235,6 @@ extern bool initcall_debug; static exitcall_t __exitcall_##fn __exit_call = fn #define console_initcall(fn) ___define_initcall(fn,, .con_initcall) -#define security_initcall(fn) ___define_initcall(fn,, .lsm_info) struct obs_kernel_param { const char *str; diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 97a020c616ad..d13059feca09 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2039,6 +2039,18 @@ extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, char *lsm); +struct lsm_info { + int (*init)(void); /* Required. */ +}; + +extern struct lsm_info __start_lsm_info[], __end_lsm_info[]; + +#define security_initcall(lsm) \ + static struct lsm_info __lsm_##lsm \ + __used __section(.lsm_info.init) \ + __aligned(sizeof(unsigned long)) \ + = { .init = lsm, } + #ifdef CONFIG_SECURITY_SELINUX_DISABLE /* * Assuring the safety of deleting a security module is up to diff --git a/include/linux/module.h b/include/linux/module.h index f807f15bebbe..264979283756 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -123,7 +123,6 @@ extern void cleanup_module(void); #define late_initcall_sync(fn) module_init(fn) #define console_initcall(fn) module_init(fn) -#define security_initcall(fn) module_init(fn) /* Each module must use one module_init(). */ #define module_init(initfn) \ diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 5a6810041e5c..70d21b566955 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "integrity.h" static struct rb_root integrity_iint_tree = RB_ROOT; diff --git a/security/security.c b/security/security.c index 41a5da2c7faf..e74f46fba591 100644 --- a/security/security.c +++ b/security/security.c @@ -43,16 +43,12 @@ char *lsm_names; static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; -static void __init do_security_initcalls(void) +static void __init major_lsm_init(void) { - initcall_t call; - initcall_entry_t *ce; + struct lsm_info *lsm; - ce = __start_lsm_info; - while (ce < __end_lsm_info) { - call = initcall_from_entry(ce); - call(); - ce++; + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { + lsm->init(); } } @@ -82,7 +78,7 @@ int __init security_init(void) /* * Load all the remaining security modules. */ - do_security_initcalls(); + major_lsm_init(); return 0; } From 3ac946d12e344a48c1192ef8910c6095a0d6a8ac Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:22 -0700 Subject: [PATCH 11/15] vmlinux.lds.h: Move LSM_TABLE into INIT_DATA 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 Reviewed-by: Casey Schaufler Reviewed-by: John Johansen Reviewed-by: James Morris Signed-off-by: James Morris --- 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(-) diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index f35ed578e007..8fb16bdabdcf 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -71,7 +71,6 @@ SECTIONS INIT_SETUP(L1_CACHE_BYTES) INIT_CALLS CON_INITCALL - SECURITY_INITCALL } .init.arch.info : { diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 3593d5c1acd2..8c74037ade22 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -96,7 +96,6 @@ SECTIONS INIT_SETUP(16) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS } diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 605d1b60469c..7d23d591b03c 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -166,7 +166,6 @@ SECTIONS INIT_SETUP(16) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS *(.init.rodata.* .init.bss) /* from the EFI stub */ } diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index 35716a3048de..49f716c0a1df 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S @@ -56,7 +56,6 @@ SECTIONS __init_begin = .; INIT_TEXT_SECTION(4) INIT_DATA_SECTION(4) - SECURITY_INIT __init_end = .; _edata = . ; _begin_data = LOADADDR(.data); diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 289d0e7f3e3a..e1f3e8741292 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -117,8 +117,6 @@ SECTIONS { CON_INITCALL } - SECURITY_INIT - __init_end_before_initramfs = .; .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 07ae018e550e..105a976323aa 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -212,8 +212,6 @@ SECTIONS CON_INITCALL } - SECURITY_INIT - . = ALIGN(8); __ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) { __start___ftr_fixup = .; diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index 7adb4e6b658a..4049f2c46387 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -53,8 +53,6 @@ CON_INITCALL } - SECURITY_INIT - .exitcall : { __exitcall_begin = .; *(.exitcall.exit) diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index a1c3edb8ad56..b727b18a68ac 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -197,7 +197,6 @@ SECTIONS INIT_SETUP(XCHAL_ICACHE_LINESIZE) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS } diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 5079a969e612..b31ea8bdfef9 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -203,6 +203,15 @@ #define EARLYCON_TABLE() #endif +#ifdef CONFIG_SECURITY +#define LSM_TABLE() . = ALIGN(8); \ + __start_lsm_info = .; \ + KEEP(*(.lsm_info.init)) \ + __end_lsm_info = .; +#else +#define LSM_TABLE() +#endif + #define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name) #define __OF_TABLE(cfg, name) ___OF_TABLE(cfg, name) #define OF_TABLE(cfg, name) __OF_TABLE(IS_ENABLED(cfg), name) @@ -597,7 +606,8 @@ IRQCHIP_OF_MATCH_TABLE() \ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(timer) \ - EARLYCON_TABLE() + EARLYCON_TABLE() \ + LSM_TABLE() #define INIT_TEXT \ *(.init.text .init.text.*) \ @@ -786,17 +796,6 @@ KEEP(*(.con_initcall.init)) \ __con_initcall_end = .; -#define SECURITY_INITCALL \ - __start_lsm_info = .; \ - KEEP(*(.lsm_info.init)) \ - __end_lsm_info = .; - -/* Older linker script style for security init. */ -#define SECURITY_INIT \ - .lsm_info.init : AT(ADDR(.lsm_info.init) - LOAD_OFFSET) { \ - LSM_INFO \ - } - #ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ @@ -963,7 +962,6 @@ INIT_SETUP(initsetup_align) \ INIT_CALLS \ CON_INITCALL \ - SECURITY_INITCALL \ INIT_RAM_FS \ } From 3d6e5f6dcf6561e57b6466e43e14029fb196028d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:23 -0700 Subject: [PATCH 12/15] LSM: Convert security_initcall() into DEFINE_LSM() 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 Reviewed-by: Casey Schaufler Reviewed-by: James Morris Signed-off-by: James Morris --- include/linux/lsm_hooks.h | 5 ++--- 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, 17 insertions(+), 8 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index d13059feca09..9c6b4198ff5a 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2045,11 +2045,10 @@ struct lsm_info { extern struct lsm_info __start_lsm_info[], __end_lsm_info[]; -#define security_initcall(lsm) \ +#define DEFINE_LSM(lsm) \ static struct lsm_info __lsm_##lsm \ __used __section(.lsm_info.init) \ - __aligned(sizeof(unsigned long)) \ - = { .init = lsm, } + __aligned(sizeof(unsigned long)) #ifdef CONFIG_SECURITY_SELINUX_DISABLE /* diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8b8b70620bbe..c4863956c832 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1606,4 +1606,6 @@ static int __init apparmor_init(void) return error; } -security_initcall(apparmor_init); +DEFINE_LSM(apparmor) = { + .init = apparmor_init, +}; diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 70d21b566955..94e8e1820748 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -175,7 +175,9 @@ static int __init integrity_iintcache_init(void) 0, SLAB_PANIC, init_once); return 0; } -security_initcall(integrity_iintcache_init); +DEFINE_LSM(integrity) = { + .init = integrity_iintcache_init, +}; /* diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ad9a9b8e9979..6ca2e89ddbd6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7202,7 +7202,9 @@ void selinux_complete_init(void) /* SELinux requires early initialization in order to label all processes and objects when they are created. */ -security_initcall(selinux_init); +DEFINE_LSM(selinux) = { + .init = selinux_init, +}; #if defined(CONFIG_NETFILTER) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 340fc30ad85d..c62e26939a69 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4882,4 +4882,6 @@ static __init int smack_init(void) * Smack requires early initialization in order to label * all processes and objects when they are created. */ -security_initcall(smack_init); +DEFINE_LSM(smack) = { + .init = smack_init, +}; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 9f932e2d6852..b2d833999910 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -550,4 +550,6 @@ static int __init tomoyo_init(void) return 0; } -security_initcall(tomoyo_init); +DEFINE_LSM(tomoyo) = { + .init = tomoyo_init, +}; From 07aed2f2af5a5892ced035dbcf3993f630825fc3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:24 -0700 Subject: [PATCH 13/15] LSM: Record LSM name in struct lsm_info In preparation for making LSM selections outside of the LSMs, include the name of LSMs in struct lsm_info. Signed-off-by: Kees Cook Reviewed-by: Casey Schaufler Signed-off-by: James Morris --- include/linux/lsm_hooks.h | 1 + security/apparmor/lsm.c | 1 + security/integrity/iint.c | 1 + security/selinux/hooks.c | 1 + security/smack/smack_lsm.c | 1 + security/tomoyo/tomoyo.c | 1 + 6 files changed, 6 insertions(+) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9c6b4198ff5a..ae159b02f3ab 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2040,6 +2040,7 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count, char *lsm); struct lsm_info { + const char *name; /* Required. */ int (*init)(void); /* Required. */ }; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index c4863956c832..dca4b7dbf368 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1607,5 +1607,6 @@ static int __init apparmor_init(void) } DEFINE_LSM(apparmor) = { + .name = "apparmor", .init = apparmor_init, }; diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 94e8e1820748..1ea05da2323d 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -176,6 +176,7 @@ static int __init integrity_iintcache_init(void) return 0; } DEFINE_LSM(integrity) = { + .name = "integrity", .init = integrity_iintcache_init, }; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6ca2e89ddbd6..9651bccae270 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7203,6 +7203,7 @@ void selinux_complete_init(void) /* SELinux requires early initialization in order to label all processes and objects when they are created. */ DEFINE_LSM(selinux) = { + .name = "selinux", .init = selinux_init, }; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c62e26939a69..2fb56bcf1316 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4883,5 +4883,6 @@ static __init int smack_init(void) * all processes and objects when they are created. */ DEFINE_LSM(smack) = { + .name = "smack", .init = smack_init, }; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index b2d833999910..1b5b5097efd7 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -551,5 +551,6 @@ static int __init tomoyo_init(void) } DEFINE_LSM(tomoyo) = { + .name = "tomoyo", .init = tomoyo_init, }; From 9b8c7c14059af801637a818882159145c370d6f1 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:25 -0700 Subject: [PATCH 14/15] LSM: Provide init debugging infrastructure Booting with "lsm.debug" will report future details on how LSM ordering decisions are being made. Signed-off-by: Kees Cook Reviewed-by: Casey Schaufler Reviewed-by: John Johansen Reviewed-by: James Morris Signed-off-by: James Morris --- .../admin-guide/kernel-parameters.txt | 2 ++ security/security.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 9871e649ffef..32d323ee9218 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2274,6 +2274,8 @@ ltpc= [NET] Format: ,, + 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 diff --git a/security/security.c b/security/security.c index e74f46fba591..395f804f6a91 100644 --- a/security/security.c +++ b/security/security.c @@ -12,6 +12,8 @@ * (at your option) any later version. */ +#define pr_fmt(fmt) "LSM: " fmt + #include #include #include @@ -43,11 +45,19 @@ char *lsm_names; static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; +static __initdata bool debug; +#define init_debug(...) \ + do { \ + if (debug) \ + pr_info(__VA_ARGS__); \ + } while (0) + static void __init major_lsm_init(void) { struct lsm_info *lsm; for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { + init_debug("initializing %s\n", lsm->name); lsm->init(); } } @@ -91,6 +101,14 @@ static int __init choose_lsm(char *str) } __setup("security=", choose_lsm); +/* Enable LSM order debugging. */ +static int __init enable_debug(char *str) +{ + debug = true; + return 1; +} +__setup("lsm.debug", enable_debug); + static bool match_last_lsm(const char *list, const char *lsm) { const char *last; From 3f6caaf5ff33073ca1a3a0b82edacab3c57c38f9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Oct 2018 17:18:26 -0700 Subject: [PATCH 15/15] LSM: Don't ignore initialization failures LSM initialization failures have traditionally been ignored. We should at least WARN when something goes wrong. Signed-off-by: Kees Cook Reviewed-by: Casey Schaufler Reviewed-by: John Johansen Signed-off-by: James Morris --- security/security.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/security/security.c b/security/security.c index 395f804f6a91..2055af907eba 100644 --- a/security/security.c +++ b/security/security.c @@ -55,10 +55,12 @@ static __initdata bool debug; static void __init major_lsm_init(void) { struct lsm_info *lsm; + int ret; for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { init_debug("initializing %s\n", lsm->name); - lsm->init(); + ret = lsm->init(); + WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); } }