nfsd4: kill unneeded cl_confirm check
[safe/jmp/linux-2.6] / kernel / signal.c
index 39d1227..4333b6d 100644 (file)
@@ -55,7 +55,7 @@ static int sig_ignored(struct task_struct *t, int sig)
         * signal handler may change by the time it is
         * unblocked.
         */
-       if (sigismember(&t->blocked, sig))
+       if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
                return 0;
 
        /* Is it explicitly or implicitly ignored? */
@@ -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);
@@ -125,7 +124,7 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-       if (!recalc_sigpending_tsk(current))
+       if (!recalc_sigpending_tsk(current) && !freezing(current))
                clear_thread_flag(TIF_SIGPENDING);
 
 }
@@ -255,6 +254,16 @@ flush_signal_handlers(struct task_struct *t, int force_default)
        }
 }
 
+int unhandled_signal(struct task_struct *tsk, int sig)
+{
+       if (is_global_init(tsk))
+               return 1;
+       if (tsk->ptrace & PT_PTRACED)
+               return 0;
+       return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
+               (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
+}
+
 
 /* Notify the system that a driver wants to block all signals for this
  * process, and wants to be notified if any signals at all were to be
@@ -368,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 (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);
@@ -397,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
@@ -415,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 &&
+       if (signr &&
             ((info->si_code & __SI_MASK) == __SI_TIMER) &&
             info->si_sys_private){
                /*
@@ -449,15 +456,15 @@ void signal_wake_up(struct task_struct *t, int resume)
        set_tsk_thread_flag(t, TIF_SIGPENDING);
 
        /*
-        * For SIGKILL, we want to wake it up in the stopped/traced case.
-        * We don't check t->state here because there is a race with it
+        * For SIGKILL, we want to wake it up in the stopped/traced/killable
+        * case. We don't check t->state here because there is a race with it
         * executing another processor and just now entering stopped state.
         * By using wake_up_state, we ensure the process will wake up and
         * handle its death signal.
         */
        mask = TASK_INTERRUPTIBLE;
        if (resume)
-               mask |= TASK_STOPPED | TASK_TRACED;
+               mask |= TASK_WAKEKILL;
        if (!wake_up_state(t, mask))
                kick_process(t);
 }
@@ -523,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);
 }
@@ -613,7 +620,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
                         * Wake up the stopped thread _after_ setting
                         * TIF_SIGPENDING
                         */
-                       state = TASK_STOPPED;
+                       state = __TASK_STOPPED;
                        if (sig_user_defined(t, SIGCONT) && !sigismember(&t->blocked, SIGCONT)) {
                                set_tsk_thread_flag(t, TIF_SIGPENDING);
                                state |= TASK_INTERRUPTIBLE;
@@ -687,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:
@@ -723,16 +730,16 @@ 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__
-       printk("code at %08lx: ", regs->eip);
+#if defined(__i386__) && !defined(__arch_um__)
+       printk("code at %08lx: ", regs->ip);
        {
                int i;
                for (i = 0; i < 16; i++) {
                        unsigned char insn;
 
-                       __get_user(insn, (unsigned char *)(regs->eip + i));
+                       __get_user(insn, (unsigned char *)(regs->ip + i));
                        printk("%02x ", insn);
                }
        }
@@ -831,7 +838,7 @@ static inline int wants_signal(int sig, struct task_struct *p)
                return 0;
        if (sig == SIGKILL)
                return 1;
-       if (p->state & (TASK_STOPPED | TASK_TRACED))
+       if (task_is_stopped_or_traced(p))
                return 0;
        return task_curr(p) || !signal_pending(p);
 }
@@ -901,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;
                }
 
@@ -920,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;
        }
 
@@ -977,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
@@ -993,6 +994,12 @@ void zap_other_threads(struct task_struct *p)
        }
 }
 
+int fastcall __fatal_signal_pending(struct task_struct *tsk)
+{
+       return sigismember(&tsk->pending.signal, SIGKILL);
+}
+EXPORT_SYMBOL(__fatal_signal_pending);
+
 /*
  * Must be called under rcu_read_lock() or with tasklist_lock read-held.
  */
@@ -1088,7 +1095,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;
 }
@@ -1149,7 +1156,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)
@@ -1159,9 +1166,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;
@@ -1265,7 +1272,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;
 }
 
 /*
@@ -1290,20 +1302,19 @@ struct sigqueue *sigqueue_alloc(void)
 void sigqueue_free(struct sigqueue *q)
 {
        unsigned long flags;
+       spinlock_t *lock = &current->sighand->siglock;
+
        BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
        /*
         * If the signal is still pending remove it from the
-        * pending queue.
+        * pending queue. We must hold ->siglock while testing
+        * q->list to serialize with collect_signal().
         */
-       if (unlikely(!list_empty(&q->list))) {
-               spinlock_t *lock = &current->sighand->siglock;
-               read_lock(&tasklist_lock);
-               spin_lock_irqsave(lock, flags);
-               if (!list_empty(&q->list))
-                       list_del_init(&q->list);
-               spin_unlock_irqrestore(lock, flags);
-               read_unlock(&tasklist_lock);
-       }
+       spin_lock_irqsave(lock, flags);
+       if (!list_empty(&q->list))
+               list_del_init(&q->list);
+       spin_unlock_irqrestore(lock, flags);
+
        q->flags &= ~SIGQUEUE_PREALLOC;
        __sigqueue_free(q);
 }
@@ -1436,14 +1447,29 @@ void do_notify_parent(struct task_struct *tsk, int sig)
        BUG_ON(sig == -1);
 
        /* do_notify_parent_cldstop should have been called instead.  */
-       BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
+       BUG_ON(task_is_stopped_or_traced(tsk));
 
        BUG_ON(!tsk->ptrace &&
               (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
        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. */
@@ -1508,7 +1534,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. */
@@ -1551,10 +1583,6 @@ static inline int may_ptrace_stop(void)
                    (current->ptrace & PT_ATTACHED)))
                return 0;
 
-       if (unlikely(current->signal == current->parent->signal) &&
-           unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))
-               return 0;
-
        /*
         * Are we in the middle of do_coredump?
         * If so and our tracer is also part of the coredump stopping
@@ -1638,7 +1666,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.  */
@@ -1707,7 +1735,7 @@ static int do_signal_stop(int signr)
                         * so this check has no races.
                         */
                        if (!t->exit_state &&
-                           !(t->state & (TASK_STOPPED|TASK_TRACED))) {
+                           !task_is_stopped_or_traced(t)) {
                                stop_count++;
                                signal_wake_up(t, 0);
                        }
@@ -1808,7 +1836,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;
                        }
 
@@ -1839,11 +1867,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)) {
@@ -2197,7 +2223,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);
@@ -2213,12 +2239,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
@@ -2297,15 +2323,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;
 
@@ -2332,7 +2349,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);
                }