diff options
Diffstat (limited to 'security/keys/permission.c')
| -rw-r--r-- | security/keys/permission.c | 83 | 
1 files changed, 38 insertions, 45 deletions
diff --git a/security/keys/permission.c b/security/keys/permission.c index 28645502cd0..732cc0beffd 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -1,4 +1,4 @@ -/* permission.c: key permission determination +/* Key permission checking   *   * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.   * Written by David Howells (dhowells@redhat.com) @@ -13,21 +13,22 @@  #include <linux/security.h>  #include "internal.h" -/*****************************************************************************/  /**   * key_task_permission - Check a key can be used - * @key_ref: The key to check - * @cred: The credentials to use - * @perm: The permissions to check for + * @key_ref: The key to check. + * @cred: The credentials to use. + * @perm: The permissions to check for.   *   * Check to see whether permission is granted to use a key in the desired way,   * but permit the security modules to override.   * - * The caller must hold either a ref on cred or must hold the RCU readlock or a - * spinlock. + * The caller must hold either a ref on cred or must hold the RCU readlock. + * + * Returns 0 if successful, -EACCES if access is denied based on the + * permissions bits or the LSM check.   */  int key_task_permission(const key_ref_t key_ref, const struct cred *cred, -			key_perm_t perm) +			unsigned perm)  {  	struct key *key;  	key_perm_t kperm; @@ -35,19 +36,16 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,  	key = key_ref_to_ptr(key_ref); -	if (key->user->user_ns != cred->user->user_ns) -		goto use_other_perms; -  	/* use the second 8-bits of permissions for keys the caller owns */ -	if (key->uid == cred->fsuid) { +	if (uid_eq(key->uid, cred->fsuid)) {  		kperm = key->perm >> 16;  		goto use_these_perms;  	}  	/* use the third 8-bits of permissions for keys the caller has a group  	 * membership in common with */ -	if (key->gid != -1 && key->perm & KEY_GRP_ALL) { -		if (key->gid == cred->fsgid) { +	if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) { +		if (gid_eq(key->gid, cred->fsgid)) {  			kperm = key->perm >> 8;  			goto use_these_perms;  		} @@ -59,8 +57,6 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,  		}  	} -use_other_perms: -  	/* otherwise use the least-significant 8-bits */  	kperm = key->perm; @@ -72,46 +68,43 @@ use_these_perms:  	if (is_key_possessed(key_ref))  		kperm |= key->perm >> 24; -	kperm = kperm & perm & KEY_ALL; +	kperm = kperm & perm & KEY_NEED_ALL;  	if (kperm != perm)  		return -EACCES;  	/* let LSM be the final arbiter */  	return security_key_permission(key_ref, cred, perm); - -} /* end key_task_permission() */ - +}  EXPORT_SYMBOL(key_task_permission); -/*****************************************************************************/ -/* - * validate a key +/** + * key_validate - Validate a key. + * @key: The key to be validated. + * + * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the + * key is invalidated, -EKEYREVOKED if the key's type has been removed or if + * the key has been revoked or -EKEYEXPIRED if the key has expired.   */ -int key_validate(struct key *key) +int key_validate(const struct key *key)  { -	struct timespec now; -	int ret = 0; - -	if (key) { -		/* check it's still accessible */ -		ret = -EKEYREVOKED; -		if (test_bit(KEY_FLAG_REVOKED, &key->flags) || -		    test_bit(KEY_FLAG_DEAD, &key->flags)) -			goto error; - -		/* check it hasn't expired */ -		ret = 0; -		if (key->expiry) { -			now = current_kernel_time(); -			if (now.tv_sec >= key->expiry) -				ret = -EKEYEXPIRED; -		} -	} +	unsigned long flags = key->flags; -error: -	return ret; +	if (flags & (1 << KEY_FLAG_INVALIDATED)) +		return -ENOKEY; -} /* end key_validate() */ +	/* check it's still accessible */ +	if (flags & ((1 << KEY_FLAG_REVOKED) | +		     (1 << KEY_FLAG_DEAD))) +		return -EKEYREVOKED; + +	/* check it hasn't expired */ +	if (key->expiry) { +		struct timespec now = current_kernel_time(); +		if (now.tv_sec >= key->expiry) +			return -EKEYEXPIRED; +	} +	return 0; +}  EXPORT_SYMBOL(key_validate);  | 
