whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit 638820d8da8ededd6dc609beaef02d5396599c03
parent d5e4d81da4d443d54b0b5c28ba6d26be297c509b
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Wed, 24 Oct 2018 11:49:35 +0100

Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:
 "In this patchset, there are a couple of minor updates, as well as some
  reworking of the LSM initialization code from Kees Cook (these prepare
  the way for ordered stackable LSMs, but are a valuable cleanup on
  their own)"

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  LSM: Don't ignore initialization failures
  LSM: Provide init debugging infrastructure
  LSM: Record LSM name in struct lsm_info
  LSM: Convert security_initcall() into DEFINE_LSM()
  vmlinux.lds.h: Move LSM_TABLE into INIT_DATA
  LSM: Convert from initcall to struct lsm_info
  LSM: Remove initcall tracing
  LSM: Rename .security_initcall section to .lsm_info
  vmlinux.lds.h: Avoid copy/paste of security_init section
  LSM: Correctly announce start of LSM initialization
  security: fix LSM description location
  keys: Fix the use of the C++ keyword "private" in uapi/linux/keyctl.h
  seccomp: remove unnecessary unlikely()
  security: tomoyo: Fix obsolete function
  security/capabilities: remove check for -EINVAL

Diffstat:
MDocumentation/admin-guide/kernel-parameters.txt | 2++
MDocumentation/security/LSM.rst | 2+-
March/arc/kernel/vmlinux.lds.S | 1-
March/arm/kernel/vmlinux-xip.lds.S | 1-
March/arm64/kernel/vmlinux.lds.S | 1-
March/h8300/kernel/vmlinux.lds.S | 1-
March/microblaze/kernel/vmlinux.lds.S | 2--
March/powerpc/kernel/vmlinux.lds.S | 2--
March/um/include/asm/common.lds.S | 2--
March/xtensa/kernel/vmlinux.lds.S | 1-
Minclude/asm-generic/vmlinux.lds.h | 25+++++++++++--------------
Minclude/linux/init.h | 2--
Minclude/linux/lsm_hooks.h | 12++++++++++++
Minclude/linux/module.h | 1-
Minclude/uapi/linux/keyctl.h | 7++++++-
Mkernel/seccomp.c | 4++--
Msecurity/apparmor/lsm.c | 5++++-
Msecurity/commoncap.c | 3---
Msecurity/integrity/iint.c | 6+++++-
Msecurity/security.c | 43+++++++++++++++++++++++++++----------------
Msecurity/selinux/hooks.c | 5++++-
Msecurity/smack/smack_lsm.c | 5++++-
Msecurity/tomoyo/common.c | 3++-
Msecurity/tomoyo/tomoyo.c | 5++++-
24 files changed, 84 insertions(+), 57 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt @@ -2284,6 +2284,8 @@ ltpc= [NET] Format: <io>,<irq>,<dma> + 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/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. diff --git 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 @@ -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 @@ -183,7 +183,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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -476,13 +485,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 @@ -607,7 +609,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.*) \ @@ -796,11 +799,6 @@ KEEP(*(.con_initcall.init)) \ __con_initcall_end = .; -#define SECURITY_INITCALL \ - __security_initcall_start = .; \ - KEEP(*(.security_initcall.init)) \ - __security_initcall_end = .; - #ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ @@ -967,7 +965,6 @@ INIT_SETUP(initsetup_align) \ INIT_CALLS \ CON_INITCALL \ - SECURITY_INITCALL \ INIT_RAM_FS \ } diff --git 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 __security_initcall_start[], __security_initcall_end[]; /* 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,, .security_initcall) struct obs_kernel_param { const char *str; diff --git 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 { + const char *name; /* Required. */ + int (*init)(void); /* Required. */ +}; + +extern struct lsm_info __start_lsm_info[], __end_lsm_info[]; + +#define DEFINE_LSM(lsm) \ + static struct lsm_info __lsm_##lsm \ + __used __section(.lsm_info.init) \ + __aligned(sizeof(unsigned long)) + #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 @@ -124,7 +124,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/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; }; diff --git 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; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c @@ -1606,4 +1606,7 @@ alloc_out: return error; } -security_initcall(apparmor_init); +DEFINE_LSM(apparmor) = { + .name = "apparmor", + .init = apparmor_init, +}; diff --git 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) diff --git a/security/integrity/iint.c b/security/integrity/iint.c @@ -22,6 +22,7 @@ #include <linux/file.h> #include <linux/uaccess.h> #include <linux/security.h> +#include <linux/lsm_hooks.h> #include "integrity.h" static struct rb_root integrity_iint_tree = RB_ROOT; @@ -174,7 +175,10 @@ static int __init integrity_iintcache_init(void) 0, SLAB_PANIC, init_once); return 0; } -security_initcall(integrity_iintcache_init); +DEFINE_LSM(integrity) = { + .name = "integrity", + .init = integrity_iintcache_init, +}; /* diff --git 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 <linux/bpf.h> #include <linux/capability.h> #include <linux/dcache.h> @@ -30,8 +32,6 @@ #include <linux/string.h> #include <net/flow.h> -#include <trace/events/initcall.h> - #define MAX_LSM_EVM_XATTR 2 /* Maximum number of letters for an LSM name string */ @@ -45,20 +45,22 @@ char *lsm_names; static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; -static void __init do_security_initcalls(void) +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; int ret; - initcall_t call; - initcall_entry_t *ce; - - ce = __security_initcall_start; - trace_initcall_level("security"); - while (ce < __security_initcall_end) { - call = initcall_from_entry(ce); - trace_initcall_start(call); - ret = call(); - trace_initcall_finish(call, ret); - ce++; + + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { + init_debug("initializing %s\n", lsm->name); + ret = lsm->init(); + WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); } } @@ -72,10 +74,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. @@ -87,7 +90,7 @@ int __init security_init(void) /* * Load all the remaining security modules. */ - do_security_initcalls(); + major_lsm_init(); return 0; } @@ -100,6 +103,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; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c @@ -7207,7 +7207,10 @@ 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) = { + .name = "selinux", + .init = selinux_init, +}; #if defined(CONFIG_NETFILTER) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c @@ -4882,4 +4882,7 @@ 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) = { + .name = "smack", + .init = smack_init, +}; diff --git 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); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c @@ -550,4 +550,7 @@ static int __init tomoyo_init(void) return 0; } -security_initcall(tomoyo_init); +DEFINE_LSM(tomoyo) = { + .name = "tomoyo", + .init = tomoyo_init, +};