mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] KEYS: Fix crash in GC
@ 2015-10-19 16:12 David Howells
  2015-10-19 16:12 ` [PATCH 1/2] KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring David Howells
  2015-10-19 16:13 ` [PATCH 2/2] KEYS: Don't permit request_key() to construct a new keyring David Howells
  0 siblings, 2 replies; 3+ messages in thread
From: David Howells @ 2015-10-19 16:12 UTC (permalink / raw)
  To: torvalds, jmorris
  Cc: linux-kernel, stable, dhowells, linux-security-module, keyrings, dvyukov


Hi James, Linus,

Here are two patches, the first of which at least should go upstream
immediately:

 (1) Prevent a user-triggerable crash in the keyrings destructor when a
     negatively instantiated keyring is garbage collected.  I have also seen
     this triggered for user type keys.

 (2) Prevent the user from using requesting that a keyring be created and
     instantiated through an upcall.  Doing so is probably safe since the
     keyring type ignores the arguments to its instantiation function - but we
     probably shouldn't let keyrings be created in this manner.

I'm okay with patch (2) being deferred to the next merge window if we're only
fixing security bugs at this time upstream.

The patches can be found here also:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-fixes

David
---
David Howells (2):
      KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring
      KEYS: Don't permit request_key() to construct a new keyring


 security/keys/gc.c          |    6 ++++--
 security/keys/request_key.c |    3 +++
 2 files changed, 7 insertions(+), 2 deletions(-)


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring
  2015-10-19 16:12 [PATCH 0/2] KEYS: Fix crash in GC David Howells
@ 2015-10-19 16:12 ` David Howells
  2015-10-19 16:13 ` [PATCH 2/2] KEYS: Don't permit request_key() to construct a new keyring David Howells
  1 sibling, 0 replies; 3+ messages in thread
From: David Howells @ 2015-10-19 16:12 UTC (permalink / raw)
  To: torvalds, jmorris
  Cc: linux-kernel, stable, dhowells, linux-security-module, keyrings, dvyukov

The following sequence of commands:

    i=`keyctl add user a a @s`
    keyctl request2 keyring foo bar @t
    keyctl unlink $i @s

tries to invoke an upcall to instantiate a keyring if one doesn't already
exist by that name within the user's keyring set.  However, if the upcall
fails, the code sets keyring->type_data.reject_error to -ENOKEY or some
other error code.  When the key is garbage collected, the key destroy
function is called unconditionally and keyring_destroy() uses list_empty()
on keyring->type_data.link - which is in a union with reject_error.
Subsequently, the kernel tries to unlink the keyring from the keyring names
list - which oopses like this:

	BUG: unable to handle kernel paging request at 00000000ffffff8a
	IP: [<ffffffff8126e051>] keyring_destroy+0x3d/0x88
	...
	Workqueue: events key_garbage_collector
	...
	RIP: 0010:[<ffffffff8126e051>] keyring_destroy+0x3d/0x88
	RSP: 0018:ffff88003e2f3d30  EFLAGS: 00010203
	RAX: 00000000ffffff82 RBX: ffff88003bf1a900 RCX: 0000000000000000
	RDX: 0000000000000000 RSI: 000000003bfc6901 RDI: ffffffff81a73a40
	RBP: ffff88003e2f3d38 R08: 0000000000000152 R09: 0000000000000000
	R10: ffff88003e2f3c18 R11: 000000000000865b R12: ffff88003bf1a900
	R13: 0000000000000000 R14: ffff88003bf1a908 R15: ffff88003e2f4000
	...
	CR2: 00000000ffffff8a CR3: 000000003e3ec000 CR4: 00000000000006f0
	...
	Call Trace:
	 [<ffffffff8126c756>] key_gc_unused_keys.constprop.1+0x5d/0x10f
	 [<ffffffff8126ca71>] key_garbage_collector+0x1fa/0x351
	 [<ffffffff8105ec9b>] process_one_work+0x28e/0x547
	 [<ffffffff8105fd17>] worker_thread+0x26e/0x361
	 [<ffffffff8105faa9>] ? rescuer_thread+0x2a8/0x2a8
	 [<ffffffff810648ad>] kthread+0xf3/0xfb
	 [<ffffffff810647ba>] ? kthread_create_on_node+0x1c2/0x1c2
	 [<ffffffff815f2ccf>] ret_from_fork+0x3f/0x70
	 [<ffffffff810647ba>] ? kthread_create_on_node+0x1c2/0x1c2

Note the value in RAX.  This is a 32-bit representation of -ENOKEY.

The solution is to only call ->destroy() if the key was successfully
instantiated.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
---

 security/keys/gc.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/security/keys/gc.c b/security/keys/gc.c
index 39eac1fd5706..addf060399e0 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -134,8 +134,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
 		kdebug("- %u", key->serial);
 		key_check(key);
 
-		/* Throw away the key data */
-		if (key->type->destroy)
+		/* Throw away the key data if the key is instantiated */
+		if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+		    !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+		    key->type->destroy)
 			key->type->destroy(key);
 
 		security_key_free(key);


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/2] KEYS: Don't permit request_key() to construct a new keyring
  2015-10-19 16:12 [PATCH 0/2] KEYS: Fix crash in GC David Howells
  2015-10-19 16:12 ` [PATCH 1/2] KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring David Howells
@ 2015-10-19 16:13 ` David Howells
  1 sibling, 0 replies; 3+ messages in thread
From: David Howells @ 2015-10-19 16:13 UTC (permalink / raw)
  To: torvalds, jmorris
  Cc: linux-kernel, stable, dhowells, linux-security-module, keyrings, dvyukov

If request_key() is used to find a keyring, only do the search part - don't
do the construction part if the keyring was not found by the search.  We
don't really want keyrings in the negative instantiated state since the
rejected/negative instantiation error value in the payload is unioned with
keyring metadata.

Now the kernel gives an error:

	request_key("keyring", "#selinux,bdekeyring", "keyring", KEY_SPEC_USER_SESSION_KEYRING) = -1 EPERM (Operation not permitted)

Signed-off-by: David Howells <dhowells@redhat.com>
---

 security/keys/request_key.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 486ef6fa393b..0d6253124278 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -440,6 +440,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
 
 	kenter("");
 
+	if (ctx->index_key.type == &key_type_keyring)
+		return ERR_PTR(-EPERM);
+	
 	user = key_user_lookup(current_fsuid());
 	if (!user)
 		return ERR_PTR(-ENOMEM);


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-10-19 16:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-19 16:12 [PATCH 0/2] KEYS: Fix crash in GC David Howells
2015-10-19 16:12 ` [PATCH 1/2] KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring David Howells
2015-10-19 16:13 ` [PATCH 2/2] KEYS: Don't permit request_key() to construct a new keyring David Howells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®