| From 3d96406c7da1ed5811ea52a3b0905f4f0e295376 Mon Sep 17 00:00:00 2001 |
| From: David Howells <dhowells@redhat.com> |
| Date: Fri, 10 Sep 2010 09:59:51 +0100 |
| Subject: KEYS: Fix bug in keyctl_session_to_parent() if parent has no session keyring |
| |
| From: David Howells <dhowells@redhat.com> |
| |
| commit 3d96406c7da1ed5811ea52a3b0905f4f0e295376 upstream. |
| |
| Fix a bug in keyctl_session_to_parent() whereby it tries to check the ownership |
| of the parent process's session keyring whether or not the parent has a session |
| keyring [CVE-2010-2960]. |
| |
| This results in the following oops: |
| |
| BUG: unable to handle kernel NULL pointer dereference at 00000000000000a0 |
| IP: [<ffffffff811ae4dd>] keyctl_session_to_parent+0x251/0x443 |
| ... |
| Call Trace: |
| [<ffffffff811ae2f3>] ? keyctl_session_to_parent+0x67/0x443 |
| [<ffffffff8109d286>] ? __do_fault+0x24b/0x3d0 |
| [<ffffffff811af98c>] sys_keyctl+0xb4/0xb8 |
| [<ffffffff81001eab>] system_call_fastpath+0x16/0x1b |
| |
| if the parent process has no session keyring. |
| |
| If the system is using pam_keyinit then it mostly protected against this as all |
| processes derived from a login will have inherited the session keyring created |
| by pam_keyinit during the log in procedure. |
| |
| To test this, pam_keyinit calls need to be commented out in /etc/pam.d/. |
| |
| Reported-by: Tavis Ormandy <taviso@cmpxchg8b.com> |
| Signed-off-by: David Howells <dhowells@redhat.com> |
| Acked-by: Tavis Ormandy <taviso@cmpxchg8b.com> |
| Cc: dann frazier <dannf@debian.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| security/keys/keyctl.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/security/keys/keyctl.c |
| +++ b/security/keys/keyctl.c |
| @@ -1292,7 +1292,8 @@ long keyctl_session_to_parent(void) |
| goto not_permitted; |
| |
| /* the keyrings must have the same UID */ |
| - if (pcred ->tgcred->session_keyring->uid != mycred->euid || |
| + if ((pcred->tgcred->session_keyring && |
| + pcred->tgcred->session_keyring->uid != mycred->euid) || |
| mycred->tgcred->session_keyring->uid != mycred->euid) |
| goto not_permitted; |
| |