Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt
[pandora-kernel.git] / kernel / signal.c
index 3169bed..4537bdd 100644 (file)
@@ -99,7 +99,6 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
 static int recalc_sigpending_tsk(struct task_struct *t)
 {
        if (t->signal->group_stop_count > 0 ||
-           (freezing(t)) ||
            PENDING(&t->pending, &t->blocked) ||
            PENDING(&t->signal->shared_pending, &t->blocked)) {
                set_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -257,7 +256,7 @@ flush_signal_handlers(struct task_struct *t, int force_default)
 
 int unhandled_signal(struct task_struct *tsk, int sig)
 {
-       if (is_init(tsk))
+       if (is_global_init(tsk))
                return 1;
        if (tsk->ptrace & PT_PTRACED)
                return 0;
@@ -378,8 +377,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
         */
-       if (likely(tsk == current))
-               signr = __dequeue_signal(&tsk->pending, mask, info);
+       signr = __dequeue_signal(&tsk->pending, mask, info);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
                                         mask, info);
@@ -407,8 +405,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                        }
                }
        }
-       if (likely(tsk == current))
-               recalc_sigpending();
+       recalc_sigpending();
        if (signr && unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
@@ -425,7 +422,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
                        tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
        }
-       if (signr && likely(tsk == current) &&
+       if (signr &&
             ((info->si_code & __SI_MASK) == __SI_TIMER) &&
             info->si_sys_private){
                /*
@@ -533,18 +530,18 @@ static int check_kill_permission(int sig, struct siginfo *info,
        if (!valid_signal(sig))
                return error;
 
-       error = audit_signal_info(sig, t); /* Let audit system see the signal */
-       if (error)
-               return error;
-
-       error = -EPERM;
-       if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
-           && ((sig != SIGCONT) ||
-               (process_session(current) != process_session(t)))
-           && (current->euid ^ t->suid) && (current->euid ^ t->uid)
-           && (current->uid ^ t->suid) && (current->uid ^ t->uid)
-           && !capable(CAP_KILL))
+       if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) {
+               error = audit_signal_info(sig, t); /* Let audit system see the signal */
+               if (error)
+                       return error;
+               error = -EPERM;
+               if (((sig != SIGCONT) ||
+                       (task_session_nr(current) != task_session_nr(t)))
+                   && (current->euid ^ t->suid) && (current->euid ^ t->uid)
+                   && (current->uid ^ t->suid) && (current->uid ^ t->uid)
+                   && !capable(CAP_KILL))
                return error;
+       }
 
        return security_task_kill(t, info, sig, 0);
 }
@@ -697,7 +694,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        q->info.si_signo = sig;
                        q->info.si_errno = 0;
                        q->info.si_code = SI_USER;
-                       q->info.si_pid = current->pid;
+                       q->info.si_pid = task_pid_vnr(current);
                        q->info.si_uid = current->uid;
                        break;
                case (unsigned long) SEND_SIG_PRIV:
@@ -733,9 +730,9 @@ int print_fatal_signals;
 static void print_fatal_signal(struct pt_regs *regs, int signr)
 {
        printk("%s/%d: potentially unexpected fatal signal %d.\n",
-               current->comm, current->pid, signr);
+               current->comm, task_pid_nr(current), signr);
 
-#ifdef __i386__
+#if defined(__i386__) && !defined(__arch_um__)
        printk("code at %08lx: ", regs->eip);
        {
                int i;
@@ -911,8 +908,7 @@ __group_complete_signal(int sig, struct task_struct *p)
                        do {
                                sigaddset(&t->pending.signal, SIGKILL);
                                signal_wake_up(t, 1);
-                               t = next_thread(t);
-                       } while (t != p);
+                       } while_each_thread(p, t);
                        return;
                }
 
@@ -930,13 +926,11 @@ __group_complete_signal(int sig, struct task_struct *p)
                rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
                p->signal->group_stop_count = 0;
                p->signal->group_exit_task = t;
-               t = p;
+               p = t;
                do {
                        p->signal->group_stop_count++;
-                       signal_wake_up(t, 0);
-                       t = next_thread(t);
-               } while (t != p);
-               wake_up_process(p->signal->group_exit_task);
+                       signal_wake_up(t, t == p);
+               } while_each_thread(p, t);
                return;
        }
 
@@ -987,9 +981,6 @@ void zap_other_threads(struct task_struct *p)
        p->signal->flags = SIGNAL_GROUP_EXIT;
        p->signal->group_stop_count = 0;
 
-       if (thread_group_empty(p))
-               return;
-
        for (t = next_thread(p); t != p; t = next_thread(t)) {
                /*
                 * Don't bother with already dead threads
@@ -1098,7 +1089,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
 {
        int error;
        rcu_read_lock();
-       error = kill_pid_info(sig, info, find_pid(pid));
+       error = kill_pid_info(sig, info, find_vpid(pid));
        rcu_read_unlock();
        return error;
 }
@@ -1159,7 +1150,7 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
 
                read_lock(&tasklist_lock);
                for_each_process(p) {
-                       if (p->pid > 1 && p->tgid != current->tgid) {
+                       if (p->pid > 1 && !same_thread_group(p, current)) {
                                int err = group_send_sig_info(sig, info, p);
                                ++count;
                                if (err != -EPERM)
@@ -1169,9 +1160,9 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
                read_unlock(&tasklist_lock);
                ret = count ? retval : -ESRCH;
        } else if (pid < 0) {
-               ret = kill_pgrp_info(sig, info, find_pid(-pid));
+               ret = kill_pgrp_info(sig, info, find_vpid(-pid));
        } else {
-               ret = kill_pid_info(sig, info, find_pid(pid));
+               ret = kill_pid_info(sig, info, find_vpid(pid));
        }
        rcu_read_unlock();
        return ret;
@@ -1275,7 +1266,12 @@ EXPORT_SYMBOL(kill_pid);
 int
 kill_proc(pid_t pid, int sig, int priv)
 {
-       return kill_proc_info(sig, __si_special(priv), pid);
+       int ret;
+
+       rcu_read_lock();
+       ret = kill_pid_info(sig, __si_special(priv), find_pid(pid));
+       rcu_read_unlock();
+       return ret;
 }
 
 /*
@@ -1452,7 +1448,22 @@ void do_notify_parent(struct task_struct *tsk, int sig)
 
        info.si_signo = sig;
        info.si_errno = 0;
-       info.si_pid = tsk->pid;
+       /*
+        * we are under tasklist_lock here so our parent is tied to
+        * us and cannot exit and release its namespace.
+        *
+        * the only it can is to switch its nsproxy with sys_unshare,
+        * bu uncharing pid namespaces is not allowed, so we'll always
+        * see relevant namespace
+        *
+        * write_lock() currently calls preempt_disable() which is the
+        * same as rcu_read_lock(), but according to Oleg, this is not
+        * correct to rely on this
+        */
+       rcu_read_lock();
+       info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+       rcu_read_unlock();
+
        info.si_uid = tsk->uid;
 
        /* FIXME: find out whether or not this is supposed to be c*time. */
@@ -1517,7 +1528,13 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
 
        info.si_signo = SIGCHLD;
        info.si_errno = 0;
-       info.si_pid = tsk->pid;
+       /*
+        * see comment in do_notify_parent() abot the following 3 lines
+        */
+       rcu_read_lock();
+       info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+       rcu_read_unlock();
+
        info.si_uid = tsk->uid;
 
        /* FIXME: find out whether or not this is supposed to be c*time. */
@@ -1643,7 +1660,7 @@ void ptrace_notify(int exit_code)
        memset(&info, 0, sizeof info);
        info.si_signo = SIGTRAP;
        info.si_code = exit_code;
-       info.si_pid = current->pid;
+       info.si_pid = task_pid_vnr(current);
        info.si_uid = current->uid;
 
        /* Let the debugger run.  */
@@ -1813,7 +1830,7 @@ relock:
                                info->si_signo = signr;
                                info->si_errno = 0;
                                info->si_code = SI_USER;
-                               info->si_pid = current->parent->pid;
+                               info->si_pid = task_pid_vnr(current->parent);
                                info->si_uid = current->parent->uid;
                        }
 
@@ -1844,11 +1861,9 @@ relock:
                        continue;
 
                /*
-                * Init of a pid space gets no signals it doesn't want from
-                * within that pid space. It can of course get signals from
-                * its parent pid space.
+                * Global init gets no signals it doesn't want.
                 */
-               if (current == child_reaper(current))
+               if (is_global_init(current))
                        continue;
 
                if (sig_kernel_stop(signr)) {
@@ -2202,7 +2217,7 @@ sys_kill(int pid, int sig)
        info.si_signo = sig;
        info.si_errno = 0;
        info.si_code = SI_USER;
-       info.si_pid = current->tgid;
+       info.si_pid = task_tgid_vnr(current);
        info.si_uid = current->uid;
 
        return kill_something_info(sig, &info, pid);
@@ -2218,12 +2233,12 @@ static int do_tkill(int tgid, int pid, int sig)
        info.si_signo = sig;
        info.si_errno = 0;
        info.si_code = SI_TKILL;
-       info.si_pid = current->tgid;
+       info.si_pid = task_tgid_vnr(current);
        info.si_uid = current->uid;
 
        read_lock(&tasklist_lock);
-       p = find_task_by_pid(pid);
-       if (p && (tgid <= 0 || p->tgid == tgid)) {
+       p = find_task_by_vpid(pid);
+       if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
                error = check_kill_permission(sig, &info, p);
                /*
                 * The null signal is a permissions and process existence
@@ -2302,15 +2317,6 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
        k = &current->sighand->action[sig-1];
 
        spin_lock_irq(&current->sighand->siglock);
-       if (signal_pending(current)) {
-               /*
-                * If there might be a fatal signal pending on multiple
-                * threads, make sure we take it before changing the action.
-                */
-               spin_unlock_irq(&current->sighand->siglock);
-               return -ERESTARTNOINTR;
-       }
-
        if (oact)
                *oact = *k;
 
@@ -2337,7 +2343,6 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
                        rm_from_queue_full(&mask, &t->signal->shared_pending);
                        do {
                                rm_from_queue_full(&mask, &t->pending);
-                               recalc_sigpending_and_wake(t);
                                t = next_thread(t);
                        } while (t != current);
                }