[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

rpms/kernel/FC-6 kernel-2.6.spec, 1.2816, 1.2817 linux-2.6-utrace.patch, 1.32, 1.33



Author: roland

Update of /cvs/dist/rpms/kernel/FC-6
In directory cvs.devel.redhat.com:/tmp/cvs-serv26147

Modified Files:
	kernel-2.6.spec linux-2.6-utrace.patch 
Log Message:
utrace update: clean up recent fixes, fix races on detach


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/FC-6/kernel-2.6.spec,v
retrieving revision 1.2816
retrieving revision 1.2817
diff -u -r1.2816 -r1.2817
--- kernel-2.6.spec	23 Oct 2006 05:04:28 -0000	1.2816
+++ kernel-2.6.spec	23 Oct 2006 09:56:33 -0000	1.2817
@@ -1221,7 +1221,7 @@
 
 # OLPC specific patches
 %if 0%{?olpc}
-# MTD NAND driver core updates... 
+# MTD NAND driver core updates...
 # git://git.infradead.org/~dwmw2/cafe-2.6.18.git
 %patch5000 -p1
 # ... needed for OLPC CAFÉ NAND driver
@@ -1230,7 +1230,7 @@
 # Marvell 88ALP01 camera
 %patch5010 -p1
 %patch5011 -p1
-# OLPC DCON fb driver 
+# OLPC DCON fb driver
 %patch5020 -p1
 # Marvell Libertas wireless driver
 %patch5030 -p1
@@ -2058,6 +2058,9 @@
 %endif
 
 %changelog
+* Mon Oct 23 2006 Roland McGrath <roland redhat com>
+- utrace update: clean up recent fixes, fix races on detach
+
 * Sun Oct 22 2006 David Woodhouse <dwmw2 redhat com>
 - Add hardware ECC support to CAFÉ NAND driver
 - Fix compilation of camera driver
@@ -2100,7 +2103,7 @@
 - Add Marvell 88ALP01 camera controller support (OLPC)
 - Add OLPC DCON fb driver
 
-* Mon Oct 16 2006 Dave Jones <davej redhat com> 
+* Mon Oct 16 2006 Dave Jones <davej redhat com>
 - Silence another noisy boot-time printk. (#210810)
 - Remove broken VIA quirk that prevented booting on some EPIAs (#210817)
 - Fix JBD crash with 1K blocksize filesystems. (#209005)
@@ -2108,14 +2111,14 @@
 * Mon Oct 16 2006 Stephen C. Tweedie <sct redhat com>
 - Add RPM release number to the Xen build version
 
-* Sat Oct 14 2006 Dave Jones <davej redhat com> 
+* Sat Oct 14 2006 Dave Jones <davej redhat com>
 - 2.6.18.1
 - Remove some RHEL'isms from the specfile.
 
-* Fri Oct 13 2006 Dave Jones <davej redhat com> 
+* Fri Oct 13 2006 Dave Jones <davej redhat com>
 - Fix use after free in NFSv4
 
-* Fri Oct 13 2006 Juan Quintela <quintela redhat com> 
+* Fri Oct 13 2006 Juan Quintela <quintela redhat com>
 - update xen HV cset 11740.
 - xen kernel update:
   * linux-2.6-xen-fedora changeset:   36227:84594d199837
@@ -2131,7 +2134,7 @@
 
 * Thu Oct 12 2006 Dave Jones <davej redhat com>
 - Fix unbalanced locking in decnet.
-  (You know we're getting close to a release when I'm 
+  (You know we're getting close to a release when I'm
    fixing bugs in DECNet of all things).
   Both users will be very happy this fix made it into FC6.
 - Improve mm debugging in rmap sanity checking.

linux-2.6-utrace.patch:
 Documentation/utrace.txt                |  455 ++++++++
 arch/alpha/kernel/asm-offsets.c         |    2 
 arch/alpha/kernel/entry.S               |    4 
 arch/arm/kernel/ptrace.c                |   36 
 arch/arm26/kernel/ptrace.c              |   32 
 arch/frv/kernel/ptrace.c                |   15 
 arch/i386/kernel/entry.S                |    7 
 arch/i386/kernel/i387.c                 |  143 +-
 arch/i386/kernel/process.c              |    3 
 arch/i386/kernel/ptrace.c               |  863 ++++++++--------
 arch/i386/kernel/signal.c               |   37 
 arch/i386/kernel/vm86.c                 |    7 
 arch/ia64/ia32/ia32_entry.S             |    2 
 arch/ia64/ia32/sys_ia32.c               |   23 
 arch/ia64/kernel/asm-offsets.c          |    2 
 arch/ia64/kernel/fsys.S                 |   16 
 arch/ia64/kernel/mca.c                  |    2 
 arch/ia64/kernel/ptrace.c               | 1670 +++++++++++++++----------------
 arch/ia64/kernel/signal.c               |    4 
 arch/mips/kernel/ptrace.c               |   21 
 arch/mips/kernel/sysirix.c              |    2 
 arch/powerpc/kernel/Makefile            |    4 
 arch/powerpc/kernel/asm-offsets.c       |    2 
 arch/powerpc/kernel/process.c           |    5 
 arch/powerpc/kernel/ptrace-common.h     |  161 ---
 arch/powerpc/kernel/ptrace.c            |  959 ++++++++++--------
 arch/powerpc/kernel/ptrace32.c          |  436 --------
 arch/powerpc/kernel/signal_32.c         |   55 +
 arch/powerpc/kernel/signal_64.c         |    3 
 arch/powerpc/kernel/sys_ppc32.c         |    5 
 arch/powerpc/lib/sstep.c                |    3 
 arch/powerpc/platforms/cell/spufs/run.c |    2 
 arch/ppc/kernel/asm-offsets.c           |    2 
 arch/s390/kernel/Makefile               |    2 
 arch/s390/kernel/compat_linux.c         |    3 
 arch/s390/kernel/compat_signal.c        |    5 
 arch/s390/kernel/process.c              |    3 
 arch/s390/kernel/ptrace.c               |  651 +++++++++++-
 arch/s390/kernel/signal.c               |    3 
 arch/s390/kernel/traps.c                |    6 
 arch/sparc64/kernel/Makefile            |    2 
 arch/sparc64/kernel/binfmt_aout32.c     |    2 
 arch/sparc64/kernel/entry.S             |    6 
 arch/sparc64/kernel/process.c           |    3 
 arch/sparc64/kernel/ptrace.c            | 1221 ++++++++++++-----------
 arch/sparc64/kernel/signal.c            |    2 
 arch/sparc64/kernel/signal32.c          |    2 
 arch/sparc64/kernel/sys_sparc32.c       |    3 
 arch/sparc64/kernel/systbls.S           |    4 
 arch/x86_64/ia32/fpu32.c                |   92 +
 arch/x86_64/ia32/ia32_aout.c            |    6 
 arch/x86_64/ia32/ia32_signal.c          |    8 
 arch/x86_64/ia32/ia32entry.S            |    2 
 arch/x86_64/ia32/ptrace32.c             |  715 +++++++++----
 arch/x86_64/ia32/sys_ia32.c             |    5 
 arch/x86_64/kernel/process.c            |    5 
 arch/x86_64/kernel/ptrace.c             |  648 +++++++-----
 arch/x86_64/kernel/signal.c             |   28 
 arch/x86_64/kernel/traps.c              |    8 
 arch/x86_64/mm/fault.c                  |    4 
 drivers/connector/cn_proc.c             |    4 
 fs/binfmt_aout.c                        |    6 
 fs/binfmt_elf.c                         |    6 
 fs/binfmt_elf_fdpic.c                   |    7 
 fs/binfmt_flat.c                        |    3 
 fs/binfmt_som.c                         |    2 
 fs/exec.c                               |   11 
 fs/proc/array.c                         |   14 
 fs/proc/base.c                          |   17 
 include/asm-i386/i387.h                 |   13 
 include/asm-i386/signal.h               |    4 
 include/asm-i386/thread_info.h          |    7 
 include/asm-i386/tracehook.h            |   49 
 include/asm-ia64/elf.h                  |   24 
 include/asm-ia64/tracehook.h            |   81 +
 include/asm-powerpc/tracehook.h         |   80 +
 include/asm-s390/tracehook.h            |   53 +
 include/asm-sparc64/tracehook.h         |   44 
 include/asm-x86_64/fpu32.h              |    3 
 include/asm-x86_64/thread_info.h        |    2 
 include/asm-x86_64/tracehook.h          |   54 +
 include/linux/init_task.h               |    3 
 include/linux/ptrace.h                  |  224 +++-
 include/linux/sched.h                   |   25 
 include/linux/tracehook.h               |  707 +++++++++++++
 include/linux/utrace.h                  |  484 +++++++++
 init/Kconfig                            |   29 
 kernel/Makefile                         |    1 
 kernel/exit.c                           |  254 +---
 kernel/fork.c                           |   62 -
 kernel/ptrace.c                         | 1632 ++++++++++++++++++++++++------
 kernel/signal.c                         |  211 ----
 kernel/sys.c                            |    2 
 kernel/timer.c                          |    4 
 kernel/utrace.c                         | 1688 ++++++++++++++++++++++++++++++++
 security/selinux/hooks.c                |   54 -
 security/selinux/include/objsec.h       |    1 
 97 files changed, 9720 insertions(+), 4567 deletions(-)

Index: linux-2.6-utrace.patch
===================================================================
RCS file: /cvs/dist/rpms/kernel/FC-6/linux-2.6-utrace.patch,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- linux-2.6-utrace.patch	12 Oct 2006 22:37:23 -0000	1.32
+++ linux-2.6-utrace.patch	23 Oct 2006 09:56:33 -0000	1.33
@@ -8,7 +8,7 @@
  arch/i386/kernel/i387.c                 |  143 +--
  arch/i386/kernel/process.c              |    3 
  arch/i386/kernel/ptrace.c               |  863 +++++++++-------
- arch/i386/kernel/signal.c               |   39 -
+ arch/i386/kernel/signal.c               |   37 -
  arch/i386/kernel/vm86.c                 |    7 
  arch/ia64/ia32/ia32_entry.S             |    2 
  arch/ia64/ia32/sys_ia32.c               |   23 
@@ -25,8 +25,8 @@
  arch/powerpc/kernel/ptrace-common.h     |  161 ---
  arch/powerpc/kernel/ptrace.c            |  959 +++++++++++-------
  arch/powerpc/kernel/ptrace32.c          |  436 --------
- arch/powerpc/kernel/signal_32.c         |   56 +
- arch/powerpc/kernel/signal_64.c         |    4 
+ arch/powerpc/kernel/signal_32.c         |   55 +
+ arch/powerpc/kernel/signal_64.c         |    3 
  arch/powerpc/kernel/sys_ppc32.c         |    5 
  arch/powerpc/lib/sstep.c                |    3 
  arch/powerpc/platforms/cell/spufs/run.c |    2 
@@ -36,14 +36,14 @@
  arch/s390/kernel/compat_signal.c        |    5 
  arch/s390/kernel/process.c              |    3 
  arch/s390/kernel/ptrace.c               |  651 +++++++++++-
- arch/s390/kernel/signal.c               |    4 
+ arch/s390/kernel/signal.c               |    3 
  arch/s390/kernel/traps.c                |    6 
  arch/sparc64/Makefile                   |    0 
  arch/sparc64/kernel/Makefile            |    2 
  arch/sparc64/kernel/binfmt_aout32.c     |    2 
  arch/sparc64/kernel/entry.S             |    6 
  arch/sparc64/kernel/process.c           |    3 
- arch/sparc64/kernel/ptrace.c            | 1221 ++++++++++++-----------
+ arch/sparc64/kernel/ptrace.c            | 1221 ++++++++++++----------
  arch/sparc64/kernel/signal.c            |    2 
  arch/sparc64/kernel/signal32.c          |    2 
  arch/sparc64/kernel/sys_sparc32.c       |    3 
@@ -56,7 +56,7 @@
  arch/x86_64/ia32/sys_ia32.c             |    5 
  arch/x86_64/kernel/process.c            |    5 
  arch/x86_64/kernel/ptrace.c             |  648 +++++++-----
- arch/x86_64/kernel/signal.c             |   30 -
+ arch/x86_64/kernel/signal.c             |   28 -
  arch/x86_64/kernel/traps.c              |    8 
  arch/x86_64/mm/fault.c                  |    4 
  drivers/connector/cn_proc.c             |    4 
@@ -73,7 +73,7 @@
  include/asm-i386/thread_info.h          |    7 
  include/asm-i386/tracehook.h            |   49 +
  include/asm-ia64/elf.h                  |   24 
- include/asm-ia64/tracehook.h            |   81 ++
+ include/asm-ia64/tracehook.h            |   81 +
  include/asm-powerpc/tracehook.h         |   80 +
  include/asm-s390/tracehook.h            |   53 +
  include/asm-sparc64/tracehook.h         |   44 +
@@ -93,10 +93,10 @@
  kernel/signal.c                         |  211 +---
  kernel/sys.c                            |    2 
  kernel/timer.c                          |    4 
- kernel/utrace.c                         | 1590 ++++++++++++++++++++++++++++++
+ kernel/utrace.c                         | 1688 +++++++++++++++++++++++++++++++
  security/selinux/hooks.c                |   54 +
  security/selinux/include/objsec.h       |    1 
- 98 files changed, 9630 insertions(+), 4566 deletions(-)
+ 98 files changed, 9720 insertions(+), 4567 deletions(-)
  create mode 100644 Documentation/utrace.txt
  delete arch/powerpc/kernel/ptrace-common.h
  delete arch/powerpc/kernel/ptrace32.c
@@ -1175,7 +1175,7 @@
 +/*
 + * Hooks in <linux/tracehook.h> call these entry points to the utrace dispatch.
 + */
-+void utrace_quiescent(struct task_struct *);
++void utrace_quiescent(struct task_struct *, struct utrace_signal *);
 +void utrace_release_task(struct task_struct *);
 +int utrace_get_signal(struct task_struct *, struct pt_regs *,
 +		      siginfo_t *, struct k_sigaction *);
@@ -2096,7 +2096,7 @@
 +{
 +#ifdef CONFIG_UTRACE
 +	if (current->utrace_flags & UTRACE_ACTION_QUIESCE)
-+		utrace_quiescent(current);
++		utrace_quiescent(current, NULL);
 +#endif
 +}
 +
@@ -3228,7 +3228,7 @@
  EXPORT_SYMBOL(sigprocmask);
 --- linux-2.6/kernel/utrace.c.utrace-ptrace-compat
 +++ linux-2.6/kernel/utrace.c
-@@ -0,0 +1,1590 @@
+@@ -0,0 +1,1688 @@
 +#include <linux/utrace.h>
 +#include <linux/tracehook.h>
 +#include <linux/err.h>
@@ -3350,9 +3350,13 @@
 +	kmem_cache_free(utrace_cachep, utrace);
 +}
 +
++/*
++ * Called with utrace locked.  Clean it up and free it via RCU.
++ */
 +static void
 +rcu_utrace_free(struct utrace *utrace)
 +{
++	utrace_unlock(utrace);
 +	INIT_RCU_HEAD(&utrace->u.dead);
 +	call_rcu(&utrace->u.dead, utrace_free);
 +}
@@ -3366,23 +3370,34 @@
 +}
 +
 +/*
-+ * Called with utrace locked and the target quiescent (maybe current).
-+ * If this was the last engine, utrace is left locked and not freed,
-+ * but is removed from the task.
++ * Remove the utrace pointer from the task, unless there is a pending
++ * forced signal (or it's quiescent in utrace_get_signal).
 + */
-+static void
-+remove_engine(struct utrace_attached_engine *engine,
-+	      struct task_struct *tsk, struct utrace *utrace)
++static inline void
++utrace_clear_tsk(struct task_struct *tsk, struct utrace *utrace)
 +{
-+	list_del_rcu(&engine->entry);
-+	if (list_empty(&utrace->engines)) {
++	if (utrace->u.live.signal == NULL) {
 +		task_lock(tsk);
 +		if (likely(tsk->utrace != NULL)) {
 +			rcu_assign_pointer(tsk->utrace, NULL);
-+			tsk->utrace_flags = 0;
++			tsk->utrace_flags &= UTRACE_ACTION_NOREAP;
 +		}
 +		task_unlock(tsk);
 +	}
++}
++
++/*
++ * Called with utrace locked and the target quiescent (maybe current).
++ * If this was the last engine and there is no parting forced signal
++ * pending, utrace is left locked and not freed, but is removed from the task.
++ */
++static void
++remove_engine(struct utrace_attached_engine *engine,
++	      struct task_struct *tsk, struct utrace *utrace)
++{
++	list_del_rcu(&engine->entry);
++	if (list_empty(&utrace->engines))
++		utrace_clear_tsk(tsk, utrace);
 +	call_rcu(&engine->rhead, utrace_engine_free);
 +}
 +
@@ -3391,21 +3406,89 @@
 + * Called with utrace locked, after remove_engine may have run.
 + * Passed the flags from all remaining engines, i.e. zero if none left.
 + * Install the flags in tsk->utrace_flags and return with utrace unlocked.
-+ * If no engines are left, utrace is freed and we return NULL.
++ * If no engines are left and there is no parting forced signal pending,
++ * utrace is freed and we return NULL.
 + */
 +static struct utrace *
 +check_dead_utrace(struct task_struct *tsk, struct utrace *utrace,
-+		 unsigned long flags)
++		  unsigned long flags)
 +{
-+	if (flags) {
-+		tsk->utrace_flags = flags;
++	long exit_state = 0;
++
++	if (utrace->u.live.signal != NULL)
++		/*
++		 * There is a pending forced signal.  It may have been
++		 * left by an engine now detached.  The empty utrace
++		 * remains attached until it can be processed.
++		 */
++		flags |= UTRACE_ACTION_QUIESCE;
++
++	/*
++	 * If tracing was preventing a SIGCHLD or self-reaping
++	 * and is no longer, we'll do that report or reaping now.
++	 */
++	if (((tsk->utrace_flags &~ flags) & UTRACE_ACTION_NOREAP)
++	    && tsk->exit_state && !utrace->u.exit.notified) {
++		BUG_ON(tsk->exit_state != EXIT_ZOMBIE);
++		/*
++		 * While holding the utrace lock, mark that it's been done.
++		 * For self-reaping, we need to change tsk->exit_state
++		 * before clearing tsk->utrace_flags, so that the real
++		 * parent can't see it in EXIT_ZOMBIE momentarily and reap it.
++		 */
++		utrace->u.exit.notified = 1;
++		if (tsk->exit_signal == -1) {
++			exit_state = xchg(&tsk->exit_state, EXIT_DEAD);
++			BUG_ON(exit_state != EXIT_ZOMBIE);
++			exit_state = EXIT_DEAD;
++
++			/*
++			 * Now that we've changed its state to DEAD,
++			 * it's safe to install the new tsk->utrace_flags
++			 * value without the UTRACE_ACTION_NOREAP bit set.
++			 */
++		}
++		else if (thread_group_empty(tsk)) {
++			/*
++			 * We need to prevent the real parent from reaping
++			 * until after we've called do_notify_parent, below.
++			 * It can get into wait_task_zombie any time after
++			 * the UTRACE_ACTION_NOREAP bit is cleared.  It's
++			 * safe for that to do everything it does until its
++			 * release_task call starts tearing things down.
++			 * Holding tasklist_lock for reading prevents
++			 * release_task from proceeding until we've done
++			 * everything we need to do.
++			 */
++			exit_state = EXIT_ZOMBIE;
++			read_lock(&tasklist_lock);
++		}
++	}
++
++	tsk->utrace_flags = flags;
++	if (flags)
 +		utrace_unlock(utrace);
-+		return utrace;
++	else {
++		rcu_utrace_free(utrace);
++		utrace = NULL;
 +	}
 +
-+	utrace_unlock(utrace);
-+	rcu_utrace_free(utrace);
-+	return NULL;
++	/*
++	 * Now we're finished updating the utrace state.
++	 * Do a pending self-reaping or parent notification.
++	 */
++	if (exit_state == EXIT_DEAD)
++		/*
++		 * Note this can wind up in utrace_reap and do more callbacks.
++		 * Our callers must be in places where that is OK.
++		 */
++		release_task(tsk);
++	else if (exit_state == EXIT_ZOMBIE) {
++		do_notify_parent(tsk, tsk->exit_signal);
++		read_unlock(&tasklist_lock); /* See comment above.  */
++	}
++
++	return utrace;
 +}
 +
 +
@@ -3582,29 +3665,6 @@
 +
 +
 +/*
-+ * If tracing was preventing a SIGCHLD or self-reaping
-+ * and is no longer, do that report or reaping right now.
-+ */
-+static void
-+check_noreap(struct task_struct *target, struct utrace *utrace,
-+	     u32 old_action, u32 action)
-+{
-+	if ((action | ~old_action) & UTRACE_ACTION_NOREAP)
-+		return;
-+
-+	if (utrace && xchg(&utrace->u.exit.notified, 1))
-+		return;
-+
-+	if (target->exit_signal == -1)
-+		release_task(target);
-+	else if (thread_group_empty(target)) {
-+		read_lock(&tasklist_lock);
-+		do_notify_parent(target, target->exit_signal);
-+		read_unlock(&tasklist_lock);
-+	}
-+}
-+
-+/*
 + * We may have been the one keeping the target thread quiescent.
 + * Check if it should wake up now.
 + * Called with utrace locked, and unlocks it on return.
@@ -3627,8 +3687,6 @@
 +		list_for_each_entry(engine, &utrace->engines, entry)
 +			flags |= engine->flags | UTRACE_EVENT(REAP);
 +		utrace = check_dead_utrace(target, utrace, flags);
-+
-+		check_noreap(target, utrace, old_flags, flags);
 +		return;
 +	}
 +
@@ -3744,7 +3802,6 @@
 +		}
 +		call_rcu(&engine->rhead, utrace_engine_free);
 +	}
-+	utrace_unlock(utrace);
 +
 +	rcu_utrace_free(utrace);
 +}
@@ -3910,9 +3967,8 @@
 +		struct utrace **utracep, u32 action)
 +{
 +	struct utrace_attached_engine *engine, *next;
-+	unsigned long flags;
++	unsigned long flags = 0;
 +
-+	flags = 0;
 +	list_for_each_entry_safe(engine, next, &utrace->engines, entry) {
 +		if (engine->ops == &dead_engine_ops)
 +			remove_engine(engine, tsk, utrace);
@@ -3944,7 +4000,7 @@
 +check_quiescent(struct task_struct *tsk, u32 action)
 +{
 +	if (action & UTRACE_ACTION_STATE_MASK)
-+		utrace_quiescent(tsk);
++		utrace_quiescent(tsk, NULL);
 +}
 +
 +/*
@@ -4046,9 +4102,14 @@
 + * Called if UTRACE_EVENT(QUIESCE) or UTRACE_ACTION_QUIESCE flag is set.
 + * Also called after other event reports.
 + * It is a good time to block.
++ *
++ * The signal pointer is nonzero when called from utrace_get_signal,
++ * where a pending forced signal can be processed right away.  Otherwise,
++ * we keep UTRACE_ACTION_QUIESCE set after resuming so that utrace_get_signal
++ * will be entered before user mode.
 + */
 +void
-+utrace_quiescent(struct task_struct *tsk)
++utrace_quiescent(struct task_struct *tsk, struct utrace_signal *signal)
 +{
 +	struct utrace *utrace = tsk->utrace;
 +	unsigned long action;
@@ -4062,6 +4123,11 @@
 +	 * If some engines want us quiescent, we block here.
 +	 */
 +	if (action & UTRACE_ACTION_QUIESCE) {
++		if (signal != NULL) {
++			BUG_ON(utrace->u.live.signal != NULL);
++			utrace->u.live.signal = signal;
++		}
++
 +		spin_lock_irq(&tsk->sighand->siglock);
 +		/*
 +		 * If wake_quiescent is trying to wake us up now, it will
@@ -4086,6 +4152,17 @@
 +		else
 +			spin_unlock_irq(&tsk->sighand->siglock);
 +
++		if (signal != NULL) {
++			/*
++			 * We know the struct stays in place when its
++			 * u.live.signal is set, see check_dead_utrace.
++			 * This makes it safe to clear its pointer here.
++			 */
++			BUG_ON(tsk->utrace != utrace);
++			BUG_ON(utrace->u.live.signal != signal);
++			utrace->u.live.signal = NULL;
++		}
++
 +		/*
 +		 * We've woken up.  One engine could be waking us up while
 +		 * another has asked us to quiesce.  So check afresh.  We
@@ -4103,6 +4180,10 @@
 +		 * Our flags are out of date.
 +		 * Update the set of events of interest from the union
 +		 * of the interests of the remaining tracing engines.
++		 * This may notice that there are no engines left
++		 * and clean up the struct utrace.  It's left in place
++		 * and the QUIESCE flag set as long as utrace_get_signal
++		 * still needs to process a pending forced signal.
 +		 */
 +		struct utrace_attached_engine *engine;
 +		unsigned long flags = 0;
@@ -4110,8 +4191,9 @@
 +		utrace_lock(utrace);
 +		list_for_each_entry(engine, &utrace->engines, entry)
 +			flags |= engine->flags | UTRACE_EVENT(REAP);
-+		tsk->utrace_flags = flags;
-+		utrace_unlock(utrace);
++		if (flags == 0)
++			utrace_clear_tsk(tsk, utrace);
++		utrace = check_dead_utrace(tsk, utrace, flags);
 +	}
 +
 +	/*
@@ -4162,7 +4244,7 @@
 +}
 +
 +/*
-+ * Called iff UTRACE_EVENT(DEATH) flag is set.
++ * Called iff UTRACE_EVENT(DEATH) or UTRACE_ACTION_QUIESCE flag is set.
 + *
 + * It is always possible that we are racing with utrace_release_task here,
 + * if UTRACE_ACTION_NOREAP is not set, or in the case of non-leader exec
@@ -4190,6 +4272,7 @@
 +		if (engine->flags & UTRACE_EVENT(QUIESCE))
 +			REPORT(report_quiesce);
 +	}
++
 +	/*
 +	 * Unconditionally lock and recompute the flags.
 +	 * This may notice that there are no engines left and
@@ -4222,8 +4305,6 @@
 +
 +			utrace_unlock(utrace);
 +		}
-+
-+		check_noreap(tsk, utrace, oaction, action);
 +	}
 +}
 +
@@ -4426,41 +4507,49 @@
 +#endif
 +
 +	/*
++	 * If a signal was injected previously, it could not use our
++	 * stack space directly.  It had to allocate a data structure,
++	 * which we can now copy out of and free.
++	 *
++	 * We don't have to lock access to u.live.signal because it's only
++	 * touched by utrace_inject_signal when we're quiescent.
++	 */
++	if (utrace->u.live.signal != NULL) {
++		signal.signr = utrace->u.live.signal->signr;
++		copy_siginfo(info, utrace->u.live.signal->info);
++		if (utrace->u.live.signal->return_ka)
++			*return_ka = *utrace->u.live.signal->return_ka;
++		else
++			signal.return_ka = NULL;
++		kfree(utrace->u.live.signal);
++		utrace->u.live.signal = NULL;
++	}
++
++	/*
 +	 * If we should quiesce, now is the time.
 +	 * First stash a pointer to the state on our stack,
 +	 * so that utrace_inject_signal can tell us what to do.
 +	 */
-+	if (utrace->u.live.signal == NULL)
-+		utrace->u.live.signal = &signal;
-+
 +	if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
 +		spin_unlock_irq(&tsk->sighand->siglock);
-+		utrace_quiescent(tsk);
-+		if (utrace->u.live.signal != &signal || signal.signr == 0)
++
++		utrace_quiescent(tsk, &signal);
++
++		/*
++		 * Noone wants us quiescent any more, we can take signals.
++		 * Unless we have a forced signal to take, back out to the
++		 * signal code to resynchronize after releasing the siglock.
++		 */
++		if (signal.signr == 0)
 +			/*
 +			 * This return value says to reacquire the siglock
 +			 * and check again.  This will check for a pending
 +			 * group stop and process it before coming back here.
 +			 */
 +			return -1;
-+		spin_lock_irq(&tsk->sighand->siglock);
-+	}
 +
-+	/*
-+	 * If a signal was injected previously, it could not use our
-+	 * stack space directly.  It had to allocate a data structure,
-+	 * which we can now copy out of and free.
-+	 */
-+	if (utrace->u.live.signal != &signal) {
-+		signal.signr = utrace->u.live.signal->signr;
-+		copy_siginfo(info, utrace->u.live.signal->info);
-+		if (utrace->u.live.signal->return_ka)
-+			*return_ka = *utrace->u.live.signal->return_ka;
-+		else
-+			signal.return_ka = NULL;
-+		kfree(utrace->u.live.signal);
++		spin_lock_irq(&tsk->sighand->siglock);
 +	}
-+	utrace->u.live.signal = NULL;
 +
 +	/*
 +	 * If a signal was injected, everything is in place now.  Go do it.
@@ -4499,6 +4588,13 @@
 +	ka = &tsk->sighand->action[signal.signr - 1];
 +	*return_ka = *ka;
 +
++	/*
++	 * We are never allowed to interfere with SIGKILL,
++	 * just punt after filling in *return_ka for our caller.
++	 */
++	if (signal.signr == SIGKILL)
++		return signal.signr;
++
 +	if (ka->sa.sa_handler == SIG_IGN) {
 +		event = UTRACE_EVENT(SIGNAL_IGN);
 +		action = UTRACE_SIGNAL_IGN;
@@ -4639,7 +4735,9 @@
 +
 +	ret = 0;
 +	signal = utrace->u.live.signal;
-+	if (signal == NULL) {
++	if (unlikely(target->exit_state))
++		ret = -ESRCH;
++	else if (signal == NULL) {
 +		ret = -ENOSYS;	/* XXX */
 +	}
 +	else if (signal->signr != 0)
@@ -7305,7 +7403,7 @@
  
 --- linux-2.6/init/Kconfig.utrace-ptrace-compat
 +++ linux-2.6/init/Kconfig
-@@ -511,6 +511,35 @@ config STOP_MACHINE
+@@ -512,6 +512,35 @@ config STOP_MACHINE
  	  Need stop_machine() primitive.
  endmenu
  
@@ -7644,11 +7742,11 @@
  
  	/* Set up the stack frame */
  	if (ka->sa.sa_flags & SA_SIGINFO)
-@@ -557,6 +535,17 @@ handle_signal(unsigned long sig, siginfo
+@@ -555,6 +533,15 @@ handle_signal(unsigned long sig, siginfo
+ 			sigaddset(&current->blocked,sig);
+ 		recalc_sigpending();
  		spin_unlock_irq(&current->sighand->siglock);
- 	}
- 
-+	if (ret) {
++
 +		/*
 +		 * Clear TF when entering the signal handler, but
 +		 * notify any tracer that was single-stepping it.
@@ -7657,11 +7755,9 @@
 +		 */
 +		regs->eflags &= ~TF_MASK;
 +		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+	}
-+
- 	return ret;
- }
+ 	}
  
+ 	return ret;
 --- linux-2.6/arch/i386/kernel/vm86.c.utrace-ptrace-compat
 +++ linux-2.6/arch/i386/kernel/vm86.c
 @@ -529,13 +529,6 @@ int handle_vm86_trap(struct kernel_vm86_
@@ -9470,16 +9566,15 @@
  #include <linux/module.h>
  
  #include <asm/sigcontext.h>
-@@ -461,6 +462,9 @@ static int handle_signal(unsigned long s
+@@ -459,6 +460,8 @@ static int handle_signal(unsigned long s
+ 			sigaddset(&current->blocked,sig);
+ 		recalc_sigpending();
  		spin_unlock_irq(&current->sighand->siglock);
++
++		tracehook_report_handle_signal(sig, ka, oldset, regs);
  	}
  
-+	if (ret)
-+		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+
  	return ret;
- }
- 
 --- linux-2.6/arch/powerpc/kernel/process.c.utrace-ptrace-compat
 +++ linux-2.6/arch/powerpc/kernel/process.c
 @@ -814,11 +814,6 @@ int sys_execve(unsigned long a0, unsigne
@@ -9563,15 +9658,15 @@
  /*
   * Note: it is necessary to treat pid and sig as unsigned ints, with the
   * corresponding cast to a signed int to insure that the proper conversion
-@@ -1218,5 +1271,8 @@ no_signal:
+@@ -1216,6 +1269,8 @@ no_signal:
+ 		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+ 		if (test_thread_flag(TIF_RESTORE_SIGMASK))
  			clear_thread_flag(TIF_RESTORE_SIGMASK);
++
++		tracehook_report_handle_signal(signr, &ka, oldset, regs);
  	}
  
-+	if (ret)
-+		tracehook_report_handle_signal(signr, &ka, oldset, regs);
-+
  	return ret;
- }
 --- linux-2.6/arch/powerpc/kernel/ptrace.c.utrace-ptrace-compat
 +++ linux-2.6/arch/powerpc/kernel/ptrace.c
 @@ -22,128 +22,239 @@
@@ -14186,16 +14281,15 @@
  #include <asm/ucontext.h>
  #include <asm/uaccess.h>
  #include <asm/lowcore.h>
-@@ -405,6 +406,9 @@ handle_signal(unsigned long sig, struct 
+@@ -403,6 +404,8 @@ handle_signal(unsigned long sig, struct 
+ 			sigaddset(&current->blocked,sig);
+ 		recalc_sigpending();
  		spin_unlock_irq(&current->sighand->siglock);
++
++		tracehook_report_handle_signal(sig, ka, oldset, regs);
  	}
  
-+	if (ret == 0) 
-+		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+
  	return ret;
- }
- 
 --- linux-2.6/arch/s390/kernel/compat_signal.c.utrace-ptrace-compat
 +++ linux-2.6/arch/s390/kernel/compat_signal.c
 @@ -28,6 +28,7 @@
@@ -14206,17 +14300,17 @@
  #include "compat_linux.h"
  #include "compat_ptrace.h"
  
-@@ -580,6 +581,10 @@ handle_signal32(unsigned long sig, struc
+@@ -579,7 +580,9 @@ handle_signal32(unsigned long sig, struc
+ 			sigaddset(&current->blocked,sig);
  		recalc_sigpending();
  		spin_unlock_irq(&current->sighand->siglock);
- 	}
 +
-+	if (ret == 0) 
 +		tracehook_report_handle_signal(sig, ka, oldset, regs);
+ 	}
 +
  	return ret;
  }
- 
+-
 --- linux-2.6/arch/s390/kernel/process.c.utrace-ptrace-compat
 +++ linux-2.6/arch/s390/kernel/process.c
 @@ -331,9 +331,6 @@ asmlinkage long sys_execve(struct pt_reg
@@ -15067,11 +15161,11 @@
  
  #ifdef CONFIG_IA32_EMULATION
  	if (test_thread_flag(TIF_IA32)) {
-@@ -417,6 +410,17 @@ handle_signal(unsigned long sig, siginfo
+@@ -415,6 +408,15 @@ handle_signal(unsigned long sig, siginfo
+ 			sigaddset(&current->blocked,sig);
+ 		recalc_sigpending();
  		spin_unlock_irq(&current->sighand->siglock);
- 	}
- 
-+	if (ret) {
++
 +		/*
 +		 * Clear TF when entering the signal handler, but
 +		 * notify any tracer that was single-stepping it.
@@ -15080,11 +15174,9 @@
 +		 */
 +		regs->eflags &= ~TF_MASK;
 +		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+	}
-+
- 	return ret;
- }
+ 	}
  
+ 	return ret;
 --- linux-2.6/arch/x86_64/kernel/process.c.utrace-ptrace-compat
 +++ linux-2.6/arch/x86_64/kernel/process.c
 @@ -636,11 +636,6 @@ long sys_execve(char __user *name, char 
@@ -16995,179 +17087,3 @@
 -	}
 +	tracehook_report_syscall(regs, leaving);
  }
-Index: linux-2.6.18.noarch/kernel/utrace.c
-===================================================================
---- linux-2.6.18.noarch.orig/kernel/utrace.c
-+++ linux-2.6.18.noarch/kernel/utrace.c
-@@ -155,6 +155,16 @@ remove_engine(struct utrace_attached_eng
- 	call_rcu(&engine->rhead, utrace_engine_free);
- }
- 
-+/*
-+ * This is pointed to by the utrace struct, but it's really a private
-+ * structure between utrace_get_signal and utrace_inject_signal.
-+ */
-+struct utrace_signal
-+{
-+	siginfo_t *const info;
-+	struct k_sigaction *return_ka;
-+	int signr;
-+};
- 
- /*
-  * Called with utrace locked, after remove_engine may have run.
-@@ -172,6 +182,11 @@ check_dead_utrace(struct task_struct *ts
- 		return utrace;
- 	}
- 
-+	if (utrace->u.live.signal && utrace->u.live.signal->signr != 0) {
-+		utrace_unlock(utrace);
-+		return utrace;
-+	}
-+
- 	utrace_unlock(utrace);
- 	rcu_utrace_free(utrace);
- 	return NULL;
-@@ -1083,19 +1098,6 @@ utrace_report_syscall(struct pt_regs *re
- 	check_quiescent(tsk, action);
- }
- 
--
--/*
-- * This is pointed to by the utrace struct, but it's really a private
-- * structure between utrace_get_signal and utrace_inject_signal.
-- */
--struct utrace_signal
--{
--	siginfo_t *const info;
--	struct k_sigaction *return_ka;
--	int signr;
--};
--
--
- // XXX copied from signal.c
- #ifdef SIGEMT
- #define M_SIGEMT	M(SIGEMT)
-@@ -1205,7 +1207,7 @@ utrace_get_signal(struct task_struct *ts
- 	if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
- 		spin_unlock_irq(&tsk->sighand->siglock);
- 		utrace_quiescent(tsk);
--		if (utrace->u.live.signal != &signal || signal.signr == 0)
-+		if (signal.signr == 0)
- 			/*
- 			 * This return value says to reacquire the siglock
- 			 * and check again.  This will check for a pending
-@@ -1324,6 +1326,9 @@ utrace_get_signal(struct task_struct *ts
- 		recalc_sigpending_tsk(tsk);
- 	}
- 
-+	if (tsk->utrace != utrace)
-+		rcu_utrace_free(utrace);
-+
- 	/*
- 	 * We express the chosen action to the signals code in terms
- 	 * of a representative signal whose default action does it.
-diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
-index ebc9976..0000000 100644  
---- a/arch/i386/kernel/signal.c
-+++ b/arch/i386/kernel/signal.c
-@@ -533,9 +533,7 @@ handle_signal(unsigned long sig, siginfo
- 			sigaddset(&current->blocked,sig);
- 		recalc_sigpending();
- 		spin_unlock_irq(&current->sighand->siglock);
--	}
- 
--	if (ret) {
- 		/*
- 		 * Clear TF when entering the signal handler, but
- 		 * notify any tracer that was single-stepping it.
-diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
-index a65dc89..0000000 100644  
---- a/arch/powerpc/kernel/signal_32.c
-+++ b/arch/powerpc/kernel/signal_32.c
-@@ -1217,10 +1217,9 @@ no_signal:
- 		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
- 		if (test_thread_flag(TIF_RESTORE_SIGMASK))
- 			clear_thread_flag(TIF_RESTORE_SIGMASK);
--	}
- 
--	if (ret)
- 		tracehook_report_handle_signal(signr, &ka, oldset, regs);
-+	}
- 
- 	return ret;
- }
-diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
-index d7b86c0..0000000 100644  
---- a/arch/powerpc/kernel/signal_64.c
-+++ b/arch/powerpc/kernel/signal_64.c
-@@ -460,10 +460,9 @@ static int handle_signal(unsigned long s
- 			sigaddset(&current->blocked,sig);
- 		recalc_sigpending();
- 		spin_unlock_irq(&current->sighand->siglock);
--	}
- 
--	if (ret)
- 		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+	}
- 
- 	return ret;
- }
-diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
-index 456cdf6..0000000 100644  
---- a/arch/s390/kernel/compat_signal.c
-+++ b/arch/s390/kernel/compat_signal.c
-@@ -580,10 +580,9 @@ handle_signal32(unsigned long sig, struc
- 			sigaddset(&current->blocked,sig);
- 		recalc_sigpending();
- 		spin_unlock_irq(&current->sighand->siglock);
--	}
- 
--	if (ret == 0) 
- 		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+	}
- 
- 	return ret;
- }
-diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
-index 7fa7492..0000000 100644  
---- a/arch/s390/kernel/signal.c
-+++ b/arch/s390/kernel/signal.c
-@@ -404,10 +404,9 @@ handle_signal(unsigned long sig, struct 
- 			sigaddset(&current->blocked,sig);
- 		recalc_sigpending();
- 		spin_unlock_irq(&current->sighand->siglock);
--	}
- 
--	if (ret == 0) 
- 		tracehook_report_handle_signal(sig, ka, oldset, regs);
-+	}
- 
- 	return ret;
- }
-diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
-index 683c4f0..0000000 100644  
---- a/arch/x86_64/kernel/signal.c
-+++ b/arch/x86_64/kernel/signal.c
-@@ -408,9 +408,7 @@ handle_signal(unsigned long sig, siginfo
- 			sigaddset(&current->blocked,sig);
- 		recalc_sigpending();
- 		spin_unlock_irq(&current->sighand->siglock);
--	}
- 
--	if (ret) {
- 		/*
- 		 * Clear TF when entering the signal handler, but
- 		 * notify any tracer that was single-stepping it.
---- a/kernel/utrace.c
-+++ b/kernel/utrace.c
-@@ -1268,6 +1268,9 @@ utrace_get_signal(struct task_struct *ts
- 	ka = &tsk->sighand->action[signal.signr - 1];
- 	*return_ka = *ka;
- 
-+	if (signal.signr == SIGKILL)
-+		return signal.signr;
-+
- 	if (ka->sa.sa_handler == SIG_IGN) {
- 		event = UTRACE_EVENT(SIGNAL_IGN);
- 		action = UTRACE_SIGNAL_IGN;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]