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