ptrace: fix ptrace_unfreeze_traced() race with rt-lock
The patch "ptrace: fix ptrace vs tasklist_lock race" changed ptrace_freeze_traced() to take task->saved_state into account, but ptrace_unfreeze_traced() has the same problem and needs a similar fix: it should check/update both ->state and ->saved_state. Reported-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com> Fixes: "ptrace: fix ptrace vs tasklist_lock race" Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: stable-rt@vger.kernel.org Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
bc0a27b923
commit
6bd4eef1d8
|
@ -213,8 +213,8 @@ static bool ptrace_freeze_traced(struct task_struct *task)
|
|||
|
||||
static void ptrace_unfreeze_traced(struct task_struct *task)
|
||||
{
|
||||
if (task->state != __TASK_TRACED)
|
||||
return;
|
||||
unsigned long flags;
|
||||
bool frozen = true;
|
||||
|
||||
WARN_ON(!task->ptrace || task->parent != current);
|
||||
|
||||
|
@ -223,12 +223,19 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
|
|||
* Recheck state under the lock to close this race.
|
||||
*/
|
||||
spin_lock_irq(&task->sighand->siglock);
|
||||
if (task->state == __TASK_TRACED) {
|
||||
if (__fatal_signal_pending(task))
|
||||
wake_up_state(task, __TASK_TRACED);
|
||||
else
|
||||
task->state = TASK_TRACED;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&task->pi_lock, flags);
|
||||
if (task->state == __TASK_TRACED)
|
||||
task->state = TASK_TRACED;
|
||||
else if (task->saved_state == __TASK_TRACED)
|
||||
task->saved_state = TASK_TRACED;
|
||||
else
|
||||
frozen = false;
|
||||
raw_spin_unlock_irqrestore(&task->pi_lock, flags);
|
||||
|
||||
if (frozen && __fatal_signal_pending(task))
|
||||
wake_up_state(task, __TASK_TRACED);
|
||||
|
||||
spin_unlock_irq(&task->sighand->siglock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue