Chuck Ebbert a4789ad
From: David Howells <dhowells@redhat.com>
Chuck Ebbert a4789ad
Date: Fri, 10 Sep 2010 08:59:46 +0000 (+0100)
Chuck Ebbert a4789ad
Subject: KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
Chuck Ebbert a4789ad
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9d1ac65a9698513d00e5608d93fca0c53f536c14
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
There's an protected access to the parent process's credentials in the middle
Chuck Ebbert a4789ad
of keyctl_session_to_parent().  This results in the following RCU warning:
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
  ===================================================
Chuck Ebbert a4789ad
  [ INFO: suspicious rcu_dereference_check() usage. ]
Chuck Ebbert a4789ad
  ---------------------------------------------------
Chuck Ebbert a4789ad
  security/keys/keyctl.c:1291 invoked rcu_dereference_check() without protection!
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
  other info that might help us debug this:
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
  rcu_scheduler_active = 1, debug_locks = 0
Chuck Ebbert a4789ad
  1 lock held by keyctl-session-/2137:
Chuck Ebbert a4789ad
   #0:  (tasklist_lock){.+.+..}, at: [<ffffffff811ae2ec>] keyctl_session_to_parent+0x60/0x236
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
  stack backtrace:
Chuck Ebbert a4789ad
  Pid: 2137, comm: keyctl-session- Not tainted 2.6.36-rc2-cachefs+ #1
Chuck Ebbert a4789ad
  Call Trace:
Chuck Ebbert a4789ad
   [<ffffffff8105606a>] lockdep_rcu_dereference+0xaa/0xb3
Chuck Ebbert a4789ad
   [<ffffffff811ae379>] keyctl_session_to_parent+0xed/0x236
Chuck Ebbert a4789ad
   [<ffffffff811af77e>] sys_keyctl+0xb4/0xb6
Chuck Ebbert a4789ad
   [<ffffffff81001eab>] system_call_fastpath+0x16/0x1b
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
The code should take the RCU read lock to make sure the parents credentials
Chuck Ebbert a4789ad
don't go away, even though it's holding a spinlock and has IRQ disabled.
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
Signed-off-by: David Howells <dhowells@redhat.com>
Chuck Ebbert a4789ad
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Chuck Ebbert a4789ad
---
Chuck Ebbert a4789ad
Chuck Ebbert a4789ad
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
Chuck Ebbert a4789ad
index b2b0998..3868c67 100644
Chuck Ebbert a4789ad
--- a/security/keys/keyctl.c
Chuck Ebbert a4789ad
+++ b/security/keys/keyctl.c
Chuck Ebbert a4789ad
@@ -1272,6 +1272,7 @@ long keyctl_session_to_parent(void)
Chuck Ebbert a4789ad
 	keyring_r = NULL;
Chuck Ebbert a4789ad
 
Chuck Ebbert a4789ad
 	me = current;
Chuck Ebbert a4789ad
+	rcu_read_lock();
Chuck Ebbert a4789ad
 	write_lock_irq(&tasklist_lock);
Chuck Ebbert a4789ad
 
Chuck Ebbert a4789ad
 	parent = me->real_parent;
Chuck Ebbert a4789ad
@@ -1319,6 +1320,7 @@ long keyctl_session_to_parent(void)
Chuck Ebbert a4789ad
 	set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
Chuck Ebbert a4789ad
 
Chuck Ebbert a4789ad
 	write_unlock_irq(&tasklist_lock);
Chuck Ebbert a4789ad
+	rcu_read_unlock();
Chuck Ebbert a4789ad
 	if (oldcred)
Chuck Ebbert a4789ad
 		put_cred(oldcred);
Chuck Ebbert a4789ad
 	return 0;
Chuck Ebbert a4789ad
@@ -1327,6 +1329,7 @@ already_same:
Chuck Ebbert a4789ad
 	ret = 0;
Chuck Ebbert a4789ad
 not_permitted:
Chuck Ebbert a4789ad
 	write_unlock_irq(&tasklist_lock);
Chuck Ebbert a4789ad
+	rcu_read_unlock();
Chuck Ebbert a4789ad
 	put_cred(cred);
Chuck Ebbert a4789ad
 	return ret;
Chuck Ebbert a4789ad