diff options
author | David Howells <dhowells@redhat.com> | 2010-08-04 11:59:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-04 14:17:10 -0400 |
commit | 694f690d27dadccc8cb9d90532e76593b61fe098 (patch) | |
tree | ea641e53ae530d0d3708fbfcab8109cc5e840d21 /kernel/signal.c | |
parent | e75aa85892b2ee78c79edac720868cbef16e62eb (diff) |
CRED: Fix RCU warning due to previous patch fixing __task_cred()'s checks
Commit 8f92054e7ca1 ("CRED: Fix __task_cred()'s lockdep check and banner
comment") fixed the lockdep checks on __task_cred(). This has shown up
a place in the signalling code where a lock should be held - namely that
check_kill_permission() requires its callers to hold the RCU lock.
Fix group_send_sig_info() to get the RCU read lock around its call to
check_kill_permission().
Without this patch, the following warning can occur:
===================================================
[ INFO: suspicious rcu_dereference_check() usage. ]
---------------------------------------------------
kernel/signal.c:660 invoked rcu_dereference_check() without protection!
...
Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 906ae5a1779c..bded65187780 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -637,7 +637,7 @@ static inline bool si_fromuser(const struct siginfo *info) | |||
637 | 637 | ||
638 | /* | 638 | /* |
639 | * Bad permissions for sending the signal | 639 | * Bad permissions for sending the signal |
640 | * - the caller must hold at least the RCU read lock | 640 | * - the caller must hold the RCU read lock |
641 | */ | 641 | */ |
642 | static int check_kill_permission(int sig, struct siginfo *info, | 642 | static int check_kill_permission(int sig, struct siginfo *info, |
643 | struct task_struct *t) | 643 | struct task_struct *t) |
@@ -1127,11 +1127,14 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long | |||
1127 | 1127 | ||
1128 | /* | 1128 | /* |
1129 | * send signal info to all the members of a group | 1129 | * send signal info to all the members of a group |
1130 | * - the caller must hold the RCU read lock at least | ||
1131 | */ | 1130 | */ |
1132 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | 1131 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) |
1133 | { | 1132 | { |
1134 | int ret = check_kill_permission(sig, info, p); | 1133 | int ret; |
1134 | |||
1135 | rcu_read_lock(); | ||
1136 | ret = check_kill_permission(sig, info, p); | ||
1137 | rcu_read_unlock(); | ||
1135 | 1138 | ||
1136 | if (!ret && sig) | 1139 | if (!ret && sig) |
1137 | ret = do_send_sig_info(sig, info, p, true); | 1140 | ret = do_send_sig_info(sig, info, p, true); |