Skip to content

Commit

Permalink
KEYS: Deal with dead-type keys appropriately [try #6]
Browse files Browse the repository at this point in the history
Allow keys for which the key type has been removed to be unlinked.  Currently
dead-type keys can only be disposed of by completely clearing the keyrings
that point to them.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
  • Loading branch information
David Howells authored and James Morris committed Sep 2, 2009
1 parent e0e8173 commit 5593122
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 31 deletions.
5 changes: 4 additions & 1 deletion security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ extern struct key *request_key_and_link(struct key_type *type,
struct key *dest_keyring,
unsigned long flags);

extern key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
key_perm_t perm);
#define KEY_LOOKUP_CREATE 0x01
#define KEY_LOOKUP_PARTIAL 0x02
#define KEY_LOOKUP_FOR_UNLINK 0x04

extern long join_session_keyring(const char *name);

Expand Down
6 changes: 2 additions & 4 deletions security/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,10 +642,8 @@ struct key *key_lookup(key_serial_t id)
goto error;

found:
/* pretend it doesn't exist if it's dead */
if (atomic_read(&key->usage) == 0 ||
test_bit(KEY_FLAG_DEAD, &key->flags) ||
key->type == &key_type_dead)
/* pretend it doesn't exist if it is awaiting deletion */
if (atomic_read(&key->usage) == 0)
goto not_found;

/* this races with key_put(), but that doesn't matter since key_put()
Expand Down
50 changes: 29 additions & 21 deletions security/keys/keyctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
}

/* find the target keyring (which must be writable) */
keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
goto error3;
Expand Down Expand Up @@ -185,7 +185,8 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
/* get the destination keyring if specified */
dest_ref = NULL;
if (destringid) {
dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE);
dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
KEY_WRITE);
if (IS_ERR(dest_ref)) {
ret = PTR_ERR(dest_ref);
goto error3;
Expand Down Expand Up @@ -233,9 +234,11 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
long keyctl_get_keyring_ID(key_serial_t id, int create)
{
key_ref_t key_ref;
unsigned long lflags;
long ret;

key_ref = lookup_user_key(id, create, 0, KEY_SEARCH);
lflags = create ? KEY_LOOKUP_CREATE : 0;
key_ref = lookup_user_key(id, lflags, KEY_SEARCH);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Expand Down Expand Up @@ -309,7 +312,7 @@ long keyctl_update_key(key_serial_t id,
}

/* find the target key (which must be writable) */
key_ref = lookup_user_key(id, 0, 0, KEY_WRITE);
key_ref = lookup_user_key(id, 0, KEY_WRITE);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error2;
Expand Down Expand Up @@ -337,7 +340,7 @@ long keyctl_revoke_key(key_serial_t id)
key_ref_t key_ref;
long ret;

key_ref = lookup_user_key(id, 0, 0, KEY_WRITE);
key_ref = lookup_user_key(id, 0, KEY_WRITE);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Expand All @@ -363,7 +366,7 @@ long keyctl_keyring_clear(key_serial_t ringid)
key_ref_t keyring_ref;
long ret;

keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
goto error;
Expand All @@ -389,13 +392,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
key_ref_t keyring_ref, key_ref;
long ret;

keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
goto error;
}

key_ref = lookup_user_key(id, 1, 0, KEY_LINK);
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_LINK);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error2;
Expand Down Expand Up @@ -423,13 +426,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
key_ref_t keyring_ref, key_ref;
long ret;

keyring_ref = lookup_user_key(ringid, 0, 0, KEY_WRITE);
keyring_ref = lookup_user_key(ringid, 0, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
goto error;
}

key_ref = lookup_user_key(id, 0, 0, 0);
key_ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error2;
Expand Down Expand Up @@ -465,7 +468,7 @@ long keyctl_describe_key(key_serial_t keyid,
char *tmpbuf;
long ret;

key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW);
key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
if (IS_ERR(key_ref)) {
/* viewing a key under construction is permitted if we have the
* authorisation token handy */
Expand All @@ -474,7 +477,8 @@ long keyctl_describe_key(key_serial_t keyid,
if (!IS_ERR(instkey)) {
key_put(instkey);
key_ref = lookup_user_key(keyid,
0, 1, 0);
KEY_LOOKUP_PARTIAL,
0);
if (!IS_ERR(key_ref))
goto okay;
}
Expand Down Expand Up @@ -558,7 +562,7 @@ long keyctl_keyring_search(key_serial_t ringid,
}

/* get the keyring at which to begin the search */
keyring_ref = lookup_user_key(ringid, 0, 0, KEY_SEARCH);
keyring_ref = lookup_user_key(ringid, 0, KEY_SEARCH);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
goto error2;
Expand All @@ -567,7 +571,8 @@ long keyctl_keyring_search(key_serial_t ringid,
/* get the destination keyring if specified */
dest_ref = NULL;
if (destringid) {
dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE);
dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
KEY_WRITE);
if (IS_ERR(dest_ref)) {
ret = PTR_ERR(dest_ref);
goto error3;
Expand Down Expand Up @@ -637,7 +642,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
long ret;

/* find the key first */
key_ref = lookup_user_key(keyid, 0, 0, 0);
key_ref = lookup_user_key(keyid, 0, 0);
if (IS_ERR(key_ref)) {
ret = -ENOKEY;
goto error;
Expand Down Expand Up @@ -700,7 +705,8 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
if (uid == (uid_t) -1 && gid == (gid_t) -1)
goto error;

key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Expand Down Expand Up @@ -805,7 +811,8 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
goto error;

key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Expand Down Expand Up @@ -847,7 +854,7 @@ static long get_instantiation_keyring(key_serial_t ringid,

/* if a specific keyring is nominated by ID, then use that */
if (ringid > 0) {
dkref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
if (IS_ERR(dkref))
return PTR_ERR(dkref);
*_dest_keyring = key_ref_to_ptr(dkref);
Expand Down Expand Up @@ -1083,7 +1090,8 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
time_t expiry;
long ret;

key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Expand Down Expand Up @@ -1170,7 +1178,7 @@ long keyctl_get_security(key_serial_t keyid,
char *context;
long ret;

key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW);
key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
if (IS_ERR(key_ref)) {
if (PTR_ERR(key_ref) != -EACCES)
return PTR_ERR(key_ref);
Expand All @@ -1182,7 +1190,7 @@ long keyctl_get_security(key_serial_t keyid,
return PTR_ERR(key_ref);
key_put(instkey);

key_ref = lookup_user_key(keyid, 0, 1, 0);
key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0);
if (IS_ERR(key_ref))
return PTR_ERR(key_ref);
}
Expand Down
18 changes: 13 additions & 5 deletions security/keys/process_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ static int lookup_user_key_possessed(const struct key *key, const void *target)
* - don't create special keyrings unless so requested
* - partially constructed keys aren't found unless requested
*/
key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
key_perm_t perm)
{
struct request_key_auth *rka;
Expand All @@ -503,7 +503,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
switch (id) {
case KEY_SPEC_THREAD_KEYRING:
if (!cred->thread_keyring) {
if (!create)
if (!(lflags & KEY_LOOKUP_CREATE))
goto error;

ret = install_thread_keyring();
Expand All @@ -521,7 +521,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,

case KEY_SPEC_PROCESS_KEYRING:
if (!cred->tgcred->process_keyring) {
if (!create)
if (!(lflags & KEY_LOOKUP_CREATE))
goto error;

ret = install_process_keyring();
Expand Down Expand Up @@ -642,7 +642,14 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
break;
}

if (!partial) {
/* unlink does not use the nominated key in any way, so can skip all
* the permission checks as it is only concerned with the keyring */
if (lflags & KEY_LOOKUP_FOR_UNLINK) {
ret = 0;
goto error;
}

if (!(lflags & KEY_LOOKUP_PARTIAL)) {
ret = wait_for_key_construction(key, true);
switch (ret) {
case -ERESTARTSYS:
Expand All @@ -660,7 +667,8 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
}

ret = -EIO;
if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
if (!(lflags & KEY_LOOKUP_PARTIAL) &&
!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
goto invalid_key;

/* check the permissions */
Expand Down

0 comments on commit 5593122

Please sign in to comment.