]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
ptrace race fixes
authorChris Wright <chrisw@sous-sol.org>
Wed, 17 May 2006 21:55:15 +0000 (14:55 -0700)
committerChris Wright <chrisw@sous-sol.org>
Wed, 17 May 2006 21:55:15 +0000 (14:55 -0700)
queue-2.6.16/fix-ptrace_attach-ptrace_traceme-de_thread-race.patch [new file with mode: 0644]
queue-2.6.16/ptrace_attach-fix-possible-deadlock-schenario-with-irqs.patch [new file with mode: 0644]
queue-2.6.16/series

diff --git a/queue-2.6.16/fix-ptrace_attach-ptrace_traceme-de_thread-race.patch b/queue-2.6.16/fix-ptrace_attach-ptrace_traceme-de_thread-race.patch
new file mode 100644 (file)
index 0000000..5a760ab
--- /dev/null
@@ -0,0 +1,95 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@g5.osdl.org>
+Date: Sun May 7 10:49:33 2006 -0700
+Subject: [PATCH] Fix ptrace_attach()/ptrace_traceme()/de_thread() race
+
+This holds the task lock (and, for ptrace_attach, the tasklist_lock)
+over the actual attach event, which closes a race between attacking to a
+thread that is either doing a PTRACE_TRACEME or getting de-threaded.
+
+Thanks to Oleg Nesterov for reminding me about this, and Chris Wright
+for noticing a lost return value in my first version.
+
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ kernel/ptrace.c |   39 +++++++++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 18 deletions(-)
+
+--- linux-2.6.16.16.orig/kernel/ptrace.c
++++ linux-2.6.16.16/kernel/ptrace.c
+@@ -149,12 +149,16 @@ int ptrace_may_attach(struct task_struct
+ int ptrace_attach(struct task_struct *task)
+ {
+       int retval;
+-      task_lock(task);
++
+       retval = -EPERM;
+       if (task->pid <= 1)
+-              goto bad;
++              goto out;
+       if (task->tgid == current->tgid)
+-              goto bad;
++              goto out;
++
++      write_lock_irq(&tasklist_lock);
++      task_lock(task);
++
+       /* the same process cannot be attached many times */
+       if (task->ptrace & PT_PTRACED)
+               goto bad;
+@@ -167,17 +171,15 @@ int ptrace_attach(struct task_struct *ta
+                                     ? PT_ATTACHED : 0);
+       if (capable(CAP_SYS_PTRACE))
+               task->ptrace |= PT_PTRACE_CAP;
+-      task_unlock(task);
+-      write_lock_irq(&tasklist_lock);
+       __ptrace_link(task, current);
+-      write_unlock_irq(&tasklist_lock);
+       force_sig_specific(SIGSTOP, task);
+-      return 0;
+ bad:
++      write_unlock_irq(&tasklist_lock);
+       task_unlock(task);
++out:
+       return retval;
+ }
+@@ -418,21 +420,22 @@ int ptrace_request(struct task_struct *c
+  */
+ int ptrace_traceme(void)
+ {
+-      int ret;
++      int ret = -EPERM;
+       /*
+        * Are we already being traced?
+        */
+-      if (current->ptrace & PT_PTRACED)
+-              return -EPERM;
+-      ret = security_ptrace(current->parent, current);
+-      if (ret)
+-              return -EPERM;
+-      /*
+-       * Set the ptrace bit in the process ptrace flags.
+-       */
+-      current->ptrace |= PT_PTRACED;
+-      return 0;
++      task_lock(current);
++      if (!(current->ptrace & PT_PTRACED)) {
++              ret = security_ptrace(current->parent, current);
++              /*
++               * Set the ptrace bit in the process ptrace flags.
++               */
++              if (!ret)
++                      current->ptrace |= PT_PTRACED;
++      }
++      task_unlock(current);
++      return ret;
+ }
+ /**
diff --git a/queue-2.6.16/ptrace_attach-fix-possible-deadlock-schenario-with-irqs.patch b/queue-2.6.16/ptrace_attach-fix-possible-deadlock-schenario-with-irqs.patch
new file mode 100644 (file)
index 0000000..1bb2a0f
--- /dev/null
@@ -0,0 +1,56 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@g5.osdl.org>
+Date: Thu May 11 11:08:49 2006 -0700
+Subject: [PATCH] ptrace_attach: fix possible deadlock schenario with irqs
+
+Eric Biederman points out that we can't take the task_lock while holding
+tasklist_lock for writing, because another CPU that holds the task lock
+might take an interrupt that then tries to take tasklist_lock for writing.
+
+Which would be a nasty deadlock, with one CPU spinning forever in an
+interrupt handler (although admittedly you need to really work at
+triggering it ;)
+
+Since the ptrace_attach() code is special and very unusual, just make it
+be extra careful, and use trylock+repeat to avoid the possible deadlock.
+
+Cc: Oleg Nesterov <oleg@tv-sign.ru>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Roland McGrath <roland@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ kernel/ptrace.c |   20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+--- linux-2.6.16.16.orig/kernel/ptrace.c
++++ linux-2.6.16.16/kernel/ptrace.c
+@@ -156,8 +156,26 @@ int ptrace_attach(struct task_struct *ta
+       if (task->tgid == current->tgid)
+               goto out;
+-      write_lock_irq(&tasklist_lock);
++repeat:
++      /*
++       * Nasty, nasty.
++       *
++       * We want to hold both the task-lock and the
++       * tasklist_lock for writing at the same time.
++       * But that's against the rules (tasklist_lock
++       * is taken for reading by interrupts on other
++       * cpu's that may have task_lock).
++       */
+       task_lock(task);
++      local_irq_disable();
++      if (!write_trylock(&tasklist_lock)) {
++              local_irq_enable();
++              task_unlock(task);
++              do {
++                      cpu_relax();
++              } while (!write_can_lock(&tasklist_lock));
++              goto repeat;
++      }
+       /* the same process cannot be attached many times */
+       if (task->ptrace & PT_PTRACED)
index 75767d8d3c00ad71395182e9da582c8a336a387b..d84b46918619a617d17afd50d534c79dd4d8116f 100644 (file)
@@ -18,3 +18,5 @@ i386-x86_64-Force-pci-noacpi-on-HP-XW9300.patch
 remove-cond_resched-in-gather_stats.patch
 add-migratepage-address-space-op-to-shmem.patch
 page-migration-Fix-fallback-behavior-for-dirty-pages.patch
+fix-ptrace_attach-ptrace_traceme-de_thread-race.patch
+ptrace_attach-fix-possible-deadlock-schenario-with-irqs.patch