From 4b57d6bcd94034e2eb168bdec2474e3b2b848e44 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 28 Mar 2016 15:16:53 -0400 Subject: selinux: simply inode label states to INVALID and INITIALIZED There really is no need for LABEL_MISSING as we really only care if the inode's label is INVALID or INITIALIZED. Also adjust the revalidate code to reload the label whenever the label is not INITIALIZED so we are less sensitive to label state in the future. Signed-off-by: Paul Moore --- security/selinux/include/objsec.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'security/selinux/include') diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index a2ae05414ba1..c21e135460a5 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -38,9 +38,8 @@ struct task_security_struct { }; enum label_initialized { - LABEL_MISSING, /* not initialized */ - LABEL_INITIALIZED, /* inizialized */ - LABEL_INVALID /* invalid */ + LABEL_INVALID, /* invalid or not initialized */ + LABEL_INITIALIZED /* initialized */ }; struct inode_security_struct { -- cgit v1.2.3 From 61d612ea731e57dc510472fb746b55cdc017f371 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Tue, 5 Apr 2016 13:06:27 -0700 Subject: selinux: restrict kernel module loading Utilize existing kernel_read_file hook on kernel module load. Add module_load permission to the system class. Enforces restrictions on kernel module origin when calling the finit_module syscall. The hook checks that source type has permission module_load for the target type. Example for finit_module: allow foo bar_file:system module_load; Similarly restrictions are enforced on kernel module loading when calling the init_module syscall. The hook checks that source type has permission module_load with itself as the target object because the kernel module is sourced from the calling process. Example for init_module: allow foo foo:system module_load; Signed-off-by: Jeff Vander Stoep [PM: fixed return value of selinux_kernel_read_file()] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 47 +++++++++++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'security/selinux/include') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5003b5aa3b43..fce7dc81f2d9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3722,6 +3722,52 @@ static int selinux_kernel_module_request(char *kmod_name) SYSTEM__MODULE_REQUEST, &ad); } +static int selinux_kernel_module_from_file(struct file *file) +{ + struct common_audit_data ad; + struct inode_security_struct *isec; + struct file_security_struct *fsec; + u32 sid = current_sid(); + int rc; + + /* init_module */ + if (file == NULL) + return avc_has_perm(sid, sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, NULL); + + /* finit_module */ + ad.type = LSM_AUDIT_DATA_PATH; + ad.u.path = file->f_path; + + isec = inode_security(file_inode(file)); + fsec = file->f_security; + + if (sid != fsec->sid) { + rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); + if (rc) + return rc; + } + + return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, &ad); +} + +static int selinux_kernel_read_file(struct file *file, + enum kernel_read_file_id id) +{ + int rc = 0; + + switch (id) { + case READING_MODULE: + rc = selinux_kernel_module_from_file(file); + break; + default: + break; + } + + return rc; +} + static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { return current_has_perm(p, PROCESS__SETPGID); @@ -6018,6 +6064,7 @@ static struct security_hook_list selinux_hooks[] = { LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), + LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file), LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), LSM_HOOK_INIT(task_getsid, selinux_task_getsid), diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index ef83c4b85a33..8fbd1383d75e 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -32,7 +32,7 @@ struct security_class_mapping secclass_map[] = { "setsockcreate", NULL } }, { "system", { "ipc_info", "syslog_read", "syslog_mod", - "syslog_console", "module_request", NULL } }, + "syslog_console", "module_request", "module_load", NULL } }, { "capability", { "chown", "dac_override", "dac_read_search", "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", -- cgit v1.2.3 From 0fd71a620be8648486a126fccadf9f7c2a818676 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 14 Apr 2016 10:40:57 -0400 Subject: selinux: Change bool variable name to index. security_get_bool_value(int bool) argument "bool" conflicts with in-kernel macros such as BUILD_BUG(). This patch changes this to index which isn't a type. Cc: Paul Moore Cc: Stephen Smalley Cc: Eric Paris Cc: James Morris Cc: "Serge E. Hallyn" Cc: Rasmus Villemoes Cc: Andrew Perepechko Cc: Jeff Vander Stoep Cc: selinux@tycho.nsa.gov Cc: Eric Paris Cc: Paul Moore Cc: David Howells Signed-off-by: Prarit Bhargava Acked-by: David Howells [PM: wrapped description for checkpatch.pl, use "selinux:..." as subj] Signed-off-by: Paul Moore --- security/selinux/include/conditional.h | 2 +- security/selinux/ss/services.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'security/selinux/include') diff --git a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h index 67ce7a8d8301..ff4fddca9050 100644 --- a/security/selinux/include/conditional.h +++ b/security/selinux/include/conditional.h @@ -17,6 +17,6 @@ int security_get_bools(int *len, char ***names, int **values); int security_set_bools(int len, int *values); -int security_get_bool_value(int bool); +int security_get_bool_value(int index); #endif diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ebda97333f1b..89df64672b89 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2696,7 +2696,7 @@ out: return rc; } -int security_get_bool_value(int bool) +int security_get_bool_value(int index) { int rc; int len; @@ -2705,10 +2705,10 @@ int security_get_bool_value(int bool) rc = -EFAULT; len = policydb.p_bools.nprim; - if (bool >= len) + if (index >= len) goto out; - rc = policydb.bool_val_to_struct[bool]->state; + rc = policydb.bool_val_to_struct[index]->state; out: read_unlock(&policy_rwlock); return rc; -- cgit v1.2.3 From 8e4ff6f228e4722cac74db716e308d1da33d744f Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 8 Apr 2016 13:52:00 -0400 Subject: selinux: distinguish non-init user namespace capability checks Distinguish capability checks against a target associated with the init user namespace versus capability checks against a target associated with a non-init user namespace by defining and using separate security classes for the latter. This is needed to support e.g. Chrome usage of user namespaces for the Chrome sandbox without needing to allow Chrome to also exercise capabilities on targets in the init user namespace. Suggested-by: Dan Walsh Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 14 +++++++------- security/selinux/include/classmap.h | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) (limited to 'security/selinux/include') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 474011c46bbd..bbff80c6d3f2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1631,7 +1631,7 @@ static int current_has_perm(const struct task_struct *tsk, /* Check whether a task is allowed to use a capability. */ static int cred_has_capability(const struct cred *cred, - int cap, int audit) + int cap, int audit, bool initns) { struct common_audit_data ad; struct av_decision avd; @@ -1645,10 +1645,10 @@ static int cred_has_capability(const struct cred *cred, switch (CAP_TO_INDEX(cap)) { case 0: - sclass = SECCLASS_CAPABILITY; + sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS; break; case 1: - sclass = SECCLASS_CAPABILITY2; + sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS; break; default: printk(KERN_ERR @@ -2152,7 +2152,7 @@ static int selinux_capset(struct cred *new, const struct cred *old, static int selinux_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { - return cred_has_capability(cred, cap, audit); + return cred_has_capability(cred, cap, audit, ns == &init_user_ns); } static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) @@ -2230,7 +2230,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) int rc, cap_sys_admin = 0; rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, - SECURITY_CAP_NOAUDIT); + SECURITY_CAP_NOAUDIT, true); if (rc == 0) cap_sys_admin = 1; @@ -3213,7 +3213,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void SECURITY_CAP_NOAUDIT); if (!error) error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, - SECURITY_CAP_NOAUDIT); + SECURITY_CAP_NOAUDIT, true); isec = inode_security(inode); if (!error) error = security_sid_to_context_force(isec->sid, &context, @@ -3390,7 +3390,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, case KDSKBENT: case KDSKBSENT: error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, - SECURITY_CAP_AUDIT); + SECURITY_CAP_AUDIT, true); break; /* default case assumes that the command will go diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 8fbd1383d75e..1f1f4b2f6018 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -12,6 +12,18 @@ #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ "write", "associate", "unix_read", "unix_write" +#define COMMON_CAP_PERMS "chown", "dac_override", "dac_read_search", \ + "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", \ + "linux_immutable", "net_bind_service", "net_broadcast", \ + "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", \ + "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", \ + "sys_boot", "sys_nice", "sys_resource", "sys_time", \ + "sys_tty_config", "mknod", "lease", "audit_write", \ + "audit_control", "setfcap" + +#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \ + "wake_alarm", "block_suspend", "audit_read" + /* * Note: The name for any socket class should be suffixed by "socket", * and doesn't contain more than one substr of "socket". @@ -34,14 +46,7 @@ struct security_class_mapping secclass_map[] = { { "ipc_info", "syslog_read", "syslog_mod", "syslog_console", "module_request", "module_load", NULL } }, { "capability", - { "chown", "dac_override", "dac_read_search", - "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", - "linux_immutable", "net_bind_service", "net_broadcast", - "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", - "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", - "sys_boot", "sys_nice", "sys_resource", "sys_time", - "sys_tty_config", "mknod", "lease", "audit_write", - "audit_control", "setfcap", NULL } }, + { COMMON_CAP_PERMS, NULL } }, { "filesystem", { "mount", "remount", "unmount", "getattr", "relabelfrom", "relabelto", "associate", "quotamod", @@ -150,12 +155,15 @@ struct security_class_mapping secclass_map[] = { { "memprotect", { "mmap_zero", NULL } }, { "peer", { "recv", NULL } }, { "capability2", - { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", - "audit_read", NULL } }, + { COMMON_CAP2_PERMS, NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", { COMMON_SOCK_PERMS, "attach_queue", NULL } }, { "binder", { "impersonate", "call", "set_context_mgr", "transfer", NULL } }, + { "cap_userns", + { COMMON_CAP_PERMS, NULL } }, + { "cap2_userns", + { COMMON_CAP2_PERMS, NULL } }, { NULL } }; -- cgit v1.2.3