mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
ptrace: Don't change __state
Stop playing with tsk->__state to remove TASK_WAKEKILL while a ptrace command is executing. Instead remove TASK_WAKEKILL from the definition of TASK_TRACED, and implement a new jobctl flag TASK_PTRACE_FROZEN. This new flag is set in jobctl_freeze_task and cleared when ptrace_stop is awoken or in jobctl_unfreeze_task (when ptrace_stop remains asleep). In signal_wake_up add __TASK_TRACED to state along with TASK_WAKEKILL when the wake up is for a fatal signal. Skip adding __TASK_TRACED when TASK_PTRACE_FROZEN is not set. This has the same effect as changing TASK_TRACED to __TASK_TRACED as all of the wake_ups that use TASK_KILLABLE go through signal_wake_up. Handle a ptrace_stop being called with a pending fatal signal. Previously it would have been handled by schedule simply failing to sleep. As TASK_WAKEKILL is no longer part of TASK_TRACED schedule will sleep with a fatal_signal_pending. The code in signal_wake_up guarantees that the code will be awaked by any fatal signal that codes after TASK_TRACED is set. Previously the __state value of __TASK_TRACED was changed to TASK_RUNNING when woken up or back to TASK_TRACED when the code was left in ptrace_stop. Now when woken up ptrace_stop now clears JOBCTL_PTRACE_FROZEN and when left sleeping ptrace_unfreezed_traced clears JOBCTL_PTRACE_FROZEN. Tested-by: Kees Cook <keescook@chromium.org> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Link: https://lkml.kernel.org/r/20220505182645.497868-10-ebiederm@xmission.com Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
@@ -2209,14 +2209,12 @@ static int ptrace_stop(int exit_code, int why, unsigned long message,
|
||||
}
|
||||
|
||||
/*
|
||||
* schedule() will not sleep if there is a pending signal that
|
||||
* can awaken the task.
|
||||
*
|
||||
* After this point ptrace_signal_wake_up will clear TASK_TRACED
|
||||
* if ptrace_unlink happens. Handle previous ptrace_unlinks
|
||||
* here to prevent ptrace_stop sleeping in schedule.
|
||||
* After this point ptrace_signal_wake_up or signal_wake_up
|
||||
* will clear TASK_TRACED if ptrace_unlink happens or a fatal
|
||||
* signal comes in. Handle previous ptrace_unlinks and fatal
|
||||
* signals here to prevent ptrace_stop sleeping in schedule.
|
||||
*/
|
||||
if (!current->ptrace)
|
||||
if (!current->ptrace || __fatal_signal_pending(current))
|
||||
return exit_code;
|
||||
|
||||
set_special_state(TASK_TRACED);
|
||||
@@ -2305,7 +2303,7 @@ static int ptrace_stop(int exit_code, int why, unsigned long message,
|
||||
current->exit_code = 0;
|
||||
|
||||
/* LISTENING can be set only during STOP traps, clear it */
|
||||
current->jobctl &= ~JOBCTL_LISTENING;
|
||||
current->jobctl &= ~(JOBCTL_LISTENING | JOBCTL_PTRACE_FROZEN);
|
||||
|
||||
/*
|
||||
* Queued signals ignored us while we were stopped for tracing.
|
||||
|
Reference in New Issue
Block a user