Commit 638820d8 authored by Linus Torvalds's avatar Linus Torvalds

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
parents d5e4d81d 3f6caaf5
...@@ -2284,6 +2284,8 @@ ...@@ -2284,6 +2284,8 @@
ltpc= [NET] ltpc= [NET]
Format: <io>,<irq>,<dma> Format: <io>,<irq>,<dma>
lsm.debug [SECURITY] Enable LSM initialization debugging output.
machvec= [IA-64] Force the use of a particular machine-vector machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel. (machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb Example: machvec=hpzx1_swiotlb
......
...@@ -5,7 +5,7 @@ Linux Security Module Development ...@@ -5,7 +5,7 @@ Linux Security Module Development
Based on https://lkml.org/lkml/2007/10/26/215, Based on https://lkml.org/lkml/2007/10/26/215,
a new LSM is accepted into the kernel when its intent (a description of 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 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 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 that end users and distros can make a more informed decision about which
LSMs suit their requirements. LSMs suit their requirements.
......
...@@ -71,7 +71,6 @@ SECTIONS ...@@ -71,7 +71,6 @@ SECTIONS
INIT_SETUP(L1_CACHE_BYTES) INIT_SETUP(L1_CACHE_BYTES)
INIT_CALLS INIT_CALLS
CON_INITCALL CON_INITCALL
SECURITY_INITCALL
} }
.init.arch.info : { .init.arch.info : {
......
...@@ -96,7 +96,6 @@ SECTIONS ...@@ -96,7 +96,6 @@ SECTIONS
INIT_SETUP(16) INIT_SETUP(16)
INIT_CALLS INIT_CALLS
CON_INITCALL CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS INIT_RAM_FS
} }
......
...@@ -183,7 +183,6 @@ SECTIONS ...@@ -183,7 +183,6 @@ SECTIONS
INIT_SETUP(16) INIT_SETUP(16)
INIT_CALLS INIT_CALLS
CON_INITCALL CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS INIT_RAM_FS
*(.init.rodata.* .init.bss) /* from the EFI stub */ *(.init.rodata.* .init.bss) /* from the EFI stub */
} }
......
...@@ -56,7 +56,6 @@ SECTIONS ...@@ -56,7 +56,6 @@ SECTIONS
__init_begin = .; __init_begin = .;
INIT_TEXT_SECTION(4) INIT_TEXT_SECTION(4)
INIT_DATA_SECTION(4) INIT_DATA_SECTION(4)
SECURITY_INIT
__init_end = .; __init_end = .;
_edata = . ; _edata = . ;
_begin_data = LOADADDR(.data); _begin_data = LOADADDR(.data);
......
...@@ -117,8 +117,6 @@ SECTIONS { ...@@ -117,8 +117,6 @@ SECTIONS {
CON_INITCALL CON_INITCALL
} }
SECURITY_INIT
__init_end_before_initramfs = .; __init_end_before_initramfs = .;
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
......
...@@ -212,8 +212,6 @@ SECTIONS ...@@ -212,8 +212,6 @@ SECTIONS
CON_INITCALL CON_INITCALL
} }
SECURITY_INIT
. = ALIGN(8); . = ALIGN(8);
__ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) { __ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
__start___ftr_fixup = .; __start___ftr_fixup = .;
......
...@@ -53,8 +53,6 @@ ...@@ -53,8 +53,6 @@
CON_INITCALL CON_INITCALL
} }
SECURITY_INIT
.exitcall : { .exitcall : {
__exitcall_begin = .; __exitcall_begin = .;
*(.exitcall.exit) *(.exitcall.exit)
......
...@@ -197,7 +197,6 @@ SECTIONS ...@@ -197,7 +197,6 @@ SECTIONS
INIT_SETUP(XCHAL_ICACHE_LINESIZE) INIT_SETUP(XCHAL_ICACHE_LINESIZE)
INIT_CALLS INIT_CALLS
CON_INITCALL CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS INIT_RAM_FS
} }
......
...@@ -203,6 +203,15 @@ ...@@ -203,6 +203,15 @@
#define EARLYCON_TABLE() #define EARLYCON_TABLE()
#endif #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(cfg, name) #define __OF_TABLE(cfg, name) ___OF_TABLE(cfg, name)
#define OF_TABLE(cfg, name) __OF_TABLE(IS_ENABLED(cfg), name) #define OF_TABLE(cfg, name) __OF_TABLE(IS_ENABLED(cfg), name)
...@@ -476,13 +485,6 @@ ...@@ -476,13 +485,6 @@
#define RODATA RO_DATA_SECTION(4096) #define RODATA RO_DATA_SECTION(4096)
#define RO_DATA(align) RO_DATA_SECTION(align) #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 * .text section. Map to function alignment to avoid address changes
* during second ld run in second ld pass when generating System.map * during second ld run in second ld pass when generating System.map
...@@ -607,7 +609,8 @@ ...@@ -607,7 +609,8 @@
IRQCHIP_OF_MATCH_TABLE() \ IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(timer) \ ACPI_PROBE_TABLE(timer) \
EARLYCON_TABLE() EARLYCON_TABLE() \
LSM_TABLE()
#define INIT_TEXT \ #define INIT_TEXT \
*(.init.text .init.text.*) \ *(.init.text .init.text.*) \
...@@ -796,11 +799,6 @@ ...@@ -796,11 +799,6 @@
KEEP(*(.con_initcall.init)) \ KEEP(*(.con_initcall.init)) \
__con_initcall_end = .; __con_initcall_end = .;
#define SECURITY_INITCALL \
__security_initcall_start = .; \
KEEP(*(.security_initcall.init)) \
__security_initcall_end = .;
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \ #define INIT_RAM_FS \
. = ALIGN(4); \ . = ALIGN(4); \
...@@ -967,7 +965,6 @@ ...@@ -967,7 +965,6 @@
INIT_SETUP(initsetup_align) \ INIT_SETUP(initsetup_align) \
INIT_CALLS \ INIT_CALLS \
CON_INITCALL \ CON_INITCALL \
SECURITY_INITCALL \
INIT_RAM_FS \ INIT_RAM_FS \
} }
......
...@@ -133,7 +133,6 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry) ...@@ -133,7 +133,6 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
#endif #endif
extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
extern initcall_entry_t __security_initcall_start[], __security_initcall_end[];
/* Used for contructor calls. */ /* Used for contructor calls. */
typedef void (*ctor_fn_t)(void); typedef void (*ctor_fn_t)(void);
...@@ -236,7 +235,6 @@ extern bool initcall_debug; ...@@ -236,7 +235,6 @@ extern bool initcall_debug;
static exitcall_t __exitcall_##fn __exit_call = fn static exitcall_t __exitcall_##fn __exit_call = fn
#define console_initcall(fn) ___define_initcall(fn,, .con_initcall) #define console_initcall(fn) ___define_initcall(fn,, .con_initcall)
#define security_initcall(fn) ___define_initcall(fn,, .security_initcall)
struct obs_kernel_param { struct obs_kernel_param {
const char *str; const char *str;
......
...@@ -2039,6 +2039,18 @@ extern char *lsm_names; ...@@ -2039,6 +2039,18 @@ extern char *lsm_names;
extern void security_add_hooks(struct security_hook_list *hooks, int count, extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm); 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 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
/* /*
* Assuring the safety of deleting a security module is up to * Assuring the safety of deleting a security module is up to
......
...@@ -124,7 +124,6 @@ extern void cleanup_module(void); ...@@ -124,7 +124,6 @@ extern void cleanup_module(void);
#define late_initcall_sync(fn) module_init(fn) #define late_initcall_sync(fn) module_init(fn)
#define console_initcall(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(). */ /* Each module must use one module_init(). */
#define module_init(initfn) \ #define module_init(initfn) \
......
...@@ -65,7 +65,12 @@ ...@@ -65,7 +65,12 @@
/* keyctl structures */ /* keyctl structures */
struct keyctl_dh_params { struct keyctl_dh_params {
__s32 private; union {
#ifndef __cplusplus
__s32 private;
#endif
__s32 priv;
};
__s32 prime; __s32 prime;
__s32 base; __s32 base;
}; };
......
...@@ -195,7 +195,7 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd, ...@@ -195,7 +195,7 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd,
READ_ONCE(current->seccomp.filter); READ_ONCE(current->seccomp.filter);
/* Ensure unexpected behavior doesn't result in failing open. */ /* 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; return SECCOMP_RET_KILL_PROCESS;
if (!sd) { if (!sd) {
...@@ -297,7 +297,7 @@ static inline pid_t seccomp_can_sync_threads(void) ...@@ -297,7 +297,7 @@ static inline pid_t seccomp_can_sync_threads(void)
/* Return the first thread that cannot be synchronized. */ /* Return the first thread that cannot be synchronized. */
failed = task_pid_vnr(thread); failed = task_pid_vnr(thread);
/* If the pid cannot be resolved, then return -ESRCH */ /* If the pid cannot be resolved, then return -ESRCH */
if (unlikely(WARN_ON(failed == 0))) if (WARN_ON(failed == 0))
failed = -ESRCH; failed = -ESRCH;
return failed; return failed;
} }
......
...@@ -1606,4 +1606,7 @@ static int __init apparmor_init(void) ...@@ -1606,4 +1606,7 @@ static int __init apparmor_init(void)
return error; return error;
} }
security_initcall(apparmor_init); DEFINE_LSM(apparmor) = {
.name = "apparmor",
.init = apparmor_init,
};
...@@ -684,9 +684,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_f ...@@ -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); 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: out:
if (rc) if (rc)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/lsm_hooks.h>
#include "integrity.h" #include "integrity.h"
static struct rb_root integrity_iint_tree = RB_ROOT; static struct rb_root integrity_iint_tree = RB_ROOT;
...@@ -174,7 +175,10 @@ static int __init integrity_iintcache_init(void) ...@@ -174,7 +175,10 @@ static int __init integrity_iintcache_init(void)
0, SLAB_PANIC, init_once); 0, SLAB_PANIC, init_once);
return 0; return 0;
} }
security_initcall(integrity_iintcache_init); DEFINE_LSM(integrity) = {
.name = "integrity",
.init = integrity_iintcache_init,
};
/* /*
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
* (at your option) any later version. * (at your option) any later version.
*/ */
#define pr_fmt(fmt) "LSM: " fmt
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/dcache.h> #include <linux/dcache.h>
...@@ -30,8 +32,6 @@ ...@@ -30,8 +32,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <net/flow.h> #include <net/flow.h>
#include <trace/events/initcall.h>
#define MAX_LSM_EVM_XATTR 2 #define MAX_LSM_EVM_XATTR 2
/* Maximum number of letters for an LSM name string */ /* Maximum number of letters for an LSM name string */
...@@ -45,20 +45,22 @@ char *lsm_names; ...@@ -45,20 +45,22 @@ char *lsm_names;
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY; 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; int ret;
initcall_t call;
initcall_entry_t *ce; for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
init_debug("initializing %s\n", lsm->name);
ce = __security_initcall_start; ret = lsm->init();
trace_initcall_level("security"); WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
while (ce < __security_initcall_end) {
call = initcall_from_entry(ce);
trace_initcall_start(call);
ret = call();
trace_initcall_finish(call, ret);
ce++;
} }
} }
...@@ -72,10 +74,11 @@ int __init security_init(void) ...@@ -72,10 +74,11 @@ int __init security_init(void)
int i; int i;
struct hlist_head *list = (struct hlist_head *) &security_hook_heads; 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); for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
i++) i++)
INIT_HLIST_HEAD(&list[i]); INIT_HLIST_HEAD(&list[i]);
pr_info("Security Framework initialized\n");
/* /*
* Load minor LSMs, with the capability module always first. * Load minor LSMs, with the capability module always first.
...@@ -87,7 +90,7 @@ int __init security_init(void) ...@@ -87,7 +90,7 @@ int __init security_init(void)
/* /*
* Load all the remaining security modules. * Load all the remaining security modules.
*/ */
do_security_initcalls(); major_lsm_init();
return 0; return 0;
} }
...@@ -100,6 +103,14 @@ static int __init choose_lsm(char *str) ...@@ -100,6 +103,14 @@ static int __init choose_lsm(char *str)
} }
__setup("security=", choose_lsm); __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) static bool match_last_lsm(const char *list, const char *lsm)
{ {
const char *last; const char *last;
......
...@@ -7207,7 +7207,10 @@ void selinux_complete_init(void) ...@@ -7207,7 +7207,10 @@ void selinux_complete_init(void)
/* SELinux requires early initialization in order to label /* SELinux requires early initialization in order to label
all processes and objects when they are created. */ all processes and objects when they are created. */
security_initcall(selinux_init); DEFINE_LSM(selinux) = {
.name = "selinux",
.init = selinux_init,
};
#if defined(CONFIG_NETFILTER) #if defined(CONFIG_NETFILTER)
......
...@@ -4882,4 +4882,7 @@ static __init int smack_init(void) ...@@ -4882,4 +4882,7 @@ static __init int smack_init(void)
* Smack requires early initialization in order to label * Smack requires early initialization in order to label
* all processes and objects when they are created. * all processes and objects when they are created.
*/ */
security_initcall(smack_init); DEFINE_LSM(smack) = {
.name = "smack",
.init = smack_init,
};
...@@ -1660,7 +1660,8 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) ...@@ -1660,7 +1660,8 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
head->r.eof = true; head->r.eof = true;
if (tomoyo_str_starts(&buf, "global-pid ")) if (tomoyo_str_starts(&buf, "global-pid "))
global_pid = true; global_pid = true;
pid = (unsigned int) simple_strtoul(buf, NULL, 10); if (kstrtouint(buf, 10, &pid))
return;
rcu_read_lock(); rcu_read_lock();
if (global_pid) if (global_pid)
p = find_task_by_pid_ns(pid, &init_pid_ns); p = find_task_by_pid_ns(pid, &init_pid_ns);
......
...@@ -550,4 +550,7 @@ static int __init tomoyo_init(void) ...@@ -550,4 +550,7 @@ static int __init tomoyo_init(void)
return 0; return 0;
} }
security_initcall(tomoyo_init); DEFINE_LSM(tomoyo) = {
.name = "tomoyo",
.init = tomoyo_init,
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment