diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-25 01:44:43 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-05-14 18:37:46 (GMT) |
commit | b00da6bab40ac6f547cd21b36464dfef501783b9 (patch) | |
tree | 18ff645b818fd8999588d8fd71c3b3a7c6d3f876 /include/linux | |
parent | 6a12bc3add6b316558fd23459201ce6f60fe6af7 (diff) | |
download | linux-fsl-qoriq-b00da6bab40ac6f547cd21b36464dfef501783b9.tar.xz |
signal/x86: Delay calling signals in atomic
On x86_64 we must disable preemption before we enable interrupts
for stack faults, int3 and debugging, because the current task is using
a per CPU debug stack defined by the IST. If we schedule out, another task
can come in and use the same stack and cause the stack to be corrupted
and crash the kernel on return.
When CONFIG_PREEMPT_RT_FULL is enabled, spin_locks become mutexes, and
one of these is the spin lock used in signal handling.
Some of the debug code (int3) causes do_trap() to send a signal.
This function calls a spin lock that has been converted to a mutex
and has the possibility to sleep. If this happens, the above issues with
the corrupted stack is possible.
Instead of calling the signal right away, for PREEMPT_RT and x86_64,
the signal information is stored on the stacks task_struct and
TIF_NOTIFY_RESUME is set. Then on exit of the trap, the signal resume
code will send the signal when preemption is enabled.
[ rostedt: Switched from #ifdef CONFIG_PREEMPT_RT_FULL to
ARCH_RT_DELAYS_SIGNAL_SEND and added comments to the code. ]
Cc: stable-rt@vger.kernel.org
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/sched.h | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 4d58a49..9e254d8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1209,6 +1209,10 @@ struct task_struct { sigset_t blocked, real_blocked; sigset_t saved_sigmask; /* restored if set_restore_sigmask() was used */ struct sigpending pending; +#ifdef CONFIG_PREEMPT_RT_FULL + /* TODO: move me into ->restart_block ? */ + struct siginfo forced_info; +#endif unsigned long sas_ss_sp; size_t sas_ss_size; |