aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/key.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2017-09-18 11:37:03 -0700
committerDavid Howells <dhowells@redhat.com>2017-09-25 15:19:57 +0100
commit237bbd29f7a049d310d907f4b2716a7feef9abf3 (patch)
treebc95e55675ae062350f77c9f6d8f8d0816b83207 /security/keys/key.c
parentKEYS: fix writing past end of user-supplied buffer in keyring_read() (diff)
downloadlinux-dev-237bbd29f7a049d310d907f4b2716a7feef9abf3.tar.xz
linux-dev-237bbd29f7a049d310d907f4b2716a7feef9abf3.zip
KEYS: prevent creating a different user's keyrings
It was possible for an unprivileged user to create the user and user session keyrings for another user. For example: sudo -u '#3000' sh -c 'keyctl add keyring _uid.4000 "" @u keyctl add keyring _uid_ses.4000 "" @u sleep 15' & sleep 1 sudo -u '#4000' keyctl describe @u sudo -u '#4000' keyctl describe @us This is problematic because these "fake" keyrings won't have the right permissions. In particular, the user who created them first will own them and will have full access to them via the possessor permissions, which can be used to compromise the security of a user's keys: -4: alswrv-----v------------ 3000 0 keyring: _uid.4000 -5: alswrv-----v------------ 3000 0 keyring: _uid_ses.4000 Fix it by marking user and user session keyrings with a flag KEY_FLAG_UID_KEYRING. Then, when searching for a user or user session keyring by name, skip all keyrings that don't have the flag set. Fixes: 69664cf16af4 ("keys: don't generate user and user session keyrings unless they're accessed") Cc: <stable@vger.kernel.org> [v2.6.26+] Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r--security/keys/key.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/security/keys/key.c b/security/keys/key.c
index 83da68d98b40..e5c0896c3a8f 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -302,6 +302,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_BUILT_IN)
key->flags |= 1 << KEY_FLAG_BUILTIN;
+ if (flags & KEY_ALLOC_UID_KEYRING)
+ key->flags |= 1 << KEY_FLAG_UID_KEYRING;
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;