mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
KEYS: Make /proc/keys check to see if a key is possessed before security check
Make /proc/keys check to see if the calling process possesses each key before performing the security check. The possession check can be skipped if the key doesn't have the possessor-view permission bit set. This causes the keys a process possesses to show up in /proc/keys, even if they don't have matching user/group/other view permissions. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
9156235b34
commit
927942aabb
@ -114,6 +114,10 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
|
||||
const void *description,
|
||||
key_match_func_t match);
|
||||
|
||||
extern key_ref_t search_my_process_keyrings(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match,
|
||||
const struct cred *cred);
|
||||
extern key_ref_t search_process_keyrings(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match,
|
||||
@ -134,6 +138,7 @@ extern struct key *request_key_and_link(struct key_type *type,
|
||||
struct key *dest_keyring,
|
||||
unsigned long flags);
|
||||
|
||||
extern int lookup_user_key_possessed(const struct key *key, const void *target);
|
||||
extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
|
||||
key_perm_t perm);
|
||||
#define KEY_LOOKUP_CREATE 0x01
|
||||
|
@ -184,20 +184,36 @@ static void proc_keys_stop(struct seq_file *p, void *v)
|
||||
|
||||
static int proc_keys_show(struct seq_file *m, void *v)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct rb_node *_p = v;
|
||||
struct key *key = rb_entry(_p, struct key, serial_node);
|
||||
struct timespec now;
|
||||
unsigned long timo;
|
||||
key_ref_t key_ref, skey_ref;
|
||||
char xbuf[12];
|
||||
int rc;
|
||||
|
||||
key_ref = make_key_ref(key, 0);
|
||||
|
||||
/* determine if the key is possessed by this process (a test we can
|
||||
* skip if the key does not indicate the possessor can view it
|
||||
*/
|
||||
if (key->perm & KEY_POS_VIEW) {
|
||||
skey_ref = search_my_process_keyrings(key->type, key,
|
||||
lookup_user_key_possessed,
|
||||
cred);
|
||||
if (!IS_ERR(skey_ref)) {
|
||||
key_ref_put(skey_ref);
|
||||
key_ref = make_key_ref(key, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* check whether the current task is allowed to view the key (assuming
|
||||
* non-possession)
|
||||
* - the caller holds a spinlock, and thus the RCU read lock, making our
|
||||
* access to __current_cred() safe
|
||||
*/
|
||||
rc = key_task_permission(make_key_ref(key, 0), current_cred(),
|
||||
KEY_VIEW);
|
||||
rc = key_task_permission(key_ref, cred, KEY_VIEW);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -309,22 +309,19 @@ void key_fsgid_changed(struct task_struct *tsk)
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the process keyrings for the first matching key
|
||||
* search only my process keyrings for the first matching key
|
||||
* - we use the supplied match function to see if the description (or other
|
||||
* feature of interest) matches
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we found only negative matching keys
|
||||
*/
|
||||
key_ref_t search_process_keyrings(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match,
|
||||
const struct cred *cred)
|
||||
key_ref_t search_my_process_keyrings(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match,
|
||||
const struct cred *cred)
|
||||
{
|
||||
struct request_key_auth *rka;
|
||||
key_ref_t key_ref, ret, err;
|
||||
|
||||
might_sleep();
|
||||
|
||||
/* 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;
|
||||
* otherwise we want to return a sample error (probably -EACCES) if
|
||||
@ -424,6 +421,36 @@ key_ref_t search_process_keyrings(struct key_type *type,
|
||||
}
|
||||
}
|
||||
|
||||
/* no key - decide on the error we're going to go for */
|
||||
key_ref = ret ? ret : err;
|
||||
|
||||
found:
|
||||
return key_ref;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the process keyrings for the first matching key
|
||||
* - we use the supplied match function to see if the description (or other
|
||||
* feature of interest) matches
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we found only negative matching keys
|
||||
*/
|
||||
key_ref_t search_process_keyrings(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match,
|
||||
const struct cred *cred)
|
||||
{
|
||||
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, cred);
|
||||
if (!IS_ERR(key_ref))
|
||||
goto found;
|
||||
err = key_ref;
|
||||
|
||||
/* 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
|
||||
@ -446,24 +473,19 @@ key_ref_t search_process_keyrings(struct key_type *type,
|
||||
if (!IS_ERR(key_ref))
|
||||
goto found;
|
||||
|
||||
switch (PTR_ERR(key_ref)) {
|
||||
case -EAGAIN: /* no key */
|
||||
if (ret)
|
||||
break;
|
||||
case -ENOKEY: /* negative key */
|
||||
ret = key_ref;
|
||||
break;
|
||||
default:
|
||||
err = key_ref;
|
||||
break;
|
||||
}
|
||||
ret = key_ref;
|
||||
} else {
|
||||
up_read(&cred->request_key_auth->sem);
|
||||
}
|
||||
}
|
||||
|
||||
/* no key - decide on the error we're going to go for */
|
||||
key_ref = ret ? ret : err;
|
||||
if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
|
||||
key_ref = ERR_PTR(-ENOKEY);
|
||||
else if (err == ERR_PTR(-EACCES))
|
||||
key_ref = ret;
|
||||
else
|
||||
key_ref = err;
|
||||
|
||||
found:
|
||||
return key_ref;
|
||||
@ -474,7 +496,7 @@ found:
|
||||
/*
|
||||
* see if the key we're looking at is the target key
|
||||
*/
|
||||
static int lookup_user_key_possessed(const struct key *key, const void *target)
|
||||
int lookup_user_key_possessed(const struct key *key, const void *target)
|
||||
{
|
||||
return key == target;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user