linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Eric Biggers <ebiggers@google.com>,
	David Howells <dhowells@redhat.com>
Subject: [PATCH 4.4 12/41] KEYS: prevent creating a different users keyrings
Date: Tue,  3 Oct 2017 14:21:13 +0200	[thread overview]
Message-ID: <20171003114220.691599070@linuxfoundation.org> (raw)
In-Reply-To: <20171003114219.900672076@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Biggers <ebiggers@google.com>

commit 237bbd29f7a049d310d907f4b2716a7feef9abf3 upstream.

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")
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 include/linux/key.h          |    2 ++
 security/keys/internal.h     |    2 +-
 security/keys/key.c          |    2 ++
 security/keys/keyring.c      |   23 ++++++++++++++---------
 security/keys/process_keys.c |    8 ++++++--
 5 files changed, 25 insertions(+), 12 deletions(-)

--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -177,6 +177,7 @@ struct key {
 #define KEY_FLAG_TRUSTED_ONLY	9	/* set if keyring only accepts links to trusted keys */
 #define KEY_FLAG_BUILTIN	10	/* set if key is builtin */
 #define KEY_FLAG_ROOT_CAN_INVAL	11	/* set if key can be invalidated by root without permission */
+#define KEY_FLAG_UID_KEYRING	12	/* set if key is a user or user session keyring */
 
 	/* the key type and key description string
 	 * - the desc is used to match a key against search criteria
@@ -218,6 +219,7 @@ extern struct key *key_alloc(struct key_
 #define KEY_ALLOC_QUOTA_OVERRUN	0x0001	/* add to quota, permit even if overrun */
 #define KEY_ALLOC_NOT_IN_QUOTA	0x0002	/* not in quota */
 #define KEY_ALLOC_TRUSTED	0x0004	/* Key should be flagged as trusted */
+#define KEY_ALLOC_UID_KEYRING	0x0010	/* allocating a user or user session keyring */
 
 extern void key_revoke(struct key *key);
 extern void key_invalidate(struct key *key);
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -136,7 +136,7 @@ extern key_ref_t keyring_search_aux(key_
 extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
 extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
 
-extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
+extern struct key *find_keyring_by_name(const char *name, bool uid_keyring);
 
 extern int install_user_keyrings(void);
 extern int install_thread_keyring_to_cred(struct cred *);
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *t
 		key->flags |= 1 << KEY_FLAG_IN_QUOTA;
 	if (flags & KEY_ALLOC_TRUSTED)
 		key->flags |= 1 << KEY_FLAG_TRUSTED;
+	if (flags & KEY_ALLOC_UID_KEYRING)
+		key->flags |= 1 << KEY_FLAG_UID_KEYRING;
 
 #ifdef KEY_DEBUGGING
 	key->magic = KEY_DEBUG_MAGIC;
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -961,15 +961,15 @@ found:
 /*
  * Find a keyring with the specified name.
  *
- * All named keyrings in the current user namespace are searched, provided they
- * grant Search permission directly to the caller (unless this check is
- * skipped).  Keyrings whose usage points have reached zero or who have been
- * revoked are skipped.
+ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a
+ * user in the current user namespace are considered.  If @uid_keyring is %true,
+ * the keyring additionally must have been allocated as a user or user session
+ * keyring; otherwise, it must grant Search permission directly to the caller.
  *
  * Returns a pointer to the keyring with the keyring's refcount having being
  * incremented on success.  -ENOKEY is returned if a key could not be found.
  */
-struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
+struct key *find_keyring_by_name(const char *name, bool uid_keyring)
 {
 	struct key *keyring;
 	int bucket;
@@ -997,10 +997,15 @@ struct key *find_keyring_by_name(const c
 			if (strcmp(keyring->description, name) != 0)
 				continue;
 
-			if (!skip_perm_check &&
-			    key_permission(make_key_ref(keyring, 0),
-					   KEY_NEED_SEARCH) < 0)
-				continue;
+			if (uid_keyring) {
+				if (!test_bit(KEY_FLAG_UID_KEYRING,
+					      &keyring->flags))
+					continue;
+			} else {
+				if (key_permission(make_key_ref(keyring, 0),
+						   KEY_NEED_SEARCH) < 0)
+					continue;
+			}
 
 			/* we've got a match but we might end up racing with
 			 * key_cleanup() if the keyring is currently 'dead'
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -76,7 +76,9 @@ int install_user_keyrings(void)
 		if (IS_ERR(uid_keyring)) {
 			uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
 						    cred, user_keyring_perm,
-						    KEY_ALLOC_IN_QUOTA, NULL);
+						    KEY_ALLOC_UID_KEYRING |
+							KEY_ALLOC_IN_QUOTA,
+						    NULL);
 			if (IS_ERR(uid_keyring)) {
 				ret = PTR_ERR(uid_keyring);
 				goto error;
@@ -92,7 +94,9 @@ int install_user_keyrings(void)
 			session_keyring =
 				keyring_alloc(buf, user->uid, INVALID_GID,
 					      cred, user_keyring_perm,
-					      KEY_ALLOC_IN_QUOTA, NULL);
+					      KEY_ALLOC_UID_KEYRING |
+						  KEY_ALLOC_IN_QUOTA,
+					      NULL);
 			if (IS_ERR(session_keyring)) {
 				ret = PTR_ERR(session_keyring);
 				goto error_release;

  parent reply	other threads:[~2017-10-03 12:22 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-03 12:21 [PATCH 4.4 00/41] 4.4.90-stable review Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 01/41] cifs: release auth_key.response for reconnect Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 02/41] mac80211: flush hw_roc_start work before cancelling the ROC Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 03/41] KVM: PPC: Book3S: Fix race and leak in kvm_vm_ioctl_create_spapr_tce() Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 04/41] tracing: Fix trace_pipe behavior for instance traces Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 05/41] tracing: Erase irqsoff trace with empty write Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 06/41] md/raid5: fix a race condition in stripe batch Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 07/41] md/raid5: preserve STRIPE_ON_UNPLUG_LIST in break_stripe_batch_list Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 08/41] scsi: scsi_transport_iscsi: fix the issue that iscsi_if_rx doesnt parse nlmsg properly Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 09/41] crypto: talitos - Dont provide setkey for non hmac hashing algs Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 10/41] crypto: talitos - fix sha224 Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 11/41] KEYS: fix writing past end of user-supplied buffer in keyring_read() Greg Kroah-Hartman
2017-10-16 15:47   ` Ben Hutchings
2017-10-16 18:12     ` Eric Biggers
2017-10-19 15:27     ` David Howells
2017-10-19 17:09       ` Eric Biggers
2017-10-24 23:19       ` Eric Biggers
2017-10-25  9:31         ` Ben Hutchings
2017-11-01 15:24         ` David Howells
2017-10-03 12:21 ` Greg Kroah-Hartman [this message]
2017-10-03 12:21 ` [PATCH 4.4 13/41] KEYS: prevent KEYCTL_READ on negative key Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 14/41] powerpc/pseries: Fix parent_dn reference leak in add_dt_node() Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 15/41] Fix SMB3.1.1 guest authentication to Samba Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 16/41] SMB: Validate negotiate (to protect against downgrade) even if signing off Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 17/41] SMB3: Dont ignore O_SYNC/O_DSYNC and O_DIRECT flags Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 18/41] vfs: Return -ENXIO for negative SEEK_HOLE / SEEK_DATA offsets Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 19/41] nl80211: check for the required netlink attributes presence Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 20/41] bsg-lib: dont free job in bsg_prepare_job Greg Kroah-Hartman
2017-10-16 16:32   ` Ben Hutchings
2017-10-03 12:21 ` [PATCH 4.4 21/41] seccomp: fix the usage of get/put_seccomp_filter() in seccomp_get_filter() Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 22/41] arm64: Make sure SPsel is always set Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 23/41] arm64: fault: Route pte translation faults via do_translation_fault Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 25/41] kvm: nVMX: Dont allow L2 to access the hardware CR8 Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 26/41] PCI: Fix race condition with driver_override Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 27/41] btrfs: fix NULL pointer dereference from free_reloc_roots() Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 28/41] btrfs: propagate error to btrfs_cmp_data_prepare caller Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 29/41] btrfs: prevent to set invalid default subvolid Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 30/41] x86/fpu: Dont let userspace set bogus xcomp_bv Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 31/41] gfs2: Fix debugfs glocks dump Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 32/41] timer/sysclt: Restrict timer migration sysctl values to 0 and 1 Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 35/41] cxl: Fix driver use count Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 36/41] dmaengine: mmp-pdma: add number of requestors Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 37/41] ARM: pxa: add the number of DMA requestor lines Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 38/41] ARM: pxa: fix " Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 39/41] KVM: VMX: use cmpxchg64 Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 40/41] video: fbdev: aty: do not leak uninitialized padding in clk to userspace Greg Kroah-Hartman
2017-10-03 12:21 ` [PATCH 4.4 41/41] swiotlb-xen: implement xen_swiotlb_dma_mmap callback Greg Kroah-Hartman
2017-10-03 19:26 ` [PATCH 4.4 00/41] 4.4.90-stable review Shuah Khan
2017-10-03 20:30 ` Tom Gall
2017-10-04  7:55   ` Greg Kroah-Hartman
2017-10-04  8:29     ` Sumit Semwal
2017-10-03 20:41 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171003114220.691599070@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=dhowells@redhat.com \
    --cc=ebiggers@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).