diff options
Diffstat (limited to 'security')
36 files changed, 80 insertions, 40 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 6cf8fd2b79e..f77c6042399 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -10,6 +10,7 @@  #include <linux/list.h>  #include <linux/uaccess.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/rcupdate.h>  #include <linux/mutex.h> diff --git a/security/inode.c b/security/inode.c index c3a793881d0..1c812e87450 100644 --- a/security/inode.c +++ b/security/inode.c @@ -161,13 +161,13 @@ static int create_by_name(const char *name, mode_t mode,  	mutex_lock(&parent->d_inode->i_mutex);  	*dentry = lookup_one_len(name, parent, strlen(name)); -	if (!IS_ERR(dentry)) { +	if (!IS_ERR(*dentry)) {  		if ((mode & S_IFMT) == S_IFDIR)  			error = mkdir(parent->d_inode, *dentry, mode);  		else  			error = create(parent->d_inode, *dentry, mode);  	} else -		error = PTR_ERR(dentry); +		error = PTR_ERR(*dentry);  	mutex_unlock(&parent->d_inode->i_mutex);  	return error; diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 2a5e0bcf388..52015d098fd 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -13,6 +13,7 @@   *	and store_template.   */  #include <linux/module.h> +#include <linux/slab.h>  #include "ima.h"  static const char *IMA_TEMPLATE_NAME = "ima"; diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index ff513ff737f..5af76340470 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -11,6 +11,7 @@   */  #include <linux/fs.h> +#include <linux/gfp.h>  #include <linux/audit.h>  #include "ima.h" diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 46642a19bc7..952e51373f5 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -18,6 +18,7 @@  #include <linux/crypto.h>  #include <linux/scatterlist.h>  #include <linux/err.h> +#include <linux/slab.h>  #include "ima.h"  static int init_desc(struct hash_desc *desc) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 0c72c9c3895..07cb9c338cc 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -16,6 +16,7 @@   *	current measurement list and IMA statistics   */  #include <linux/fcntl.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/seq_file.h>  #include <linux/rculist.h> diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 2d4d05d92fd..2c744d48801 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c @@ -14,6 +14,7 @@   *	- cache integrity information associated with an inode   *	  using a radix tree.   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/spinlock.h>  #include <linux/radix-tree.h> diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index a40da7ae590..b1bcb702a27 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -16,6 +16,7 @@   */  #include <linux/module.h>  #include <linux/scatterlist.h> +#include <linux/slab.h>  #include <linux/err.h>  #include "ima.h" diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 294b005d652..b2c89d9de2a 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -21,6 +21,7 @@  #include <linux/binfmts.h>  #include <linux/mount.h>  #include <linux/mman.h> +#include <linux/slab.h>  #include "ima.h" diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4759d0f9933..8643a93c596 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -15,6 +15,7 @@  #include <linux/security.h>  #include <linux/magic.h>  #include <linux/parser.h> +#include <linux/slab.h>  #include "ima.h" diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index a0880e9c8e0..46ba62b1adf 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -20,6 +20,7 @@   */  #include <linux/module.h>  #include <linux/rculist.h> +#include <linux/slab.h>  #include "ima.h"  LIST_HEAD(ima_measurements);	/* list of all measurements */ diff --git a/security/keys/gc.c b/security/keys/gc.c index 19902319d09..a46e825cbf0 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -77,10 +77,10 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)  		goto dont_gc;  	/* scan the keyring looking for dead keys */ -	klist = rcu_dereference_check(keyring->payload.subscriptions, -				      lockdep_is_held(&key_serial_lock)); +	rcu_read_lock(); +	klist = rcu_dereference(keyring->payload.subscriptions);  	if (!klist) -		goto dont_gc; +		goto unlock_dont_gc;  	for (loop = klist->nkeys - 1; loop >= 0; loop--) {  		key = klist->keys[loop]; @@ -89,11 +89,14 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)  			goto do_gc;  	} +unlock_dont_gc: +	rcu_read_unlock();  dont_gc:  	kleave(" = false");  	return false;  do_gc: +	rcu_read_unlock();  	key_gc_cursor = keyring->serial;  	key_get(keyring);  	spin_unlock(&key_serial_lock); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e814d2109f8..1e4b0037935 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -20,6 +20,11 @@  #include <asm/uaccess.h>  #include "internal.h" +#define rcu_dereference_locked_keyring(keyring)				\ +	(rcu_dereference_protected(					\ +		(keyring)->payload.subscriptions,			\ +		rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) +  /*   * when plumbing the depths of the key tree, this sets a hard limit set on how   * deep we're willing to go @@ -201,8 +206,7 @@ static long keyring_read(const struct key *keyring,  	int loop, ret;  	ret = 0; -	klist = rcu_dereference(keyring->payload.subscriptions); - +	klist = rcu_dereference_locked_keyring(keyring);  	if (klist) {  		/* calculate how much data we could return */  		qty = klist->nkeys * sizeof(key_serial_t); @@ -526,9 +530,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)  	struct key *keyring;  	int bucket; -	keyring = ERR_PTR(-EINVAL);  	if (!name) -		goto error; +		return ERR_PTR(-EINVAL);  	bucket = keyring_hash(name); @@ -555,17 +558,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)  					   KEY_SEARCH) < 0)  				continue; -			/* we've got a match */ -			atomic_inc(&keyring->usage); -			read_unlock(&keyring_name_lock); -			goto error; +			/* we've got a match but we might end up racing with +			 * key_cleanup() if the keyring is currently 'dead' +			 * (ie. it has a zero usage count) */ +			if (!atomic_inc_not_zero(&keyring->usage)) +				continue; +			goto out;  		}  	} -	read_unlock(&keyring_name_lock);  	keyring = ERR_PTR(-ENOKEY); - - error: +out: +	read_unlock(&keyring_name_lock);  	return keyring;  } /* end find_keyring_by_name() */ @@ -720,8 +724,7 @@ int __key_link(struct key *keyring, struct key *key)  	}  	/* see if there's a matching key we can displace */ -	klist = keyring->payload.subscriptions; - +	klist = rcu_dereference_locked_keyring(keyring);  	if (klist && klist->nkeys > 0) {  		struct key_type *type = key->type; @@ -765,8 +768,6 @@ int __key_link(struct key *keyring, struct key *key)  	if (ret < 0)  		goto error2; -	klist = keyring->payload.subscriptions; -  	if (klist && klist->nkeys < klist->maxkeys) {  		/* there's sufficient slack space to add directly */  		atomic_inc(&key->usage); @@ -868,7 +869,7 @@ int key_unlink(struct key *keyring, struct key *key)  	down_write(&keyring->sem); -	klist = keyring->payload.subscriptions; +	klist = rcu_dereference_locked_keyring(keyring);  	if (klist) {  		/* search the keyring for the key */  		for (loop = 0; loop < klist->nkeys; loop++) @@ -959,7 +960,7 @@ int keyring_clear(struct key *keyring)  		/* detach the pointer block with the locks held */  		down_write(&keyring->sem); -		klist = keyring->payload.subscriptions; +		klist = rcu_dereference_locked_keyring(keyring);  		if (klist) {  			/* adjust the quota */  			key_payload_reserve(keyring, @@ -991,7 +992,9 @@ EXPORT_SYMBOL(keyring_clear);   */  static void keyring_revoke(struct key *keyring)  { -	struct keyring_list *klist = keyring->payload.subscriptions; +	struct keyring_list *klist; + +	klist = rcu_dereference_locked_keyring(keyring);  	/* adjust the quota */  	key_payload_reserve(keyring, 0); @@ -1025,7 +1028,7 @@ void keyring_gc(struct key *keyring, time_t limit)  	down_write(&keyring->sem); -	klist = keyring->payload.subscriptions; +	klist = rcu_dereference_locked_keyring(keyring);  	if (!klist)  		goto no_klist; diff --git a/security/keys/proc.c b/security/keys/proc.c index 9d01021ca0c..706d63f4f18 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -12,7 +12,6 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/sched.h> -#include <linux/slab.h>  #include <linux/fs.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 5c23afb31ec..06c2ccf26ed 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -12,7 +12,6 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/sched.h> -#include <linux/slab.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 03fe63ed55b..d8c1a6a0fb0 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -68,7 +68,8 @@ static int call_sbin_request_key(struct key_construction *cons,  {  	const struct cred *cred = current_cred();  	key_serial_t prkey, sskey; -	struct key *key = cons->key, *authkey = cons->authkey, *keyring; +	struct key *key = cons->key, *authkey = cons->authkey, *keyring, +		*session;  	char *argv[9], *envp[3], uid_str[12], gid_str[12];  	char key_str[12], keyring_str[3][12];  	char desc[20]; @@ -93,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons,  	}  	/* attach the auth key to the session keyring */ -	ret = __key_link(keyring, authkey); +	ret = key_link(keyring, authkey);  	if (ret < 0)  		goto error_link; @@ -112,10 +113,12 @@ static int call_sbin_request_key(struct key_construction *cons,  	if (cred->tgcred->process_keyring)  		prkey = cred->tgcred->process_keyring->serial; -	if (cred->tgcred->session_keyring) -		sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; -	else -		sskey = cred->user->session_keyring->serial; +	rcu_read_lock(); +	session = rcu_dereference(cred->tgcred->session_keyring); +	if (!session) +		session = cred->user->session_keyring; +	sskey = session->serial; +	rcu_read_unlock();  	sprintf(keyring_str[2], "%d", sskey); @@ -336,8 +339,10 @@ static int construct_alloc_key(struct key_type *type,  key_already_present:  	mutex_unlock(&key_construction_mutex); -	if (dest_keyring) +	if (dest_keyring) { +		__key_link(dest_keyring, key_ref_to_ptr(key_ref));  		up_write(&dest_keyring->sem); +	}  	mutex_unlock(&user->cons_lock);  	key_put(key);  	*_key = key = key_ref_to_ptr(key_ref); @@ -428,6 +433,11 @@ struct key *request_key_and_link(struct key_type *type,  	if (!IS_ERR(key_ref)) {  		key = key_ref_to_ptr(key_ref); +		if (dest_keyring) { +			construct_get_dest_keyring(&dest_keyring); +			key_link(dest_keyring, key); +			key_put(dest_keyring); +		}  	} else if (PTR_ERR(key_ref) != -EAGAIN) {  		key = ERR_CAST(key_ref);  	} else  { diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 7c687d56822..e9aa0792965 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -199,7 +199,8 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)  	struct user_key_payload *upayload;  	long ret; -	upayload = rcu_dereference(key->payload.data); +	upayload = rcu_dereference_protected( +		key->payload.data, rwsem_is_locked(&((struct key *)key)->sem));  	ret = upayload->datalen;  	/* we can return the data as is */ diff --git a/security/lsm_audit.c b/security/lsm_audit.c index acba3dfc8d2..893365b79a2 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -14,6 +14,7 @@  #include <linux/types.h>  #include <linux/stddef.h>  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <linux/fs.h>  #include <linux/init.h>  #include <net/sock.h> diff --git a/security/min_addr.c b/security/min_addr.c index e86f297522b..f728728f193 100644 --- a/security/min_addr.c +++ b/security/min_addr.c @@ -33,7 +33,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write,  {  	int ret; -	if (!capable(CAP_SYS_RAWIO)) +	if (write && !capable(CAP_SYS_RAWIO))  		return -EPERM;  	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index db0fd9f3349..989fef82563 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -337,7 +337,7 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)   * Look up an AVC entry that is valid for the   * (@ssid, @tsid), interpreting the permissions   * based on @tclass.  If a valid AVC entry exists, - * then this function return the avc_node. + * then this function returns the avc_node.   * Otherwise, this function returns NULL.   */  static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) @@ -523,7 +523,7 @@ void avc_audit(u32 ssid, u32 tsid,   * @perms: permissions   *   * Register a callback function for events in the set @events - * related to the SID pair (@ssid, @tsid) and + * related to the SID pair (@ssid, @tsid)    * and the permissions @perms, interpreting   * @perms based on @tclass.  Returns %0 on success or   * -%ENOMEM if insufficient memory exists to add the callback. @@ -568,7 +568,7 @@ static inline int avc_sidcmp(u32 x, u32 y)   *   * if a valid AVC entry doesn't exist,this function returns -ENOENT.   * if kmalloc() called internal returns NULL, this function returns -ENOMEM. - * otherwise, this function update the AVC entry. The original AVC-entry object + * otherwise, this function updates the AVC entry. The original AVC-entry object   * will release later by RCU.   */  static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, diff --git a/security/selinux/netif.c b/security/selinux/netif.c index b4e14bc0bf3..d6095d63d83 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -16,6 +16,7 @@   */  #include <linux/init.h>  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/stddef.h>  #include <linux/kernel.h>  #include <linux/list.h> diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2534400317c..628da72ee76 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -29,6 +29,7 @@  #include <linux/spinlock.h>  #include <linux/rcupdate.h> +#include <linux/gfp.h>  #include <linux/ip.h>  #include <linux/ipv6.h>  #include <net/sock.h> diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1ae556446e6..0e147b6914a 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -11,6 +11,7 @@   */  #include <linux/init.h>  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/stddef.h>  #include <linux/kernel.h>  #include <linux/list.h> diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 7100072bb1b..dc92792271f 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -31,6 +31,7 @@  #include <linux/types.h>  #include <linux/rcupdate.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/in.h>  #include <linux/in6.h> diff --git a/security/selinux/netport.c b/security/selinux/netport.c index fe7fba67f19..cfe2d72d3fb 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -30,6 +30,7 @@  #include <linux/types.h>  #include <linux/rcupdate.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/in.h>  #include <linux/in6.h> diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a842808..cd4f734e274 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified  void avtab_cache_init(void);  void avtab_cache_destroy(void); -#define MAX_AVTAB_HASH_BITS 13 +#define MAX_AVTAB_HASH_BITS 11  #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)  #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)  #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a98a5..bcf9f620426 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -4,7 +4,6 @@   * Author : Stephen Smalley, <sds@epoch.ncsc.mil>   */  #include <linux/kernel.h> -#include <linux/slab.h>  #include <linux/string.h>  #include <linux/errno.h>  #include "symtab.h" diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index f3cb9ed731a..fff78d3b51a 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -38,6 +38,7 @@  #include <linux/netfilter.h>  #include <linux/netfilter_ipv4.h>  #include <linux/netfilter_ipv6.h> +#include <linux/slab.h>  #include <linux/ip.h>  #include <linux/tcp.h>  #include <linux/skbuff.h> diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 0f9ac814690..f4fac64c4da 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -11,6 +11,7 @@   */  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/fs.h>  #include <linux/sched.h>  #include "smack.h" diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5225e668dbf..fdfeaa2f28e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -25,6 +25,7 @@  #include <linux/ip.h>  #include <linux/tcp.h>  #include <linux/udp.h> +#include <linux/slab.h>  #include <linux/mutex.h>  #include <linux/pipe_fs_i.h>  #include <net/netlabel.h> diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index aeead758509..a2b72d77f92 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -20,6 +20,7 @@  #include <linux/vmalloc.h>  #include <linux/security.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/netlabel.h>  #include <net/cipso_ipv4.h> diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ff51f1026b5..975c45d88ba 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -10,6 +10,7 @@   */  #include <linux/uaccess.h> +#include <linux/slab.h>  #include <linux/security.h>  #include <linux/hardirq.h>  #include "common.h" @@ -886,6 +887,7 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned  	ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);  	if (!tomoyo_memory_ok(ptr)) {  		kfree(ptr); +		ptr = NULL;  		goto ok;  	}  	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 66caaa1b842..acb8c397d5c 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -11,6 +11,7 @@  #include "common.h"  #include <linux/binfmts.h> +#include <linux/slab.h>  /* Variables definitions.*/ diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 1b24304edb7..6f3fe76a1fd 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -10,6 +10,7 @@   */  #include "common.h" +#include <linux/slab.h>  /* Keyword array for single path operations. */  static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 9645525ccdd..d9ad35bc7fa 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -9,6 +9,7 @@  #include "common.h"  #include <linux/kthread.h> +#include <linux/slab.h>  enum tomoyo_gc_id {  	TOMOYO_ID_DOMAIN_INITIALIZER, diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index cf7d61f781b..c225c65ce42 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -15,6 +15,7 @@  #include <linux/fs_struct.h>  #include <linux/hash.h>  #include <linux/magic.h> +#include <linux/slab.h>  #include "common.h"  /**  |