diff options
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r-- | security/keys/process_keys.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 566b1cc0118..74cb79eb917 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -270,9 +270,14 @@ int copy_thread_group_keys(struct task_struct *tsk) int copy_keys(unsigned long clone_flags, struct task_struct *tsk) { key_check(tsk->thread_keyring); + key_check(tsk->request_key_auth); /* no thread keyring yet */ tsk->thread_keyring = NULL; + + /* copy the request_key() authorisation for this thread */ + key_get(tsk->request_key_auth); + return 0; } /* end copy_keys() */ @@ -290,11 +295,12 @@ void exit_thread_group_keys(struct signal_struct *tg) /*****************************************************************************/ /* - * dispose of keys upon thread exit + * dispose of per-thread keys upon thread exit */ void exit_keys(struct task_struct *tsk) { key_put(tsk->thread_keyring); + key_put(tsk->request_key_auth); } /* end exit_keys() */ @@ -382,7 +388,7 @@ key_ref_t search_process_keyrings(struct key_type *type, struct task_struct *context) { struct request_key_auth *rka; - key_ref_t key_ref, ret, err, instkey_ref; + key_ref_t key_ref, ret, err; /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were * searchable, but we failed to find a key or we found a negative key; @@ -461,30 +467,12 @@ key_ref_t search_process_keyrings(struct key_type *type, err = key_ref; break; } - - /* if this process has a session keyring and that has an - * instantiation authorisation key in the bottom level, then we - * also search the keyrings of the process mentioned there */ - if (context != current) - goto no_key; - - rcu_read_lock(); - instkey_ref = __keyring_search_one( - make_key_ref(rcu_dereference( - context->signal->session_keyring), - 1), - &key_type_request_key_auth, NULL, 0); - rcu_read_unlock(); - - if (IS_ERR(instkey_ref)) - goto no_key; - - rka = key_ref_to_ptr(instkey_ref)->payload.data; - - key_ref = search_process_keyrings(type, description, match, - rka->context); - key_ref_put(instkey_ref); - + } + /* or search the user-session keyring */ + else { + key_ref = keyring_search_aux( + make_key_ref(context->user->session_keyring, 1), + context, type, description, match); if (!IS_ERR(key_ref)) goto found; @@ -500,11 +488,21 @@ key_ref_t search_process_keyrings(struct key_type *type, break; } } - /* or search the user-session keyring */ - else { - key_ref = keyring_search_aux( - make_key_ref(context->user->session_keyring, 1), - context, type, description, match); + + /* if this process has an instantiation authorisation key, then we also + * search the keyrings of the process mentioned there + * - we don't permit access to request_key auth keys via this method + */ + if (context->request_key_auth && + context == current && + type != &key_type_request_key_auth && + key_validate(context->request_key_auth) == 0 + ) { + rka = context->request_key_auth->payload.data; + + key_ref = search_process_keyrings(type, description, match, + rka->context); + if (!IS_ERR(key_ref)) goto found; @@ -521,8 +519,6 @@ key_ref_t search_process_keyrings(struct key_type *type, } } - -no_key: /* no key - decide on the error we're going to go for */ key_ref = ret ? ret : err; @@ -628,6 +624,15 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, key = ERR_PTR(-EINVAL); goto error; + case KEY_SPEC_REQKEY_AUTH_KEY: + key = context->request_key_auth; + if (!key) + goto error; + + atomic_inc(&key->usage); + key_ref = make_key_ref(key, 1); + break; + default: key_ref = ERR_PTR(-EINVAL); if (id < 1) |