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 3.18 03/47] KEYS: fix keyctl_set_reqkey_keyring() to not leak thread keyrings
Date: Fri, 28 Apr 2017 10:32:16 +0200	[thread overview]
Message-ID: <20170428083038.474605317@linuxfoundation.org> (raw)
In-Reply-To: <20170428083038.327543269@linuxfoundation.org>

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

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

From: Eric Biggers <ebiggers@google.com>

commit c9f838d104fed6f2f61d68164712e3204bf5271b upstream.

This fixes CVE-2017-7472.

Running the following program as an unprivileged user exhausts kernel
memory by leaking thread keyrings:

	#include <keyutils.h>

	int main()
	{
		for (;;)
			keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_THREAD_KEYRING);
	}

Fix it by only creating a new thread keyring if there wasn't one before.
To make things more consistent, make install_thread_keyring_to_cred()
and install_process_keyring_to_cred() both return 0 if the corresponding
keyring is already present.

Fixes: d84f4f992cbd ("CRED: Inaugurate COW credentials")
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>

---
 security/keys/keyctl.c       |   11 +++-------
 security/keys/process_keys.c |   44 ++++++++++++++++++++++++++-----------------
 2 files changed, 31 insertions(+), 24 deletions(-)

--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1258,8 +1258,8 @@ error:
  * Read or set the default keyring in which request_key() will cache keys and
  * return the old setting.
  *
- * If a process keyring is specified then this will be created if it doesn't
- * yet exist.  The old setting will be returned if successful.
+ * If a thread or process keyring is specified then it will be created if it
+ * doesn't yet exist.  The old setting will be returned if successful.
  */
 long keyctl_set_reqkey_keyring(int reqkey_defl)
 {
@@ -1284,11 +1284,8 @@ long keyctl_set_reqkey_keyring(int reqke
 
 	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
 		ret = install_process_keyring_to_cred(new);
-		if (ret < 0) {
-			if (ret != -EEXIST)
-				goto error;
-			ret = 0;
-		}
+		if (ret < 0)
+			goto error;
 		goto set;
 
 	case KEY_REQKEY_DEFL_DEFAULT:
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -125,13 +125,18 @@ error:
 }
 
 /*
- * Install a fresh thread keyring directly to new credentials.  This keyring is
- * allowed to overrun the quota.
+ * Install a thread keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 int install_thread_keyring_to_cred(struct cred *new)
 {
 	struct key *keyring;
 
+	if (new->thread_keyring)
+		return 0;
+
 	keyring = keyring_alloc("_tid", new->uid, new->gid, new,
 				KEY_POS_ALL | KEY_USR_VIEW,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
@@ -143,7 +148,9 @@ int install_thread_keyring_to_cred(struc
 }
 
 /*
- * Install a fresh thread keyring, discarding the old one.
+ * Install a thread keyring to the current task if it didn't have one already.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 static int install_thread_keyring(void)
 {
@@ -154,8 +161,6 @@ static int install_thread_keyring(void)
 	if (!new)
 		return -ENOMEM;
 
-	BUG_ON(new->thread_keyring);
-
 	ret = install_thread_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
@@ -166,17 +171,17 @@ static int install_thread_keyring(void)
 }
 
 /*
- * Install a process keyring directly to a credentials struct.
+ * Install a process keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
  *
- * Returns -EEXIST if there was already a process keyring, 0 if one installed,
- * and other value on any other error
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 int install_process_keyring_to_cred(struct cred *new)
 {
 	struct key *keyring;
 
 	if (new->process_keyring)
-		return -EEXIST;
+		return 0;
 
 	keyring = keyring_alloc("_pid", new->uid, new->gid, new,
 				KEY_POS_ALL | KEY_USR_VIEW,
@@ -189,11 +194,9 @@ int install_process_keyring_to_cred(stru
 }
 
 /*
- * Make sure a process keyring is installed for the current process.  The
- * existing process keyring is not replaced.
+ * Install a process keyring to the current task if it didn't have one already.
  *
- * Returns 0 if there is a process keyring by the end of this function, some
- * error otherwise.
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 static int install_process_keyring(void)
 {
@@ -207,14 +210,18 @@ static int install_process_keyring(void)
 	ret = install_process_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
-		return ret != -EEXIST ? ret : 0;
+		return ret;
 	}
 
 	return commit_creds(new);
 }
 
 /*
- * Install a session keyring directly to a credentials struct.
+ * Install the given keyring as the session keyring of the given credentials
+ * struct, replacing the existing one if any.  If the given keyring is NULL,
+ * then install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
 {
@@ -249,8 +256,11 @@ int install_session_keyring_to_cred(stru
 }
 
 /*
- * Install a session keyring, discarding the old one.  If a keyring is not
- * supplied, an empty one is invented.
+ * Install the given keyring as the session keyring of the current task,
+ * replacing the existing one if any.  If the given keyring is NULL, then
+ * install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 static int install_session_keyring(struct key *keyring)
 {

  parent reply	other threads:[~2017-04-28  8:46 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-28  8:32 [PATCH 3.18 00/47] 3.18.51-stable review Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 01/47] KEYS: Disallow keyrings beginning with . to be joined as session keyrings Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 02/47] KEYS: Change the name of the dead type to ".dead" to prevent user access Greg Kroah-Hartman
2017-04-28  8:32 ` Greg Kroah-Hartman [this message]
2017-04-28  8:32 ` [PATCH 3.18 04/47] tracing: Allocate the snapshot buffer before enabling probe Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 05/47] ring-buffer: Have ring_buffer_iter_empty() return true when empty Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 06/47] cifs: Do not send echoes before Negotiate is complete Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 07/47] CIFS: remove bad_network_name flag Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 08/47] s390/mm: fix CMMA vs KSM vs others Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 09/47] Input: elantech - add Fujitsu Lifebook E547 to force crc_enabled Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 10/47] ACPI / power: Avoid maybe-uninitialized warning Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 11/47] mmc: sdhci-esdhc-imx: increase the pad I/O drive strength for DDR50 card Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 12/47] ubi/upd: Always flush after prepared for an update Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 13/47] powerpc/kprobe: Fix oops when kprobed on stdu instruction Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 14/47] x86/mce/AMD: Give a name to MCA bank 3 when accessed with legacy MSRs Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 15/47] kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 16/47] arm64: avoid returning from bad_mode Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 17/47] clk: at91: usb: fix determine_rate prototype again Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 18/47] gadgetfs: fix uninitialized variable in error handling Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 19/47] dm bufio: hide bogus warning Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 20/47] MIPS: Fix the build on jz4740 after removing the custom gpio.h Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 21/47] perf: Avoid horrible stack usage Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 22/47] fs/nfs: fix new compiler warning about boolean in switch Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 23/47] iommu/vt-d: Remove unused variable Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 24/47] mm/init: fix zone boundary creation Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 25/47] net: ti: cpmac: Fix compiler warning due to type confusion Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 26/47] MIPS: asm: compiler: Add new macros to set ISA and arch asm annotations Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 27/47] nfsd: work around a gcc-5.1 warning Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 29/47] brcmfmac: avoid " Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 30/47] tty: nozomi: avoid a harmless gcc warning Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 31/47] net: vxge: avoid unused function warnings Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 33/47] hostap: avoid uninitialized variable use in hfa384x_get_rid Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 34/47] MIPS: MSP71xx: remove odd locking in PCI config space access code Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 35/47] net: tulip: turn compile-time warning into dev_warn() Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 37/47] gfs2: avoid uninitialized variable warning Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 39/47] ARM: 8296/1: cache-l2x0: clean up aurora cache handling Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 40/47] aic94xx: Skip reading user settings if flash is not found Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 41/47] MIPS: ralink: Cosmetic change to prom_init() Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 42/47] kconfig: tinyconfig: provide whole choice blocks to avoid warnings Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 43/47] ARM: 8383/1: nommu: avoid deprecated source register on mov Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 44/47] [media] xc2028: avoid use after free Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 45/47] vfio/pci: Fix integer overflows, bitmask check Greg Kroah-Hartman
2017-04-28  8:32 ` [PATCH 3.18 46/47] staging/android/ion : fix a race condition in the ion driver Greg Kroah-Hartman
2017-04-28  8:33 ` [PATCH 3.18 47/47] ping: implement proper locking Greg Kroah-Hartman
2017-04-28 18:12 ` [PATCH 3.18 00/47] 3.18.51-stable review Guenter Roeck
2017-04-28 19:19 ` Shuah Khan

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=20170428083038.474605317@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).