diff options
Diffstat (limited to 'security/keys/request_key.c')
| -rw-r--r-- | security/keys/request_key.c | 60 | 
1 files changed, 33 insertions, 27 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index c411f9bb156..381411941cc 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -345,33 +345,34 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)   * May return a key that's already under construction instead if there was a   * race between two thread calling request_key().   */ -static int construct_alloc_key(struct key_type *type, -			       const char *description, +static int construct_alloc_key(struct keyring_search_context *ctx,  			       struct key *dest_keyring,  			       unsigned long flags,  			       struct key_user *user,  			       struct key **_key)  { -	const struct cred *cred = current_cred(); -	unsigned long prealloc; +	struct assoc_array_edit *edit;  	struct key *key;  	key_perm_t perm;  	key_ref_t key_ref;  	int ret; -	kenter("%s,%s,,,", type->name, description); +	kenter("%s,%s,,,", +	       ctx->index_key.type->name, ctx->index_key.description);  	*_key = NULL;  	mutex_lock(&user->cons_lock);  	perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;  	perm |= KEY_USR_VIEW; -	if (type->read) +	if (ctx->index_key.type->read)  		perm |= KEY_POS_READ; -	if (type == &key_type_keyring || type->update) +	if (ctx->index_key.type == &key_type_keyring || +	    ctx->index_key.type->update)  		perm |= KEY_POS_WRITE; -	key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, +	key = key_alloc(ctx->index_key.type, ctx->index_key.description, +			ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred,  			perm, flags);  	if (IS_ERR(key))  		goto alloc_failed; @@ -379,8 +380,7 @@ static int construct_alloc_key(struct key_type *type,  	set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);  	if (dest_keyring) { -		ret = __key_link_begin(dest_keyring, type, description, -				       &prealloc); +		ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit);  		if (ret < 0)  			goto link_prealloc_failed;  	} @@ -390,16 +390,16 @@ static int construct_alloc_key(struct key_type *type,  	 * waited for locks */  	mutex_lock(&key_construction_mutex); -	key_ref = search_process_keyrings(type, description, type->match, cred); +	key_ref = search_process_keyrings(ctx);  	if (!IS_ERR(key_ref))  		goto key_already_present;  	if (dest_keyring) -		__key_link(dest_keyring, key, &prealloc); +		__key_link(key, &edit);  	mutex_unlock(&key_construction_mutex);  	if (dest_keyring) -		__key_link_end(dest_keyring, type, prealloc); +		__key_link_end(dest_keyring, &ctx->index_key, edit);  	mutex_unlock(&user->cons_lock);  	*_key = key;  	kleave(" = 0 [%d]", key_serial(key)); @@ -414,8 +414,8 @@ key_already_present:  	if (dest_keyring) {  		ret = __key_link_check_live_key(dest_keyring, key);  		if (ret == 0) -			__key_link(dest_keyring, key, &prealloc); -		__key_link_end(dest_keyring, type, prealloc); +			__key_link(key, &edit); +		__key_link_end(dest_keyring, &ctx->index_key, edit);  		if (ret < 0)  			goto link_check_failed;  	} @@ -444,8 +444,7 @@ alloc_failed:  /*   * Commence key construction.   */ -static struct key *construct_key_and_link(struct key_type *type, -					  const char *description, +static struct key *construct_key_and_link(struct keyring_search_context *ctx,  					  const char *callout_info,  					  size_t callout_len,  					  void *aux, @@ -464,8 +463,7 @@ static struct key *construct_key_and_link(struct key_type *type,  	construct_get_dest_keyring(&dest_keyring); -	ret = construct_alloc_key(type, description, dest_keyring, flags, user, -				  &key); +	ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key);  	key_user_put(user);  	if (ret == 0) { @@ -529,17 +527,24 @@ struct key *request_key_and_link(struct key_type *type,  				 struct key *dest_keyring,  				 unsigned long flags)  { -	const struct cred *cred = current_cred(); +	struct keyring_search_context ctx = { +		.index_key.type		= type, +		.index_key.description	= description, +		.cred			= current_cred(), +		.match			= type->match, +		.match_data		= description, +		.flags			= KEYRING_SEARCH_LOOKUP_DIRECT, +	};  	struct key *key;  	key_ref_t key_ref;  	int ret;  	kenter("%s,%s,%p,%zu,%p,%p,%lx", -	       type->name, description, callout_info, callout_len, aux, -	       dest_keyring, flags); +	       ctx.index_key.type->name, ctx.index_key.description, +	       callout_info, callout_len, aux, dest_keyring, flags);  	/* search all the process keyrings for a key */ -	key_ref = search_process_keyrings(type, description, type->match, cred); +	key_ref = search_process_keyrings(&ctx);  	if (!IS_ERR(key_ref)) {  		key = key_ref_to_ptr(key_ref); @@ -562,9 +567,8 @@ struct key *request_key_and_link(struct key_type *type,  		if (!callout_info)  			goto error; -		key = construct_key_and_link(type, description, callout_info, -					     callout_len, aux, dest_keyring, -					     flags); +		key = construct_key_and_link(&ctx, callout_info, callout_len, +					     aux, dest_keyring, flags);  	}  error: @@ -592,8 +596,10 @@ int wait_for_key_construction(struct key *key, bool intr)  			  intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);  	if (ret < 0)  		return ret; -	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) +	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { +		smp_rmb();  		return key->type_data.reject_error; +	}  	return key_validate(key);  }  EXPORT_SYMBOL(wait_for_key_construction);  | 
