diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig | 35 | ||||
-rw-r--r-- | security/apparmor/domain.c | 2 | ||||
-rw-r--r-- | security/apparmor/policy.c | 2 | ||||
-rw-r--r-- | security/commoncap.c | 5 | ||||
-rw-r--r-- | security/integrity/evm/evm_main.c | 2 | ||||
-rw-r--r-- | security/keys/dh.c | 2 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 4 | ||||
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 | ||||
-rw-r--r-- | security/keys/persistent.c | 2 | ||||
-rw-r--r-- | security/keys/process_keys.c | 1 | ||||
-rw-r--r-- | security/keys/request_key.c | 7 | ||||
-rw-r--r-- | security/keys/trusted.c | 4 | ||||
-rw-r--r-- | security/keys/user_defined.c | 6 | ||||
-rw-r--r-- | security/selinux/hooks.c | 20 | ||||
-rw-r--r-- | security/selinux/include/classmap.h | 4 | ||||
-rw-r--r-- | security/selinux/include/security.h | 2 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 4 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 2 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 2 | ||||
-rw-r--r-- | security/tomoyo/group.c | 2 | ||||
-rw-r--r-- | security/tomoyo/util.c | 2 |
25 files changed, 95 insertions, 30 deletions
diff --git a/security/Kconfig b/security/Kconfig index 118f4549404e..d900f47eaa68 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -158,6 +158,41 @@ config HARDENED_USERCOPY_PAGESPAN been removed. This config is intended to be used only while trying to find such users. +config STATIC_USERMODEHELPER + bool "Force all usermode helper calls through a single binary" + help + By default, the kernel can call many different userspace + binary programs through the "usermode helper" kernel + interface. Some of these binaries are statically defined + either in the kernel code itself, or as a kernel configuration + option. However, some of these are dynamically created at + runtime, or can be modified after the kernel has started up. + To provide an additional layer of security, route all of these + calls through a single executable that can not have its name + changed. + + Note, it is up to this single binary to then call the relevant + "real" usermode helper binary, based on the first argument + passed to it. If desired, this program can filter and pick + and choose what real programs are called. + + If you wish for all usermode helper programs are to be + disabled, choose this option and then set + STATIC_USERMODEHELPER_PATH to an empty string. + +config STATIC_USERMODEHELPER_PATH + string "Path to the static usermode helper binary" + depends on STATIC_USERMODEHELPER + default "/sbin/usermode-helper" + help + The binary called by the kernel when any usermode helper + program is wish to be run. The "real" application's name will + be in the first argument passed to this program on the command + line. + + If you wish for all usermode helper programs to be disabled, + specify an empty string here (i.e. ""). + source security/selinux/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index ef4beef06e9d..001e133a3c8c 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -471,7 +471,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) ; } - if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { + if (bprm->unsafe & LSM_UNSAFE_PTRACE) { error = may_change_ptraced_domain(new_profile); if (error) goto audit; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index f44312a19522..def1fbd6bdfd 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -76,6 +76,8 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string.h> +#include <linux/cred.h> +#include <linux/rculist.h> #include <linux/user_namespace.h> #include "include/apparmor.h" diff --git a/security/commoncap.c b/security/commoncap.c index 6d4d586b9356..78b37838a2d3 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -548,9 +548,10 @@ skip: if ((is_setid || !cap_issubset(new->cap_permitted, old->cap_permitted)) && - bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { + ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) || + !ptracer_capable(current, new->user_ns))) { /* downgrade; they get no more than they had, and maybe less */ - if (!capable(CAP_SETUID) || + if (!ns_capable(new->user_ns, CAP_SETUID) || (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) { new->euid = new->uid; new->egid = new->gid; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index e2ed498c0f5f..063d38aef64e 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -22,6 +22,8 @@ #include <linux/xattr.h> #include <linux/integrity.h> #include <linux/evm.h> +#include <linux/magic.h> + #include <crypto/hash.h> #include <crypto/algapi.h> #include "evm.h" diff --git a/security/keys/dh.c b/security/keys/dh.c index 531ed2ec132f..893af4c45038 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -55,7 +55,7 @@ static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) if (status == 0) { const struct user_key_payload *payload; - payload = user_key_payload(key); + payload = user_key_payload_locked(key); if (maxlen == 0) { *mpi = NULL; diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 4fb315cddf5b..0010955d7876 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, const u8 **master_k goto error; down_read(&ukey->sem); - upayload = user_key_payload(ukey); + upayload = user_key_payload_locked(ukey); *master_key = upayload->data; *master_keylen = upayload->datalen; error: @@ -926,7 +926,7 @@ static long encrypted_read(const struct key *key, char __user *buffer, size_t asciiblob_len; int ret; - epayload = rcu_dereference_key(key); + epayload = dereference_key_locked(key); /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ asciiblob_len = epayload->datablob_len + ivsize + 1 diff --git a/security/keys/internal.h b/security/keys/internal.h index a705a7d92ad7..a2f4c0abb8d8 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -13,6 +13,7 @@ #define _INTERNAL_H #include <linux/sched.h> +#include <linux/cred.h> #include <linux/key-type.h> #include <linux/task_work.h> #include <linux/keyctl.h> diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 04a764f71ec8..52c34532c785 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -12,12 +12,14 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/sched/task.h> #include <linux/slab.h> #include <linux/syscalls.h> #include <linux/key.h> #include <linux/keyctl.h> #include <linux/fs.h> #include <linux/capability.h> +#include <linux/cred.h> #include <linux/string.h> #include <linux/err.h> #include <linux/vmalloc.h> diff --git a/security/keys/persistent.c b/security/keys/persistent.c index 1edc1f0a0ce2..d0cb5b32eff7 100644 --- a/security/keys/persistent.c +++ b/security/keys/persistent.c @@ -10,6 +10,8 @@ */ #include <linux/user_namespace.h> +#include <linux/cred.h> + #include "internal.h" unsigned persistent_keyring_expiry = 3 * 24 * 3600; /* Expire after 3 days of non-use */ diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 918cddcd4516..b6fdd22205b1 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/sched/user.h> #include <linux/keyctl.h> #include <linux/fs.h> #include <linux/err.h> diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 43affcf10b22..9822e500d50d 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -72,7 +72,7 @@ static void umh_keys_cleanup(struct subprocess_info *info) /* * Call a usermode helper with a specific session keyring. */ -static int call_usermodehelper_keys(char *path, char **argv, char **envp, +static int call_usermodehelper_keys(const char *path, char **argv, char **envp, struct key *session_keyring, int wait) { struct subprocess_info *info; @@ -95,6 +95,7 @@ static int call_sbin_request_key(struct key_construction *cons, const char *op, void *aux) { + static char const request_key[] = "/sbin/request-key"; const struct cred *cred = current_cred(); key_serial_t prkey, sskey; struct key *key = cons->key, *authkey = cons->authkey, *keyring, @@ -161,7 +162,7 @@ static int call_sbin_request_key(struct key_construction *cons, /* set up the argument list */ i = 0; - argv[i++] = "/sbin/request-key"; + argv[i++] = (char *)request_key; argv[i++] = (char *) op; argv[i++] = key_str; argv[i++] = uid_str; @@ -172,7 +173,7 @@ static int call_sbin_request_key(struct key_construction *cons, argv[i] = NULL; /* do it */ - ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, + ret = call_usermodehelper_keys(request_key, argv, envp, keyring, UMH_WAIT_PROC); kdebug("usermode -> 0x%x", ret); if (ret >= 0) { diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 90d61751ff12..2ae31c5a87de 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -1140,12 +1140,12 @@ out: static long trusted_read(const struct key *key, char __user *buffer, size_t buflen) { - struct trusted_key_payload *p; + const struct trusted_key_payload *p; char *ascii_buf; char *bufp; int i; - p = rcu_dereference_key(key); + p = dereference_key_locked(key); if (!p) return -EINVAL; if (!buffer || buflen <= 0) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index e187c8909d9d..26605134f17a 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -107,7 +107,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) /* attach the new data, displacing the old */ key->expiry = prep->expiry; if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) - zap = rcu_dereference_key(key); + zap = dereference_key_locked(key); rcu_assign_keypointer(key, prep->payload.data[0]); prep->payload.data[0] = NULL; @@ -123,7 +123,7 @@ EXPORT_SYMBOL_GPL(user_update); */ void user_revoke(struct key *key) { - struct user_key_payload *upayload = key->payload.data[0]; + struct user_key_payload *upayload = user_key_payload_locked(key); /* clear the quota */ key_payload_reserve(key, 0); @@ -169,7 +169,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) const struct user_key_payload *upayload; long ret; - upayload = user_key_payload(key); + upayload = user_key_payload_locked(key); ret = upayload->datalen; /* we can return the data as is */ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9bc12bcddc2c..0c2ac318aa7f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -28,7 +28,8 @@ #include <linux/kernel.h> #include <linux/tracehook.h> #include <linux/errno.h> -#include <linux/sched.h> +#include <linux/sched/signal.h> +#include <linux/sched/task.h> #include <linux/lsm_hooks.h> #include <linux/xattr.h> #include <linux/capability.h> @@ -480,12 +481,13 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) sbsec->behavior == SECURITY_FS_USE_NATIVE || /* Special handling. Genfs but also in-core setxattr handler */ !strcmp(sb->s_type->name, "sysfs") || - !strcmp(sb->s_type->name, "cgroup") || - !strcmp(sb->s_type->name, "cgroup2") || !strcmp(sb->s_type->name, "pstore") || !strcmp(sb->s_type->name, "debugfs") || !strcmp(sb->s_type->name, "tracefs") || - !strcmp(sb->s_type->name, "rootfs"); + !strcmp(sb->s_type->name, "rootfs") || + (selinux_policycap_cgroupseclabel && + (!strcmp(sb->s_type->name, "cgroup") || + !strcmp(sb->s_type->name, "cgroup2"))); } static int sb_finish_set_opts(struct super_block *sb) @@ -1401,7 +1403,9 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_KCM_SOCKET; case PF_QIPCRTR: return SECCLASS_QIPCRTR_SOCKET; -#if PF_MAX > 43 + case PF_SMC: + return SECCLASS_SMC_SOCKET; +#if PF_MAX > 44 #error New address family defined, please update this function. #endif } @@ -2397,8 +2401,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) /* Make sure that anyone attempting to ptrace over a task that * changes its SID has the appropriate permit */ - if (bprm->unsafe & - (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { + if (bprm->unsafe & LSM_UNSAFE_PTRACE) { u32 ptsid = ptrace_parent_sid(); if (ptsid != 0) { rc = avc_has_perm(ptsid, new_tsec->sid, @@ -4363,7 +4366,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in inet_get_local_port_range(sock_net(sk), &low, &high); - if (snum < max(PROT_SOCK, low) || snum > high) { + if (snum < max(inet_prot_sock(sock_net(sk)), low) || + snum > high) { err = sel_netport_sid(sk->sk_protocol, snum, &sid); if (err) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 7898ffa6d3e6..d429c4a1c551 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -229,9 +229,11 @@ struct security_class_mapping secclass_map[] = { { COMMON_SOCK_PERMS, NULL } }, { "qipcrtr_socket", { COMMON_SOCK_PERMS, NULL } }, + { "smc_socket", + { COMMON_SOCK_PERMS, NULL } }, { NULL } }; -#if PF_MAX > 43 +#if PF_MAX > 44 #error New address family defined, please update secclass_map. #endif diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index beaa14b8b6cf..f979c35e037e 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -71,6 +71,7 @@ enum { POLICYDB_CAPABILITY_OPENPERM, POLICYDB_CAPABILITY_EXTSOCKCLASS, POLICYDB_CAPABILITY_ALWAYSNETWORK, + POLICYDB_CAPABILITY_CGROUPSECLABEL, __POLICYDB_CAPABILITY_MAX }; #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) @@ -79,6 +80,7 @@ extern int selinux_policycap_netpeer; extern int selinux_policycap_openperm; extern int selinux_policycap_extsockclass; extern int selinux_policycap_alwaysnetwork; +extern int selinux_policycap_cgroupseclabel; /* * type_datum properties diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index c354807381c1..cb3fd98fb05a 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -46,7 +46,8 @@ static char *policycap_names[] = { "network_peer_controls", "open_perms", "extended_socket_class", - "always_check_network" + "always_check_network", + "cgroup_seclabel" }; unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; @@ -424,10 +425,9 @@ out: return ret; } -static int sel_mmap_policy_fault(struct vm_area_struct *vma, - struct vm_fault *vmf) +static int sel_mmap_policy_fault(struct vm_fault *vmf) { - struct policy_load_memory *plm = vma->vm_file->private_data; + struct policy_load_memory *plm = vmf->vma->vm_file->private_data; unsigned long offset; struct page *page; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 7d10e5d418bb..9db4709a6877 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -360,7 +360,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) if (mapunit != BITS_PER_U64) { printk(KERN_ERR "SELinux: ebitmap: map size %u does not " - "match my size %Zd (high bit was %d)\n", + "match my size %zd (high bit was %d)\n", mapunit, BITS_PER_U64, e->highbit); goto bad; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index d719db4219cd..9c92f29a38ea 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2266,7 +2266,7 @@ int policydb_read(struct policydb *p, void *fp) len = le32_to_cpu(buf[1]); if (len != strlen(POLICYDB_STRING)) { printk(KERN_ERR "SELinux: policydb string length %d does not " - "match expected length %Zu\n", + "match expected length %zu\n", len, strlen(POLICYDB_STRING)); goto bad; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a70fcee9824b..b4aa491a0a23 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -74,6 +74,7 @@ int selinux_policycap_netpeer; int selinux_policycap_openperm; int selinux_policycap_extsockclass; int selinux_policycap_alwaysnetwork; +int selinux_policycap_cgroupseclabel; static DEFINE_RWLOCK(policy_rwlock); @@ -1993,6 +1994,9 @@ static void security_load_policycaps(void) POLICYDB_CAPABILITY_EXTSOCKCLASS); selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, POLICYDB_CAPABILITY_ALWAYSNETWORK); + selinux_policycap_cgroupseclabel = + ebitmap_get_bit(&policydb.policycaps, + POLICYDB_CAPABILITY_CGROUPSECLABEL); } static int security_preserve_bools(struct policydb *p); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 60b4217b9b68..fc8fb31fc24f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -931,7 +931,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) isp->smk_task != sbsp->smk_root) return 0; - if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { + if (bprm->unsafe & LSM_UNSAFE_PTRACE) { struct task_struct *tracer; rc = 0; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 838ffa78cfda..00d223e9fb37 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -5,8 +5,10 @@ */ #include "common.h" + #include <linux/binfmts.h> #include <linux/slab.h> +#include <linux/rculist.h> /* Variables definitions.*/ diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c index 50092534ec54..944ad77d8fba 100644 --- a/security/tomoyo/group.c +++ b/security/tomoyo/group.c @@ -5,6 +5,8 @@ */ #include <linux/slab.h> +#include <linux/rculist.h> + #include "common.h" /** diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 5fe3679137ae..848317fea704 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -5,6 +5,8 @@ */ #include <linux/slab.h> +#include <linux/rculist.h> + #include "common.h" /* Lock for protecting policy. */ |