media: dw9807-vcm: Add regulator support to the driver
[platform/kernel/linux-rpi.git] / kernel / signal.c
index e661f88..0bbd89f 100644 (file)
@@ -1324,6 +1324,34 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t,
        struct k_sigaction *action;
        int sig = info->si_signo;
 
+       /*
+        * On some archs, PREEMPT_RT has to delay sending a signal from a trap
+        * since it can not enable preemption, and the signal code's spin_locks
+        * turn into mutexes. Instead, it must set TIF_NOTIFY_RESUME which will
+        * send the signal on exit of the trap.
+        */
+#ifdef ARCH_RT_DELAYS_SIGNAL_SEND
+       if (in_atomic()) {
+               struct task_struct *t = current;
+
+               if (WARN_ON_ONCE(t->forced_info.si_signo))
+                       return 0;
+
+               if (is_si_special(info)) {
+                       WARN_ON_ONCE(info != SEND_SIG_PRIV);
+                       t->forced_info.si_signo = info->si_signo;
+                       t->forced_info.si_errno = 0;
+                       t->forced_info.si_code = SI_KERNEL;
+                       t->forced_info.si_pid = 0;
+                       t->forced_info.si_uid = 0;
+               } else {
+                       t->forced_info = *info;
+               }
+
+               set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
+               return 0;
+       }
+#endif
        spin_lock_irqsave(&t->sighand->siglock, flags);
        action = &t->sighand->action[sig-1];
        ignored = action->sa.sa_handler == SIG_IGN;
@@ -1339,9 +1367,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t,
        }
        /*
         * Don't clear SIGNAL_UNKILLABLE for traced tasks, users won't expect
-        * debugging to leave init killable.
+        * debugging to leave init killable. But HANDLER_EXIT is always fatal.
         */
-       if (action->sa.sa_handler == SIG_DFL && !t->ptrace)
+       if (action->sa.sa_handler == SIG_DFL &&
+           (!t->ptrace || (handler == HANDLER_EXIT)))
                t->signal->flags &= ~SIGNAL_UNKILLABLE;
        ret = send_signal(sig, info, t, PIDTYPE_PID);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
@@ -1671,6 +1700,19 @@ void force_fatal_sig(int sig)
        force_sig_info_to_task(&info, current, HANDLER_SIG_DFL);
 }
 
+void force_exit_sig(int sig)
+{
+       struct kernel_siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_code = SI_KERNEL;
+       info.si_pid = 0;
+       info.si_uid = 0;
+       force_sig_info_to_task(&info, current, HANDLER_EXIT);
+}
+
 /*
  * When things go south during signal handling, we
  * will force a SIGSEGV. And if the signal that caused
@@ -1788,7 +1830,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 }
 #endif
 
-int force_sig_perf(void __user *addr, u32 type, u64 sig_data)
+int send_sig_perf(void __user *addr, u32 type, u64 sig_data)
 {
        struct kernel_siginfo info;
 
@@ -1800,7 +1842,18 @@ int force_sig_perf(void __user *addr, u32 type, u64 sig_data)
        info.si_perf_data = sig_data;
        info.si_perf_type = type;
 
-       return force_sig_info(&info);
+       /*
+        * Signals generated by perf events should not terminate the whole
+        * process if SIGTRAP is blocked, however, delivering the signal
+        * asynchronously is better than not delivering at all. But tell user
+        * space if the signal was asynchronous, so it can clearly be
+        * distinguished from normal synchronous ones.
+        */
+       info.si_perf_flags = sigismember(&current->blocked, info.si_signo) ?
+                                    TRAP_PERF_FLAG_ASYNC :
+                                    0;
+
+       return send_sig_info(info.si_signo, &info, current);
 }
 
 /**
@@ -2002,12 +2055,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
        bool autoreap = false;
        u64 utime, stime;
 
-       BUG_ON(sig == -1);
+       WARN_ON_ONCE(sig == -1);
 
-       /* do_notify_parent_cldstop should have been called instead.  */
-       BUG_ON(task_is_stopped_or_traced(tsk));
+       /* do_notify_parent_cldstop should have been called instead.  */
+       WARN_ON_ONCE(task_is_stopped_or_traced(tsk));
 
-       BUG_ON(!tsk->ptrace &&
+       WARN_ON_ONCE(!tsk->ptrace &&
               (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
        /* Wake up all pidfd waiters */
@@ -2283,16 +2336,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t
                if (gstop_done && ptrace_reparented(current))
                        do_notify_parent_cldstop(current, false, why);
 
-               /*
-                * Don't want to allow preemption here, because
-                * sys_ptrace() needs this task to be inactive.
-                *
-                * XXX: implement read_unlock_no_resched().
-                */
-               preempt_disable();
                read_unlock(&tasklist_lock);
                cgroup_enter_frozen();
-               preempt_enable_no_resched();
                freezable_schedule();
                cgroup_leave_frozen(true);
        } else {
@@ -2696,19 +2741,19 @@ relock:
                goto relock;
        }
 
-       /* Has this task already been marked for death? */
-       if (signal_group_exit(signal)) {
-               ksig->info.si_signo = signr = SIGKILL;
-               sigdelset(&current->pending.signal, SIGKILL);
-               trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
-                               &sighand->action[SIGKILL - 1]);
-               recalc_sigpending();
-               goto fatal;
-       }
-
        for (;;) {
                struct k_sigaction *ka;
 
+               /* Has this task already been marked for death? */
+               if (signal_group_exit(signal)) {
+                       ksig->info.si_signo = signr = SIGKILL;
+                       sigdelset(&current->pending.signal, SIGKILL);
+                       trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
+                               &sighand->action[SIGKILL - 1]);
+                       recalc_sigpending();
+                       goto fatal;
+               }
+
                if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) &&
                    do_signal_stop(0))
                        goto relock;
@@ -3431,6 +3476,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
                to->si_addr = ptr_to_compat(from->si_addr);
                to->si_perf_data = from->si_perf_data;
                to->si_perf_type = from->si_perf_type;
+               to->si_perf_flags = from->si_perf_flags;
                break;
        case SIL_CHLD:
                to->si_pid = from->si_pid;
@@ -3508,6 +3554,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
                to->si_addr = compat_ptr(from->si_addr);
                to->si_perf_data = from->si_perf_data;
                to->si_perf_type = from->si_perf_type;
+               to->si_perf_flags = from->si_perf_flags;
                break;
        case SIL_CHLD:
                to->si_pid    = from->si_pid;
@@ -4688,6 +4735,7 @@ static inline void siginfo_buildtime_checks(void)
        CHECK_OFFSET(si_pkey);
        CHECK_OFFSET(si_perf_data);
        CHECK_OFFSET(si_perf_type);
+       CHECK_OFFSET(si_perf_flags);
 
        /* sigpoll */
        CHECK_OFFSET(si_band);