ptrace: fix ptrace_unfreeze_traced() race with rt-lock
[ Upstream commit 0fdc91971b ]
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: Tom Zanussi <zanussi@kernel.org>
This commit is contained in:
committed by
jianlong.wang
parent
b4623989a8
commit
e2ef23f859
@@ -207,8 +207,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);
|
||||
|
||||
@@ -217,12 +217,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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user