|
@@ -319,11 +319,7 @@ void key_fsgid_changed(struct task_struct *tsk)
|
|
|
* In the case of a successful return, the possession attribute is set on the
|
|
|
* returned key reference.
|
|
|
*/
|
|
|
-key_ref_t search_my_process_keyrings(struct key_type *type,
|
|
|
- const void *description,
|
|
|
- key_match_func_t match,
|
|
|
- bool no_state_check,
|
|
|
- const struct cred *cred)
|
|
|
+key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
|
|
|
{
|
|
|
key_ref_t key_ref, ret, err;
|
|
|
|
|
@@ -339,10 +335,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
|
|
|
err = ERR_PTR(-EAGAIN);
|
|
|
|
|
|
/* search the thread keyring first */
|
|
|
- if (cred->thread_keyring) {
|
|
|
+ if (ctx->cred->thread_keyring) {
|
|
|
key_ref = keyring_search_aux(
|
|
|
- make_key_ref(cred->thread_keyring, 1),
|
|
|
- cred, type, description, match, no_state_check);
|
|
|
+ make_key_ref(ctx->cred->thread_keyring, 1), ctx);
|
|
|
if (!IS_ERR(key_ref))
|
|
|
goto found;
|
|
|
|
|
@@ -358,10 +353,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
|
|
|
}
|
|
|
|
|
|
/* search the process keyring second */
|
|
|
- if (cred->process_keyring) {
|
|
|
+ if (ctx->cred->process_keyring) {
|
|
|
key_ref = keyring_search_aux(
|
|
|
- make_key_ref(cred->process_keyring, 1),
|
|
|
- cred, type, description, match, no_state_check);
|
|
|
+ make_key_ref(ctx->cred->process_keyring, 1), ctx);
|
|
|
if (!IS_ERR(key_ref))
|
|
|
goto found;
|
|
|
|
|
@@ -379,11 +373,11 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
|
|
|
}
|
|
|
|
|
|
/* search the session keyring */
|
|
|
- if (cred->session_keyring) {
|
|
|
+ if (ctx->cred->session_keyring) {
|
|
|
rcu_read_lock();
|
|
|
key_ref = keyring_search_aux(
|
|
|
- make_key_ref(rcu_dereference(cred->session_keyring), 1),
|
|
|
- cred, type, description, match, no_state_check);
|
|
|
+ make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1),
|
|
|
+ ctx);
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
if (!IS_ERR(key_ref))
|
|
@@ -402,10 +396,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
|
|
|
}
|
|
|
}
|
|
|
/* or search the user-session keyring */
|
|
|
- else if (cred->user->session_keyring) {
|
|
|
+ else if (ctx->cred->user->session_keyring) {
|
|
|
key_ref = keyring_search_aux(
|
|
|
- make_key_ref(cred->user->session_keyring, 1),
|
|
|
- cred, type, description, match, no_state_check);
|
|
|
+ make_key_ref(ctx->cred->user->session_keyring, 1),
|
|
|
+ ctx);
|
|
|
if (!IS_ERR(key_ref))
|
|
|
goto found;
|
|
|
|
|
@@ -437,19 +431,14 @@ found:
|
|
|
*
|
|
|
* Return same as search_my_process_keyrings().
|
|
|
*/
|
|
|
-key_ref_t search_process_keyrings(struct key_type *type,
|
|
|
- const void *description,
|
|
|
- key_match_func_t match,
|
|
|
- bool no_state_check,
|
|
|
- const struct cred *cred)
|
|
|
+key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
|
|
|
{
|
|
|
struct request_key_auth *rka;
|
|
|
key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
|
|
|
|
|
|
might_sleep();
|
|
|
|
|
|
- key_ref = search_my_process_keyrings(type, description, match,
|
|
|
- no_state_check, cred);
|
|
|
+ key_ref = search_my_process_keyrings(ctx);
|
|
|
if (!IS_ERR(key_ref))
|
|
|
goto found;
|
|
|
err = key_ref;
|
|
@@ -458,19 +447,21 @@ key_ref_t search_process_keyrings(struct key_type *type,
|
|
|
* search the keyrings of the process mentioned there
|
|
|
* - we don't permit access to request_key auth keys via this method
|
|
|
*/
|
|
|
- if (cred->request_key_auth &&
|
|
|
- cred == current_cred() &&
|
|
|
- type != &key_type_request_key_auth
|
|
|
+ if (ctx->cred->request_key_auth &&
|
|
|
+ ctx->cred == current_cred() &&
|
|
|
+ ctx->index_key.type != &key_type_request_key_auth
|
|
|
) {
|
|
|
+ const struct cred *cred = ctx->cred;
|
|
|
+
|
|
|
/* defend against the auth key being revoked */
|
|
|
down_read(&cred->request_key_auth->sem);
|
|
|
|
|
|
- if (key_validate(cred->request_key_auth) == 0) {
|
|
|
- rka = cred->request_key_auth->payload.data;
|
|
|
+ if (key_validate(ctx->cred->request_key_auth) == 0) {
|
|
|
+ rka = ctx->cred->request_key_auth->payload.data;
|
|
|
|
|
|
- key_ref = search_process_keyrings(type, description,
|
|
|
- match, no_state_check,
|
|
|
- rka->cred);
|
|
|
+ ctx->cred = rka->cred;
|
|
|
+ key_ref = search_process_keyrings(ctx);
|
|
|
+ ctx->cred = cred;
|
|
|
|
|
|
up_read(&cred->request_key_auth->sem);
|
|
|
|
|
@@ -524,19 +515,23 @@ int lookup_user_key_possessed(const struct key *key, const void *target)
|
|
|
key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
|
|
|
key_perm_t perm)
|
|
|
{
|
|
|
+ struct keyring_search_context ctx = {
|
|
|
+ .match = lookup_user_key_possessed,
|
|
|
+ .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
|
|
|
+ KEYRING_SEARCH_LOOKUP_DIRECT),
|
|
|
+ };
|
|
|
struct request_key_auth *rka;
|
|
|
- const struct cred *cred;
|
|
|
struct key *key;
|
|
|
key_ref_t key_ref, skey_ref;
|
|
|
int ret;
|
|
|
|
|
|
try_again:
|
|
|
- cred = get_current_cred();
|
|
|
+ ctx.cred = get_current_cred();
|
|
|
key_ref = ERR_PTR(-ENOKEY);
|
|
|
|
|
|
switch (id) {
|
|
|
case KEY_SPEC_THREAD_KEYRING:
|
|
|
- if (!cred->thread_keyring) {
|
|
|
+ if (!ctx.cred->thread_keyring) {
|
|
|
if (!(lflags & KEY_LOOKUP_CREATE))
|
|
|
goto error;
|
|
|
|
|
@@ -548,13 +543,13 @@ try_again:
|
|
|
goto reget_creds;
|
|
|
}
|
|
|
|
|
|
- key = cred->thread_keyring;
|
|
|
+ key = ctx.cred->thread_keyring;
|
|
|
atomic_inc(&key->usage);
|
|
|
key_ref = make_key_ref(key, 1);
|
|
|
break;
|
|
|
|
|
|
case KEY_SPEC_PROCESS_KEYRING:
|
|
|
- if (!cred->process_keyring) {
|
|
|
+ if (!ctx.cred->process_keyring) {
|
|
|
if (!(lflags & KEY_LOOKUP_CREATE))
|
|
|
goto error;
|
|
|
|
|
@@ -566,13 +561,13 @@ try_again:
|
|
|
goto reget_creds;
|
|
|
}
|
|
|
|
|
|
- key = cred->process_keyring;
|
|
|
+ key = ctx.cred->process_keyring;
|
|
|
atomic_inc(&key->usage);
|
|
|
key_ref = make_key_ref(key, 1);
|
|
|
break;
|
|
|
|
|
|
case KEY_SPEC_SESSION_KEYRING:
|
|
|
- if (!cred->session_keyring) {
|
|
|
+ if (!ctx.cred->session_keyring) {
|
|
|
/* always install a session keyring upon access if one
|
|
|
* doesn't exist yet */
|
|
|
ret = install_user_keyrings();
|
|
@@ -582,13 +577,13 @@ try_again:
|
|
|
ret = join_session_keyring(NULL);
|
|
|
else
|
|
|
ret = install_session_keyring(
|
|
|
- cred->user->session_keyring);
|
|
|
+ ctx.cred->user->session_keyring);
|
|
|
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
goto reget_creds;
|
|
|
- } else if (cred->session_keyring ==
|
|
|
- cred->user->session_keyring &&
|
|
|
+ } else if (ctx.cred->session_keyring ==
|
|
|
+ ctx.cred->user->session_keyring &&
|
|
|
lflags & KEY_LOOKUP_CREATE) {
|
|
|
ret = join_session_keyring(NULL);
|
|
|
if (ret < 0)
|
|
@@ -597,32 +592,32 @@ try_again:
|
|
|
}
|
|
|
|
|
|
rcu_read_lock();
|
|
|
- key = rcu_dereference(cred->session_keyring);
|
|
|
+ key = rcu_dereference(ctx.cred->session_keyring);
|
|
|
atomic_inc(&key->usage);
|
|
|
rcu_read_unlock();
|
|
|
key_ref = make_key_ref(key, 1);
|
|
|
break;
|
|
|
|
|
|
case KEY_SPEC_USER_KEYRING:
|
|
|
- if (!cred->user->uid_keyring) {
|
|
|
+ if (!ctx.cred->user->uid_keyring) {
|
|
|
ret = install_user_keyrings();
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- key = cred->user->uid_keyring;
|
|
|
+ key = ctx.cred->user->uid_keyring;
|
|
|
atomic_inc(&key->usage);
|
|
|
key_ref = make_key_ref(key, 1);
|
|
|
break;
|
|
|
|
|
|
case KEY_SPEC_USER_SESSION_KEYRING:
|
|
|
- if (!cred->user->session_keyring) {
|
|
|
+ if (!ctx.cred->user->session_keyring) {
|
|
|
ret = install_user_keyrings();
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- key = cred->user->session_keyring;
|
|
|
+ key = ctx.cred->user->session_keyring;
|
|
|
atomic_inc(&key->usage);
|
|
|
key_ref = make_key_ref(key, 1);
|
|
|
break;
|
|
@@ -633,7 +628,7 @@ try_again:
|
|
|
goto error;
|
|
|
|
|
|
case KEY_SPEC_REQKEY_AUTH_KEY:
|
|
|
- key = cred->request_key_auth;
|
|
|
+ key = ctx.cred->request_key_auth;
|
|
|
if (!key)
|
|
|
goto error;
|
|
|
|
|
@@ -642,20 +637,20 @@ try_again:
|
|
|
break;
|
|
|
|
|
|
case KEY_SPEC_REQUESTOR_KEYRING:
|
|
|
- if (!cred->request_key_auth)
|
|
|
+ if (!ctx.cred->request_key_auth)
|
|
|
goto error;
|
|
|
|
|
|
- down_read(&cred->request_key_auth->sem);
|
|
|
+ down_read(&ctx.cred->request_key_auth->sem);
|
|
|
if (test_bit(KEY_FLAG_REVOKED,
|
|
|
- &cred->request_key_auth->flags)) {
|
|
|
+ &ctx.cred->request_key_auth->flags)) {
|
|
|
key_ref = ERR_PTR(-EKEYREVOKED);
|
|
|
key = NULL;
|
|
|
} else {
|
|
|
- rka = cred->request_key_auth->payload.data;
|
|
|
+ rka = ctx.cred->request_key_auth->payload.data;
|
|
|
key = rka->dest_keyring;
|
|
|
atomic_inc(&key->usage);
|
|
|
}
|
|
|
- up_read(&cred->request_key_auth->sem);
|
|
|
+ up_read(&ctx.cred->request_key_auth->sem);
|
|
|
if (!key)
|
|
|
goto error;
|
|
|
key_ref = make_key_ref(key, 1);
|
|
@@ -675,9 +670,13 @@ try_again:
|
|
|
key_ref = make_key_ref(key, 0);
|
|
|
|
|
|
/* check to see if we possess the key */
|
|
|
- skey_ref = search_process_keyrings(key->type, key,
|
|
|
- lookup_user_key_possessed,
|
|
|
- true, cred);
|
|
|
+ ctx.index_key.type = key->type;
|
|
|
+ ctx.index_key.description = key->description;
|
|
|
+ ctx.index_key.desc_len = strlen(key->description);
|
|
|
+ ctx.match_data = key;
|
|
|
+ kdebug("check possessed");
|
|
|
+ skey_ref = search_process_keyrings(&ctx);
|
|
|
+ kdebug("possessed=%p", skey_ref);
|
|
|
|
|
|
if (!IS_ERR(skey_ref)) {
|
|
|
key_put(key);
|
|
@@ -717,14 +716,14 @@ try_again:
|
|
|
goto invalid_key;
|
|
|
|
|
|
/* check the permissions */
|
|
|
- ret = key_task_permission(key_ref, cred, perm);
|
|
|
+ ret = key_task_permission(key_ref, ctx.cred, perm);
|
|
|
if (ret < 0)
|
|
|
goto invalid_key;
|
|
|
|
|
|
key->last_used_at = current_kernel_time().tv_sec;
|
|
|
|
|
|
error:
|
|
|
- put_cred(cred);
|
|
|
+ put_cred(ctx.cred);
|
|
|
return key_ref;
|
|
|
|
|
|
invalid_key:
|
|
@@ -735,7 +734,7 @@ invalid_key:
|
|
|
/* if we attempted to install a keyring, then it may have caused new
|
|
|
* creds to be installed */
|
|
|
reget_creds:
|
|
|
- put_cred(cred);
|
|
|
+ put_cred(ctx.cred);
|
|
|
goto try_again;
|
|
|
}
|
|
|
|