[patch 7/9] signals: Fix more rcu assumptions

Thomas Gleixner
2009-12-10T00:54:49Z

[-- Attachment #1: signal-fix-more-rcu-assumptions.patch --]
[-- Type: text/plain, Size: 1830 bytes --]

1) Remove the misleading comment in __sigqueue_alloc() which claims
that holding a spinlock is equivalent to rcu_read_lock().

2) Wrap the __send_signal() call in send_signal() into a rcu read side
critical section to guarantee that the __sigqueue_alloc()
requirement is met in any case.

This needs to be revisited to remove the remaining users of
read_lock(&tasklist_lock) but that's outside the scope of this patch.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
---
kernel/signal.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

Index: linux-2.6-tip/kernel/signal.c
===================================================================
--- linux-2.6-tip.orig/kernel/signal.c
+++ linux-2.6-tip/kernel/signal.c
@@ -220,8 +220,7 @@ __sigqueue_alloc(int sig, struct task_st
/*
* We won't get problems with the target's UID changing under us
* because changing it requires RCU be used, and if t != current, the
- * caller must be holding the RCU readlock (by way of a spinlock) and
- * we use RCU protection here
+ * caller must be holding the RCU readlock.
*/
user = get_uid(__task_cred(t)->user);
atomic_inc(&user->sigpending);
@@ -946,7 +945,7 @@ out_set:
static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
int group)
{
- int from_ancestor_ns = 0;
+ int ret, from_ancestor_ns = 0;

#ifdef CONFIG_PID_NS
if (!is_si_special(info) && SI_FROMUSER(info) &&
@@ -954,7 +953,11 @@ static int send_signal(int sig, struct s
from_ancestor_ns = 1;
#endif

- return __send_signal(sig, info, t, group, from_ancestor_ns);
+ rcu_read_lock();
+ ret = __send_signal(sig, info, t, group, from_ancestor_ns);
+ rcu_read_unlock();
+
+ return ret;
}

static void print_fatal_signal(struct pt_regs *regs, int signr)