rpms/kernel/devel kernel.spec, 1.144, 1.145 linux-2.6-utrace-core.patch, 1.5, 1.6 linux-2.6-utrace-ptrace-compat.patch, 1.4, 1.5 linux-2.6-utrace-tracehook.patch, 1.8, 1.9

Roland McGrath (roland) fedora-extras-commits at redhat.com
Tue Sep 4 20:54:01 UTC 2007


Author: roland

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv8604

Modified Files:
	kernel.spec linux-2.6-utrace-core.patch 
	linux-2.6-utrace-ptrace-compat.patch 
	linux-2.6-utrace-tracehook.patch 
Log Message:
utrace update (#232837, #248532)


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.144
retrieving revision 1.145
diff -u -r1.144 -r1.145
--- kernel.spec	2 Sep 2007 05:40:37 -0000	1.144
+++ kernel.spec	4 Sep 2007 20:53:27 -0000	1.145
@@ -1789,6 +1789,9 @@
 
 
 %changelog
+* Tue Sep  4 2007 Roland McGrath <roland at redhat.com>
+- utrace update (#232837, #248532)
+
 * Sun Sep 02 2007 Dave Jones <davej at redhat.com>
 - Fix oops in IPv4.
 

linux-2.6-utrace-core.patch:

Index: linux-2.6-utrace-core.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-core.patch,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- linux-2.6-utrace-core.patch	21 Aug 2007 19:42:55 -0000	1.5
+++ linux-2.6-utrace-core.patch	4 Sep 2007 20:53:27 -0000	1.6
@@ -20,7 +20,7 @@
 ---
 
  kernel/Makefile                   |    1 
- kernel/utrace.c                   | 2263 +++++++++++++++++++++++++++++++++++++
+ kernel/utrace.c                   | 2344 +++++++++++++++++++++++++++++++++++++
  Documentation/utrace.txt          |  579 +++++++++
  Documentation/DocBook/Makefile    |    2 
  Documentation/DocBook/utrace.tmpl |   23 
@@ -28,7 +28,7 @@
  include/linux/utrace.h            |  544 +++++++++
  include/linux/sched.h             |    5 
  init/Kconfig                      |   20 
- 9 files changed, 3504 insertions(+), 18 deletions(-)
+ 9 files changed, 3585 insertions(+), 18 deletions(-)
  create kernel/utrace.c
  create Documentation/utrace.txt
  create Documentation/DocBook/utrace.tmpl
@@ -46,7 +46,7 @@
  # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
 --- linux-2.6/kernel/utrace.c
 +++ linux-2.6/kernel/utrace.c
-@@ -0,0 +1,2263 @@
+@@ -0,0 +1,2344 @@
 +/*
 + * utrace infrastructure interface for debugging user processes
 + *
@@ -522,7 +522,7 @@
 + */
 +struct utrace_attached_engine *
 +utrace_attach(struct task_struct *target, int flags,
-+	     const struct utrace_engine_ops *ops, void *data)
++	      const struct utrace_engine_ops *ops, void *data)
 +{
 +	struct utrace *utrace;
 +	struct utrace_attached_engine *engine;
@@ -624,10 +624,13 @@
 +EXPORT_SYMBOL_GPL(utrace_attach);
 +
 +/*
-+ * When an engine is detached, the target thread may still see it and make
-+ * callbacks until it quiesces.  We reset its event flags to just QUIESCE
-+ * and install a special ops vector whose callback is dead_engine_delete.
-+ * When the target thread quiesces, it can safely free the engine itself.
++ * When an engine is detached, the target thread may still see it
++ * and make callbacks until it quiesces.  We install a special ops
++ * vector whose callbacks are all dead_engine_delete.  When the
++ * target thread quiesces, it can safely free the engine itself.
++ * We must cover all callbacks in case of races between checking
++ * engine->flags and utrace_detach changing engine->ops.
++ * Only report_reap is never called due to a special case in utrace_reap.
 + */
 +static u32
 +dead_engine_delete(struct utrace_attached_engine *engine,
@@ -636,9 +639,38 @@
 +	return UTRACE_ACTION_DETACH;
 +}
 +
++/*
++ * Don't use .report_xxx = ... style here because this way makes it easier
++ * to be sure we're forced to have an initializer here for every member.
++ */
 +static const struct utrace_engine_ops dead_engine_ops =
 +{
-+	.report_quiesce = &dead_engine_delete
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 unsigned long, struct task_struct *)) &dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 pid_t)) &dead_engine_delete,
++	&dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 struct pt_regs *, u32, siginfo_t *,
++		 const struct k_sigaction *, struct k_sigaction *))
++	&dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 int)) &dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 const struct linux_binprm *, struct pt_regs *))
++	&dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 struct pt_regs *)) &dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 struct pt_regs *)) &dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++		 long, long *)) &dead_engine_delete,
++	(u32 (*)(struct utrace_attached_engine *, struct task_struct *))
++	&dead_engine_delete,
++	NULL,			/* report_reap */
++	NULL,			/* allow_access_process_vm */
++	NULL,			/* unsafe_exec */
++	NULL,			/* tracer_task */
 +};
 +
 +
@@ -844,9 +876,32 @@
 +		return ret;
 +	}
 +
-+	flags = engine->flags;
-+	engine->flags = UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_QUIESCE;
++	/*
++	 * This must work while the target thread races with us doing:
++	 *	if (engine->flags & UTRACE_EVENT(x)) REPORT(x, ...);
++	 * The REPORT macro uses smp_rmb() between checking engine->flags
++	 * and using engine->ops.  Here we change engine->ops first, then
++	 * use smp_wmb() before changing engine->flags.  This ensures it
++	 * can check the old flags before using the old ops, or check the
++	 * old flags before using the new ops, or check the new flags
++	 * before using the new ops, but can never check the new flags
++	 * before using the old ops.  Hence, dead_engine_ops might be used
++	 * with any old flags in place.  So, it has report_* callback
++	 * pointers for every event type.  Since it has to have those
++	 * anyway, we enable (for after any potential race) all the events
++	 * that have no overhead to enable.  We want it to get into that
++	 * callback and complete the detach ASAP.
++	 */
 +	rcu_assign_pointer(engine->ops, &dead_engine_ops);
++	smp_wmb();
++	flags = engine->flags;
++	engine->flags = (UTRACE_EVENT(QUIESCE)
++			 | UTRACE_EVENT(CLONE)
++			 | UTRACE_EVENT(VFORK_DONE)
++			 | UTRACE_EVENT(EXEC)
++			 | UTRACE_EVENT(EXIT)
++			 | UTRACE_EVENT(JCTL)
++			 | UTRACE_ACTION_QUIESCE);
 +
 +	if (quiesce(target, 1)) {
 +		remove_engine(engine, target, utrace);
@@ -971,7 +1026,7 @@
 +{
 +	struct utrace *utrace;
 +	int report;
-+	unsigned long old_flags, old_utrace_flags;
++	unsigned long old_flags, old_utrace_flags, set_utrace_flags;
 +	int ret = -EALREADY;
 +
 +#ifdef ARCH_HAS_SINGLE_STEP
@@ -1005,6 +1060,22 @@
 +	}
 +
 +	/*
++	 * When it's in TASK_STOPPED state, do not set UTRACE_EVENT(JCTL).
++	 * That bit indicates utrace_report_jctl has not run yet and so the
++	 * target cannot be considered quiescent.  But if the bit wasn't
++	 * already set, it can't be in running in there and really is
++	 * quiescent now in its existing job control stop.  We set
++	 * UTRACE_ACTION_QUIESCE to be sure that once it resumes it will
++	 * recompute its flags in utrace_quiescent.
++	 */
++	set_utrace_flags = flags;
++	if (((set_utrace_flags &~ old_utrace_flags) & UTRACE_EVENT(JCTL))
++	    && target->state == TASK_STOPPED) {
++		set_utrace_flags &= ~UTRACE_EVENT(JCTL);
++		set_utrace_flags |= UTRACE_ACTION_QUIESCE;
++	}
++
++	/*
 +	 * When setting these flags, it's essential that we really
 +	 * synchronize with exit_notify.  They cannot be set after
 +	 * exit_notify takes the tasklist_lock.  By holding the read
@@ -1014,20 +1085,20 @@
 +	 * knows positively that utrace_report_death will be called or
 +	 * that it won't.
 +	 */
-+	if ((flags &~ old_utrace_flags) & (UTRACE_ACTION_NOREAP
-+					   | DEATH_EVENTS)) {
++	if ((set_utrace_flags &~ old_utrace_flags) & (UTRACE_ACTION_NOREAP
++						      | DEATH_EVENTS)) {
 +		read_lock(&tasklist_lock);
 +		if (unlikely(target->exit_state)) {
 +			read_unlock(&tasklist_lock);
 +			spin_unlock(&utrace->lock);
 +			return ret;
 +		}
-+		target->utrace_flags |= flags;
++		target->utrace_flags |= set_utrace_flags;
 +		read_unlock(&tasklist_lock);
 +	}
 +
 +	engine->flags = flags;
-+	target->utrace_flags |= flags;
++	target->utrace_flags |= set_utrace_flags;
 +	ret = 0;
 +
 +	report = 0;
@@ -1149,10 +1220,20 @@
 +	return ret;
 +}
 +
-+#define REPORT(callback, ...) do { \
-+	u32 ret = (*rcu_dereference(engine->ops)->callback) \
-+		(engine, tsk, ##__VA_ARGS__); \
-+	action = update_action(tsk, utrace, engine, ret); \
++/*
++ * This macro is always used after checking engine->flags.
++ * The smp_rmb() here pairs with smp_wmb() in utrace_detach.
++ * engine->ops changes before engine->flags, so the flags we
++ * just tested properly enabled this report for the real ops,
++ * or harmlessly enabled it for dead_engine_ops.
++ */
++#define REPORT(callback, ...)						\
++	do {								\
++		u32 ret;						\
++		smp_rmb();						\
++		ret = (*rcu_dereference(engine->ops)->callback)		\
++			(engine, tsk, ##__VA_ARGS__);			\
++		action = update_action(tsk, utrace, engine, ret);	\
 +	} while (0)
 +
 +
@@ -3755,7 +3836,7 @@
 +#endif	/* linux/utrace.h */
 --- linux-2.6/include/linux/sched.h
 +++ linux-2.6/include/linux/sched.h
-@@ -1080,6 +1080,11 @@ struct task_struct {
+@@ -1081,6 +1081,11 @@ struct task_struct {
  	struct audit_context *audit_context;
  	seccomp_t seccomp;
  

linux-2.6-utrace-ptrace-compat.patch:

Index: linux-2.6-utrace-ptrace-compat.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-ptrace-compat.patch,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- linux-2.6-utrace-ptrace-compat.patch	21 Aug 2007 19:42:55 -0000	1.4
+++ linux-2.6-utrace-ptrace-compat.patch	4 Sep 2007 20:53:27 -0000	1.5
@@ -24,7 +24,7 @@
  arch/powerpc/lib/sstep.c        |    3 
  kernel/fork.c                   |    2 
  kernel/exit.c                   |   13 
- kernel/ptrace.c                 | 2054 +++++++++++++++++++++++++++++++++++++--
+ kernel/ptrace.c                 | 2055 +++++++++++++++++++++++++++++++++++++--
  kernel/sys_ni.c                 |    4 
  kernel/Makefile                 |    3 
  include/linux/sched.h           |    4 
@@ -32,7 +32,7 @@
  include/asm-x86_64/tracehook.h  |    1 
  include/asm-x86_64/ptrace-abi.h |    3 
  init/Kconfig                    |   15 
- 20 files changed, 2641 insertions(+), 780 deletions(-)
+ 20 files changed, 2642 insertions(+), 780 deletions(-)
  delete arch/powerpc/kernel/ptrace32.c
 
 --- linux-2.6/fs/proc/base.c
@@ -1331,7 +1331,7 @@
  		tsk = next_thread(tsk);
 --- linux-2.6/kernel/ptrace.c
 +++ linux-2.6/kernel/ptrace.c
-@@ -19,213 +19,2007 @@
+@@ -19,213 +19,2008 @@
  #include <linux/security.h>
  #include <linux/signal.h>
  #include <linux/syscalls.h>
@@ -1394,19 +1394,66 @@
 +};
 +
 +static const struct utrace_engine_ops ptrace_utrace_ops; /* Initialized below. */
+ 
+ /*
+- * Check that we have indeed attached to the thing..
++ * We use this bit in task_struct.exit_code of a ptrace'd task to indicate
++ * a ptrace stop.  It must not overlap with any bits used in real exit_code's.
++ * Those are (PTRACE_EVENT_* << 8) | 0xff.
+  */
+-int ptrace_check_attach(struct task_struct *child, int kill)
++#define PTRACE_TRAPPED_MASK	0x10000
++
 +
 +static void
 +ptrace_state_unlink(struct ptrace_state *state)
-+{
+ {
+-	return -ENOSYS;
 +	task_lock(state->parent);
 +	list_del_rcu(&state->entry);
 +	task_unlock(state->parent);
-+}
-+
+ }
+ 
+-static int may_attach(struct task_struct *task)
 +static struct ptrace_state *
 +ptrace_setup(struct task_struct *target, struct utrace_attached_engine *engine,
 +	     struct task_struct *parent, u8 options, int cap_sys_ptrace)
-+{
+ {
+-	/* May we inspect the given task?
+-	 * This check is used both for attaching with ptrace
+-	 * and for allowing access to sensitive information in /proc.
+-	 *
+-	 * ptrace_attach denies several cases that /proc allows
+-	 * because setting up the necessary parent/child relationship
+-	 * or halting the specified task is impossible.
+-	 */
+-	int dumpable = 0;
+-	/* Don't let security modules deny introspection */
+-	if (task == current)
+-		return 0;
+-	if (((current->uid != task->euid) ||
+-	     (current->uid != task->suid) ||
+-	     (current->uid != task->uid) ||
+-	     (current->gid != task->egid) ||
+-	     (current->gid != task->sgid) ||
+-	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+-		return -EPERM;
+-	smp_rmb();
+-	if (task->mm)
+-		dumpable = get_dumpable(task->mm);
+-	if (!dumpable && !capable(CAP_SYS_PTRACE))
+-		return -EPERM;
+-
+-	return security_ptrace(current, task);
+-}
+-
+-int ptrace_may_attach(struct task_struct *task)
+-{
+-	int err;
+-	task_lock(task);
+-	err = may_attach(task);
+-	task_unlock(task);
+-	return !err;
 +	struct ptrace_state *state;
 +
 +	NO_LOCKS;
@@ -1466,17 +1513,14 @@
 +	BUG_ON(state->rcu.next);
 +	call_rcu(&state->rcu, ptrace_state_free);
 +}
- 
- /*
-- * Check that we have indeed attached to the thing..
++
++/*
 + * Update the tracing engine state to match the new ptrace state.
-  */
--int ptrace_check_attach(struct task_struct *child, int kill)
++ */
 +static int __must_check
 +ptrace_update(struct task_struct *target, struct ptrace_state *state,
 +	      unsigned long flags, int from_stopped)
- {
--	return -ENOSYS;
++{
 +	int ret;
 +
 +	START_CHECK;
@@ -1541,9 +1585,8 @@
 +	END_CHECK;
 +
 +	return ret;
- }
- 
--static int may_attach(struct task_struct *task)
++}
++
 +/*
 + * This does ptrace_update and also installs state in engine->data.
 + * Only after utrace_set_flags succeeds (in ptrace_update) inside
@@ -1555,42 +1598,7 @@
 + */
 +static int __must_check
 +ptrace_setup_finish(struct task_struct *target, struct ptrace_state *state)
- {
--	/* May we inspect the given task?
--	 * This check is used both for attaching with ptrace
--	 * and for allowing access to sensitive information in /proc.
--	 *
--	 * ptrace_attach denies several cases that /proc allows
--	 * because setting up the necessary parent/child relationship
--	 * or halting the specified task is impossible.
--	 */
--	int dumpable = 0;
--	/* Don't let security modules deny introspection */
--	if (task == current)
--		return 0;
--	if (((current->uid != task->euid) ||
--	     (current->uid != task->suid) ||
--	     (current->uid != task->uid) ||
--	     (current->gid != task->egid) ||
--	     (current->gid != task->sgid) ||
--	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
--		return -EPERM;
--	smp_rmb();
--	if (task->mm)
--		dumpable = get_dumpable(task->mm);
--	if (!dumpable && !capable(CAP_SYS_PTRACE))
--		return -EPERM;
--
--	return security_ptrace(current, task);
--}
--
--int ptrace_may_attach(struct task_struct *task)
--{
--	int err;
--	task_lock(task);
--	err = may_attach(task);
--	task_unlock(task);
--	return !err;
++{
 +	int ret;
 +
 +	NO_LOCKS;
@@ -1607,12 +1615,11 @@
 +	NO_LOCKS;
 +
 +	return ret;
- }
- 
--int ptrace_attach(struct task_struct *task)
++}
++
 +
 +static int ptrace_traceme(void)
- {
++{
 +	struct utrace_attached_engine *engine;
 +	struct ptrace_state *state;
 +	int retval;
@@ -1664,10 +1671,11 @@
 +	NO_LOCKS;
 +
 +	return retval;
-+}
-+
+ }
+ 
+-int ptrace_attach(struct task_struct *task)
 +static int ptrace_attach(struct task_struct *task)
-+{
+ {
 +	struct utrace_attached_engine *engine;
 +	struct ptrace_state *state;
  	int retval;
@@ -1685,9 +1693,8 @@
 -	retval = may_attach(task);
 -	if (retval)
 +	if (!task->mm)		/* kernel threads */
- 		goto bad;
- 
--	retval = -ENOSYS;
++		goto bad;
++
 +	pr_debug("%d ptrace_attach %d state %lu exit_code %x\n",
 +		 current->pid, task->pid, task->state, task->exit_code);
 +
@@ -1699,9 +1706,10 @@
 +		retval = PTR_ERR(engine);
 +		if (retval == -EEXIST)
 +			retval = -EPERM;
-+		goto bad;
+ 		goto bad;
 +	}
-+
+ 
+-	retval = -ENOSYS;
 +	pr_debug("%d ptrace_attach %d after utrace_attach: %lu exit_code %x\n",
 +		 current->pid, task->pid, task->state, task->exit_code);
 +
@@ -1735,8 +1743,6 @@
 +	if (retval)
 +		(void) utrace_detach(task, engine);
 +	else {
-+		int stopped = 0;
-+
 +		NO_LOCKS;
 +
 +		/*
@@ -1746,48 +1752,14 @@
 +		 * We cannot call into the signal code if it's dead.
 +		 */
 +		read_lock(&tasklist_lock);
-+		if (likely(!task->exit_state)) {
++		if (likely(!task->exit_state))
 +			force_sig_specific(SIGSTOP, task);
-+
-+			spin_lock_irq(&task->sighand->siglock);
-+			stopped = (task->state == TASK_STOPPED);
-+			spin_unlock_irq(&task->sighand->siglock);
-+		}
 +		read_unlock(&tasklist_lock);
 +
-+		if (stopped) {
-+			const struct utrace_regset *regset;
-+
-+			/*
-+			 * Set QUIESCE immediately, so we can allow
-+			 * ptrace requests while he's in TASK_STOPPED.
-+			 */
-+			retval = ptrace_update(task, state, /* XXX child death+other thread waits race could have freed state already */
-+					       UTRACE_ACTION_QUIESCE, 0);
-+			if (retval)
-+				/*
-+				 * Anything is possible here.  It might not
-+				 * really have been quiescent yet.  It
-+				 * might have just woken up and died.
-+				 */
-+				BUG_ON(retval != -ESRCH && retval != -EALREADY);
-+			retval = 0;
-+
-+			/*
-+			 * Do now the regset 0 writeback that we do on every
-+			 * stop, since it's never been done.  On register
-+			 * window machines, this makes sure the user memory
-+			 * backing the register data is up to date.
-+			 */
-+			regset = utrace_regset(task, engine,
-+					       utrace_native_view(task), 0);
-+			if (regset->writeback)
-+				(*regset->writeback)(task, regset, 1);
-+		}
-+
 +		pr_debug("%d ptrace_attach %d complete (%sstopped)"
 +			 " state %lu code %x",
-+			 current->pid, task->pid, stopped ? "" : "not ",
++			 current->pid, task->pid,
++			 task->state == TASK_STOPPED ? "" : "not ",
 +			 task->state, task->exit_code);
 +	}
  
@@ -2584,13 +2556,13 @@
 +	return ret;
  }
 +#endif
++
  
 -/**
 - * ptrace_traceme  --  helper for PTRACE_TRACEME
 - *
 - * Performs checks and sets PT_PTRACED.
 - * Should be used by all ptrace implementations for PTRACE_TRACEME.
-+
 +/*
 + * Detach the zombie being reported for wait.
   */
@@ -2752,7 +2724,29 @@
 +		 * check fails we are sure to get a wakeup if it stops.
 +		 */
 +		exit_code = xchg(&p->exit_code, 0);
-+		if (exit_code)
++		if (exit_code & PTRACE_TRAPPED_MASK)
++			goto found;
++
++		/*
++		 * If p was in job-control stop (TASK_STOPPED) rather than
++		 * ptrace stop (TASK_TRACED), then SIGCONT can asynchronously
++		 * clear it back to TASK_RUNNING.  Until it gets scheduled
++		 * and clears its own ->exit_code, our xchg below will see
++		 * its stop signal.  But, we must not report it if it's no
++		 * longer in TASK_STOPPED, as vanilla wait would not--the
++		 * caller can tell if it sent the SIGCONT before calling
++		 * wait.  We must somehow distinguish this from the case
++		 * where p is in TASK_RUNNING with p->exit_code set because
++		 * it is on its way to entering TASK_TRACED (QUIESCE) for our
++		 * stop.  So, ptrace_report sets the PTRACE_TRAPPED_MASK bit
++		 * in exit_code when it's setting QUIESCE.  For a job control
++		 * control stop, that bit will never have been set.  Since
++		 * the bit's not set now, we should only report right now if
++		 * p is still stopped.  For this case we are protected by
++		 * races the same wait that vanilla do_wait (exit.c) is:
++		 * wait_chldexit is woken after p->state is set to TASK_STOPPED.
++		 */
++		if (p->state == TASK_STOPPED)
 +			goto found;
 +
 +		// XXX should handle WCONTINUED
@@ -2803,6 +2797,7 @@
 +	}
 +	else {
 +		why = CLD_TRAPPED;
++		exit_code &= ~PTRACE_TRAPPED_MASK;
 +		status = exit_code;
 +		exit_code = (status << 8) | 0x7f;
 +	}
@@ -2981,8 +2976,14 @@
 +	 */
 +	utrace_set_flags(tsk, engine, engine->flags | UTRACE_ACTION_QUIESCE);
 +
++	/*
++	 * The PTRACE_TRAPPED_MASK bit distinguishes to ptrace_do_wait that
++	 * this is a ptrace report, so we expect to enter TASK_TRACED but
++	 * might not be there yet when examined.
++	 */
 +	BUG_ON(code == 0);
-+	tsk->exit_code = code;
++	WARN_ON(code &~ 0x7ff);
++	tsk->exit_code = code | PTRACE_TRAPPED_MASK;
 +	do_notify(tsk, state->parent, CLD_TRAPPED);
 +
 +	pr_debug("%d ptrace_report quiescing exit_code %x\n",
@@ -3178,15 +3179,13 @@
 +	NO_LOCKS;
 +	printk(KERN_ERR "ptrace out of memory, lost child %d of %d",
 +	       child->pid, parent->pid);
- }
- 
--int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
++}
++
 +static u32
 +ptrace_report_clone(struct utrace_attached_engine *engine,
 +		    struct task_struct *parent,
 +		    unsigned long clone_flags, struct task_struct *child)
- {
--	int copied;
++{
 +	int event, option;
 +	struct ptrace_state *state;
 +
@@ -3217,9 +3216,7 @@
 +	}
 +	else
 +		event = 0;
- 
--	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
--	return (copied == sizeof(data)) ? 0 : -EIO;
++
 +	if (!(clone_flags & CLONE_UNTRACED)
 +	    && (event || (clone_flags & CLONE_PTRACE))) {
 +		/*
@@ -3279,7 +3276,7 @@
 +	state->have_eventmsg = 0;
 +	state->u.siginfo = info;
 +	return ptrace_report(engine, tsk, state, signo) | UTRACE_SIGNAL_IGN;
- }
++}
 +
 +static u32
 +ptrace_report_jctl(struct utrace_attached_engine *engine,
@@ -3370,12 +3367,14 @@
 +			   struct task_struct *tsk, struct pt_regs *regs)
 +{
 +	return ptrace_report_syscall(engine, tsk, regs, 0);
-+}
-+
+ }
+ 
+-int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
 +static u32
 +ptrace_report_exit(struct utrace_attached_engine *engine,
 +		   struct task_struct *tsk, long orig_code, long *code)
-+{
+ {
+-	int copied;
 +	struct ptrace_state *state = get_ptrace_state(engine, tsk);
 +	if (unlikely(state == NULL))
 +		return UTRACE_ACTION_RESUME;
@@ -3402,9 +3401,11 @@
 +	}
 +
 +	END_CHECK;
-+
+ 
+-	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+-	return (copied == sizeof(data)) ? 0 : -EIO;
 +	return unsafe;
-+}
+ }
 +
 +static struct task_struct *
 +ptrace_tracer_task(struct utrace_attached_engine *engine,
@@ -3503,7 +3504,7 @@
  # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
 --- linux-2.6/include/linux/sched.h
 +++ linux-2.6/include/linux/sched.h
-@@ -1178,6 +1178,10 @@ struct task_struct {
+@@ -1179,6 +1179,10 @@ struct task_struct {
  	atomic_t fs_excl;	/* holding fs exclusive resources */
  	struct rcu_head rcu;
  

linux-2.6-utrace-tracehook.patch:

Index: linux-2.6-utrace-tracehook.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-tracehook.patch,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- linux-2.6-utrace-tracehook.patch	1 Sep 2007 00:32:50 -0000	1.8
+++ linux-2.6-utrace-tracehook.patch	4 Sep 2007 20:53:27 -0000	1.9
@@ -221,7 +221,7 @@
  		p->uid, p->euid, p->suid, p->fsuid,
  		p->gid, p->egid, p->sgid, p->fsgid);
  
-@@ -427,7 +433,7 @@ static int do_task_stat(struct task_stru
+@@ -441,7 +447,7 @@ static int do_task_stat(struct task_stru
  
  		sid = signal_session(sig);
  		pgid = process_group(task);
@@ -257,7 +257,7 @@
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/syscalls.h>
-@@ -1161,13 +1161,7 @@ EXPORT_SYMBOL(prepare_binprm);
+@@ -1153,13 +1153,7 @@ EXPORT_SYMBOL(prepare_binprm);
  
  static int unsafe_exec(struct task_struct *p)
  {
@@ -272,7 +272,7 @@
  	if (atomic_read(&p->fs->count) > 1 ||
  	    atomic_read(&p->files->count) > 1 ||
  	    atomic_read(&p->sighand->count) > 1)
-@@ -1311,6 +1305,7 @@ int search_binary_handler(struct linux_b
+@@ -1303,6 +1297,7 @@ int search_binary_handler(struct linux_b
  				bprm->file = NULL;
  				current->did_exec = 1;
  				proc_exec_connector(current);
@@ -382,7 +382,7 @@
  			}
  		}
  		tsec->sid = sid;
-@@ -2754,11 +2760,6 @@ static int selinux_task_alloc_security(s
+@@ -2757,11 +2763,6 @@ static int selinux_task_alloc_security(s
  	tsec2->keycreate_sid = tsec1->keycreate_sid;
  	tsec2->sockcreate_sid = tsec1->sockcreate_sid;
  
@@ -394,7 +394,7 @@
  	return 0;
  }
  
-@@ -4541,6 +4542,7 @@ static int selinux_setprocattr(struct ta
+@@ -4544,6 +4545,7 @@ static int selinux_setprocattr(struct ta
  			       char *name, void *value, size_t size)
  {
  	struct task_security_struct *tsec;
@@ -402,7 +402,7 @@
  	u32 sid = 0;
  	int error;
  	char *str = value;
-@@ -4629,18 +4631,24 @@ static int selinux_setprocattr(struct ta
+@@ -4632,18 +4634,24 @@ static int selinux_setprocattr(struct ta
  		/* Check for ptracing, and update the task SID if ok.
  		   Otherwise, leave SID unchanged and fail. */
  		task_lock(p);
@@ -2621,7 +2621,7 @@
  		/*
  		 * This signal will be fatal to the whole group.
  		 */
-@@ -1448,8 +1445,7 @@ void do_notify_parent(struct task_struct
+@@ -1447,8 +1444,7 @@ void do_notify_parent(struct task_struct
   	/* do_notify_parent_cldstop should have been called instead.  */
   	BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
  
@@ -2631,7 +2631,7 @@
  
  	info.si_signo = sig;
  	info.si_errno = 0;
-@@ -1474,7 +1470,7 @@ void do_notify_parent(struct task_struct
+@@ -1473,7 +1469,7 @@ void do_notify_parent(struct task_struct
  
  	psig = tsk->parent->sighand;
  	spin_lock_irqsave(&psig->siglock, flags);
@@ -2640,7 +2640,7 @@
  	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
  	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
  		/*
-@@ -1502,20 +1498,13 @@ void do_notify_parent(struct task_struct
+@@ -1501,20 +1497,13 @@ void do_notify_parent(struct task_struct
  	spin_unlock_irqrestore(&psig->siglock, flags);
  }
  
@@ -2662,7 +2662,7 @@
  	info.si_signo = SIGCHLD;
  	info.si_errno = 0;
  	info.si_pid = tsk->pid;
-@@ -1540,6 +1529,15 @@ static void do_notify_parent_cldstop(str
+@@ -1539,6 +1528,15 @@ static void do_notify_parent_cldstop(str
   		BUG();
   	}
  
@@ -2678,7 +2678,7 @@
  	sighand = parent->sighand;
  	spin_lock_irqsave(&sighand->siglock, flags);
  	if (sighand->action[SIGCHLD-1].sa.sa_handler != SIG_IGN &&
-@@ -1552,107 +1550,6 @@ static void do_notify_parent_cldstop(str
+@@ -1551,107 +1549,6 @@ static void do_notify_parent_cldstop(str
  	spin_unlock_irqrestore(&sighand->siglock, flags);
  }
  
@@ -2786,7 +2786,7 @@
  static void
  finish_stop(int stop_count)
  {
-@@ -1661,7 +1558,7 @@ finish_stop(int stop_count)
+@@ -1660,7 +1557,7 @@ finish_stop(int stop_count)
  	 * a group stop in progress and we are the last to stop,
  	 * report to the parent.  When ptraced, every thread reports itself.
  	 */
@@ -2795,7 +2795,7 @@
  		read_lock(&tasklist_lock);
  		do_notify_parent_cldstop(current, CLD_STOPPED);
  		read_unlock(&tasklist_lock);
-@@ -1788,44 +1685,24 @@ relock:
+@@ -1787,44 +1684,24 @@ relock:
  		    handle_group_stop())
  			goto relock;
  
@@ -2856,7 +2856,7 @@
  		if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
  			continue;
  		if (ka->sa.sa_handler != SIG_DFL) {
-@@ -1874,7 +1751,7 @@ relock:
+@@ -1873,7 +1750,7 @@ relock:
  				spin_lock_irq(&current->sighand->siglock);
  			}
  
@@ -2865,7 +2865,7 @@
  				/* It released the siglock.  */
  				goto relock;
  			}
-@@ -1903,13 +1780,13 @@ relock:
+@@ -1902,13 +1779,13 @@ relock:
  			 * first and our do_group_exit call below will use
  			 * that value and ignore the one we pass it.
  			 */
@@ -2881,7 +2881,7 @@
  		/* NOTREACHED */
  	}
  	spin_unlock_irq(&current->sighand->siglock);
-@@ -1921,7 +1798,6 @@ EXPORT_SYMBOL_GPL(dequeue_signal);
+@@ -1920,7 +1797,6 @@ EXPORT_SYMBOL_GPL(dequeue_signal);
  EXPORT_SYMBOL(flush_signals);
  EXPORT_SYMBOL(force_sig);
  EXPORT_SYMBOL(kill_proc);
@@ -2902,12 +2902,12 @@
  	stats->ac_stime	 = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
 --- linux-2.6/kernel/sys.c
 +++ linux-2.6/kernel/sys.c
-@@ -1470,7 +1470,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
+@@ -1469,7 +1469,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
  	if (!thread_group_leader(p))
  		goto out;
  
 -	if (p->real_parent->tgid == group_leader->tgid) {
-+	if (p->parent == group_leader) {
++	if (p->parent->tgid == group_leader->tgid) {
  		err = -EPERM;
  		if (task_session(p) != task_session(group_leader))
  			goto out;
@@ -3100,7 +3100,7 @@
  
 --- linux-2.6/include/linux/sched.h
 +++ linux-2.6/include/linux/sched.h
-@@ -938,7 +938,6 @@ struct task_struct {
+@@ -939,7 +939,6 @@ struct task_struct {
  	void *stack;
  	atomic_t usage;
  	unsigned int flags;	/* per process flags, defined below */
@@ -3108,7 +3108,7 @@
  
  	int lock_depth;		/* BKL lock depth */
  
-@@ -972,12 +971,6 @@ struct task_struct {
+@@ -973,12 +972,6 @@ struct task_struct {
  #endif
  
  	struct list_head tasks;
@@ -3121,7 +3121,7 @@
  
  	struct mm_struct *mm, *active_mm;
  
-@@ -997,15 +990,13 @@ struct task_struct {
+@@ -998,15 +991,13 @@ struct task_struct {
  	unsigned long stack_canary;
  #endif
  	/* 
@@ -3139,7 +3139,7 @@
  	 */
  	struct list_head children;	/* list of my children */
  	struct list_head sibling;	/* linkage in my parent's children list */
-@@ -1145,8 +1136,6 @@ struct task_struct {
+@@ -1146,8 +1137,6 @@ struct task_struct {
  
  	struct io_context *io_context;
  
@@ -3148,7 +3148,7 @@
  /*
   * current io wait handle: wait queue entry to use for io waits
   * If this thread is processing aio, this points at the waitqueue
-@@ -1523,6 +1512,7 @@ extern int kill_pgrp(struct pid *pid, in
+@@ -1526,6 +1515,7 @@ extern int kill_pgrp(struct pid *pid, in
  extern int kill_pid(struct pid *pid, int sig, int priv);
  extern int kill_proc_info(int, struct siginfo *, pid_t);
  extern void do_notify_parent(struct task_struct *, int);




More information about the scm-commits mailing list