summaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-05-21 09:48:31 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-05-21 09:48:31 +0200
commit03e3e31ee5c8d45c62c31035578bab5e90133eff (patch)
tree5cff3fda5bb8278621c27823f52b7e8dd85fb0ef /kernel/ptrace.c
parentmisc: alcor_pci: fix null-ptr-deref when there is no PCI bridge (diff)
parentMerge tag 'char-misc-5.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/g... (diff)
downloadlinux-03e3e31ee5c8d45c62c31035578bab5e90133eff.tar.xz
linux-03e3e31ee5c8d45c62c31035578bab5e90133eff.zip
Merge 50f09a3dd587 ("Merge tag 'char-misc-5.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc") into char-misc-next
We want the char/misc driver fixes in here as well Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 76f09456ec4b..2997ca600d18 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -170,6 +170,21 @@ void __ptrace_unlink(struct task_struct *child)
spin_unlock(&child->sighand->siglock);
}
+static bool looks_like_a_spurious_pid(struct task_struct *task)
+{
+ if (task->exit_code != ((PTRACE_EVENT_EXEC << 8) | SIGTRAP))
+ return false;
+
+ if (task_pid_vnr(task) == task->ptrace_message)
+ return false;
+ /*
+ * The tracee changed its pid but the PTRACE_EVENT_EXEC event
+ * was not wait()'ed, most probably debugger targets the old
+ * leader which was destroyed in de_thread().
+ */
+ return true;
+}
+
/* Ensure that nothing can wake it up, even SIGKILL */
static bool ptrace_freeze_traced(struct task_struct *task)
{
@@ -180,7 +195,8 @@ static bool ptrace_freeze_traced(struct task_struct *task)
return ret;
spin_lock_irq(&task->sighand->siglock);
- if (task_is_traced(task) && !__fatal_signal_pending(task)) {
+ if (task_is_traced(task) && !looks_like_a_spurious_pid(task) &&
+ !__fatal_signal_pending(task)) {
task->state = __TASK_TRACED;
ret = true;
}