Commit 96b5c8fe authored by David Howells's avatar David Howells

KEYS: Reduce initial permissions on keys

Reduce the initial permissions on new keys to grant the possessor everything,
view permission only to the user (so the keys can be seen in /proc/keys) and
nothing else.

This gives the creator a chance to adjust the permissions mask before other
processes can access the new key or create a link to it.

To aid with this, keyring_alloc() now takes a permission argument rather than
setting the permissions itself.

The following permissions are now set:

 (1) The user and user-session keyrings grant the user that owns them full
     permissions and grant a possessor everything bar SETATTR.

 (2) The process and thread keyrings grant the possessor full permissions but
     only grant the user VIEW.  This permits the user to see them in
     /proc/keys, but not to do anything with them.

 (3) Anonymous session keyrings grant the possessor full permissions, but only
     grant the user VIEW and READ.  This means that the user can see them in
     /proc/keys and can list them, but nothing else.  Possibly READ shouldn't
     be provided either.

 (4) Named session keyrings grant everything an anonymous session keyring does,
     plus they grant the user LINK permission.  The whole point of named
     session keyrings is that others can also subscribe to them.  Possibly this
     should be a separate permission to LINK.

 (5) The temporary session keyring created by call_sbin_request_key() gets the
     same permissions as an anonymous session keyring.

 (6) Keys created by add_key() get VIEW, SEARCH, LINK and SETATTR for the
     possessor, plus READ and/or WRITE if the key type supports them.  The used
     only gets VIEW now.

 (7) Keys created by request_key() now get the same as those created by
     add_key().
Reported-by: default avatarLennart Poettering <lennart@poettering.net>
Reported-by: default avatarStef Walter <stefw@redhat.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 3a50597d
...@@ -264,6 +264,7 @@ extern int key_unlink(struct key *keyring, ...@@ -264,6 +264,7 @@ extern int key_unlink(struct key *keyring,
extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
const struct cred *cred, const struct cred *cred,
key_perm_t perm,
unsigned long flags, unsigned long flags,
struct key *dest); struct key *dest);
......
...@@ -826,13 +826,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, ...@@ -826,13 +826,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
/* if the client doesn't provide, decide on the permissions we want */ /* if the client doesn't provide, decide on the permissions we want */
if (perm == KEY_PERM_UNDEF) { if (perm == KEY_PERM_UNDEF) {
perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; perm |= KEY_USR_VIEW;
if (ktype->read) if (ktype->read)
perm |= KEY_POS_READ | KEY_USR_READ; perm |= KEY_POS_READ;
if (ktype == &key_type_keyring || ktype->update) if (ktype == &key_type_keyring || ktype->update)
perm |= KEY_USR_WRITE; perm |= KEY_POS_WRITE;
} }
/* allocate a new key */ /* allocate a new key */
......
...@@ -257,17 +257,14 @@ static long keyring_read(const struct key *keyring, ...@@ -257,17 +257,14 @@ static long keyring_read(const struct key *keyring,
* Allocate a keyring and link into the destination keyring. * Allocate a keyring and link into the destination keyring.
*/ */
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
const struct cred *cred, unsigned long flags, const struct cred *cred, key_perm_t perm,
struct key *dest) unsigned long flags, struct key *dest)
{ {
struct key *keyring; struct key *keyring;
int ret; int ret;
keyring = key_alloc(&key_type_keyring, description, keyring = key_alloc(&key_type_keyring, description,
uid, gid, cred, uid, gid, cred, perm, flags);
(KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
flags);
if (!IS_ERR(keyring)) { if (!IS_ERR(keyring)) {
ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
if (ret < 0) { if (ret < 0) {
......
...@@ -46,9 +46,11 @@ int install_user_keyrings(void) ...@@ -46,9 +46,11 @@ int install_user_keyrings(void)
struct user_struct *user; struct user_struct *user;
const struct cred *cred; const struct cred *cred;
struct key *uid_keyring, *session_keyring; struct key *uid_keyring, *session_keyring;
key_perm_t user_keyring_perm;
char buf[20]; char buf[20];
int ret; int ret;
user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
cred = current_cred(); cred = current_cred();
user = cred->user; user = cred->user;
...@@ -72,8 +74,8 @@ int install_user_keyrings(void) ...@@ -72,8 +74,8 @@ int install_user_keyrings(void)
uid_keyring = find_keyring_by_name(buf, true); uid_keyring = find_keyring_by_name(buf, true);
if (IS_ERR(uid_keyring)) { if (IS_ERR(uid_keyring)) {
uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
cred, KEY_ALLOC_IN_QUOTA, cred, user_keyring_perm,
NULL); KEY_ALLOC_IN_QUOTA, NULL);
if (IS_ERR(uid_keyring)) { if (IS_ERR(uid_keyring)) {
ret = PTR_ERR(uid_keyring); ret = PTR_ERR(uid_keyring);
goto error; goto error;
...@@ -88,7 +90,8 @@ int install_user_keyrings(void) ...@@ -88,7 +90,8 @@ int install_user_keyrings(void)
if (IS_ERR(session_keyring)) { if (IS_ERR(session_keyring)) {
session_keyring = session_keyring =
keyring_alloc(buf, user->uid, (gid_t) -1, keyring_alloc(buf, user->uid, (gid_t) -1,
cred, KEY_ALLOC_IN_QUOTA, NULL); cred, user_keyring_perm,
KEY_ALLOC_IN_QUOTA, NULL);
if (IS_ERR(session_keyring)) { if (IS_ERR(session_keyring)) {
ret = PTR_ERR(session_keyring); ret = PTR_ERR(session_keyring);
goto error_release; goto error_release;
...@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new) ...@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new)
struct key *keyring; struct key *keyring;
keyring = keyring_alloc("_tid", new->uid, new->gid, new, keyring = keyring_alloc("_tid", new->uid, new->gid, new,
KEY_POS_ALL | KEY_USR_VIEW,
KEY_ALLOC_QUOTA_OVERRUN, NULL); KEY_ALLOC_QUOTA_OVERRUN, NULL);
if (IS_ERR(keyring)) if (IS_ERR(keyring))
return PTR_ERR(keyring); return PTR_ERR(keyring);
...@@ -173,8 +177,9 @@ int install_process_keyring_to_cred(struct cred *new) ...@@ -173,8 +177,9 @@ int install_process_keyring_to_cred(struct cred *new)
if (new->process_keyring) if (new->process_keyring)
return -EEXIST; return -EEXIST;
keyring = keyring_alloc("_pid", new->uid, new->gid, keyring = keyring_alloc("_pid", new->uid, new->gid, new,
new, KEY_ALLOC_QUOTA_OVERRUN, NULL); KEY_POS_ALL | KEY_USR_VIEW,
KEY_ALLOC_QUOTA_OVERRUN, NULL);
if (IS_ERR(keyring)) if (IS_ERR(keyring))
return PTR_ERR(keyring); return PTR_ERR(keyring);
...@@ -223,8 +228,9 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) ...@@ -223,8 +228,9 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
if (cred->session_keyring) if (cred->session_keyring)
flags = KEY_ALLOC_IN_QUOTA; flags = KEY_ALLOC_IN_QUOTA;
keyring = keyring_alloc("_ses", cred->uid, cred->gid, keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
cred, flags, NULL); KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
flags, NULL);
if (IS_ERR(keyring)) if (IS_ERR(keyring))
return PTR_ERR(keyring); return PTR_ERR(keyring);
} else { } else {
...@@ -773,8 +779,10 @@ long join_session_keyring(const char *name) ...@@ -773,8 +779,10 @@ long join_session_keyring(const char *name)
keyring = find_keyring_by_name(name, false); keyring = find_keyring_by_name(name, false);
if (PTR_ERR(keyring) == -ENOKEY) { if (PTR_ERR(keyring) == -ENOKEY) {
/* not found - try and create a new one */ /* not found - try and create a new one */
keyring = keyring_alloc(name, old->uid, old->gid, old, keyring = keyring_alloc(
KEY_ALLOC_IN_QUOTA, NULL); name, old->uid, old->gid, old,
KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
KEY_ALLOC_IN_QUOTA, NULL);
if (IS_ERR(keyring)) { if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring); ret = PTR_ERR(keyring);
goto error2; goto error2;
......
...@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons, ...@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons,
cred = get_current_cred(); cred = get_current_cred();
keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
KEY_ALLOC_QUOTA_OVERRUN, NULL); KEY_ALLOC_QUOTA_OVERRUN, NULL);
put_cred(cred); put_cred(cred);
if (IS_ERR(keyring)) { if (IS_ERR(keyring)) {
...@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type, ...@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type,
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
unsigned long prealloc; unsigned long prealloc;
struct key *key; struct key *key;
key_perm_t perm;
key_ref_t key_ref; key_ref_t key_ref;
int ret; int ret;
...@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type, ...@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type,
*_key = NULL; *_key = NULL;
mutex_lock(&user->cons_lock); 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)
perm |= KEY_POS_READ;
if (type == &key_type_keyring || type->update)
perm |= KEY_POS_WRITE;
key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
KEY_POS_ALL, flags); perm, flags);
if (IS_ERR(key)) if (IS_ERR(key))
goto alloc_failed; goto alloc_failed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment