rpms/kernel/F-7 kernel-2.6.spec, 1.3337, 1.3338 linux-2.6-utrace-core.patch, 1.3, 1.4 linux-2.6-utrace-ptrace-compat.patch, 1.3, 1.4 linux-2.6-utrace-regset.patch, 1.3, 1.4

Chuck Ebbert (cebbert) fedora-extras-commits at redhat.com
Wed Sep 5 16:19:28 UTC 2007


Author: cebbert

Update of /cvs/pkgs/rpms/kernel/F-7
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv15753

Modified Files:
	kernel-2.6.spec linux-2.6-utrace-core.patch 
	linux-2.6-utrace-ptrace-compat.patch 
	linux-2.6-utrace-regset.patch 
Log Message:
* Wed Sep 05 2007 Chuck Ebbert <cebbert at redhat.com>
- Update utrace



Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-7/kernel-2.6.spec,v
retrieving revision 1.3337
retrieving revision 1.3338
diff -u -r1.3337 -r1.3338
--- kernel-2.6.spec	30 Aug 2007 21:54:14 -0000	1.3337
+++ kernel-2.6.spec	5 Sep 2007 16:18:54 -0000	1.3338
@@ -2306,6 +2306,9 @@
 %endif
 
 %changelog
+* Wed Sep 05 2007 Chuck Ebbert <cebbert at redhat.com>
+- Update utrace
+
 * Thu Aug 30 2007 John W. Linville <linville at redhat.com>
 - Update bits from wireless-2.6 and wireless-dev
 

linux-2.6-utrace-core.patch:

Index: linux-2.6-utrace-core.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-7/linux-2.6-utrace-core.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- linux-2.6-utrace-core.patch	20 Jul 2007 18:48:03 -0000	1.3
+++ linux-2.6-utrace-core.patch	5 Sep 2007 16:18:54 -0000	1.4
@@ -24,11 +24,11 @@
  Documentation/utrace.txt          |  579 +++++++++
  include/linux/sched.h             |    5 
  include/linux/tracehook.h         |   85 +
- include/linux/utrace.h            |  544 +++++++++
+ include/linux/utrace.h            |  544 ++++++++
  init/Kconfig                      |   18 
  kernel/Makefile                   |    1 
- kernel/utrace.c                   | 2263 ++++++++++++++++++++++++++++++++++++++
- 9 files changed, 3502 insertions(+), 18 deletions(-)
+ kernel/utrace.c                   | 2344 ++++++++++++++++++++++++++++++++++++++
+ 9 files changed, 3583 insertions(+), 18 deletions(-)
  create kernel/utrace.c
  create Documentation/utrace.txt
  create Documentation/DocBook/utrace.tmpl
@@ -50,7 +50,7 @@
 ===================================================================
 --- /dev/null
 +++ b/kernel/utrace.c
-@@ -0,0 +1,2263 @@
+@@ -0,0 +1,2344 @@
 +/*
 + * utrace infrastructure interface for debugging user processes
 + *
@@ -526,7 +526,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;
@@ -628,10 +628,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,
@@ -640,9 +643,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 */
 +};
 +
 +
@@ -848,9 +880,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);
@@ -975,7 +1030,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
@@ -1009,6 +1064,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
@@ -1018,20 +1089,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;
@@ -1153,10 +1224,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)
 +
 +
@@ -2951,7 +3032,7 @@
  struct linux_binprm;
  struct pt_regs;
  
-@@ -342,6 +343,7 @@ utrace_regset_copyin_ignore(unsigned int
+@@ -353,6 +354,7 @@ utrace_regset_copyin_ignore(unsigned int
   */
  static inline void tracehook_init_task(struct task_struct *child)
  {
@@ -2959,7 +3040,7 @@
  }
  
  /*
-@@ -350,6 +352,9 @@ static inline void tracehook_init_task(s
+@@ -361,6 +363,9 @@ static inline void tracehook_init_task(s
   */
  static inline void tracehook_release_task(struct task_struct *p)
  {
@@ -2969,7 +3050,7 @@
  }
  
  /*
-@@ -359,7 +364,20 @@ static inline void tracehook_release_tas
+@@ -370,7 +375,20 @@ static inline void tracehook_release_tas
   */
  static inline int tracehook_check_released(struct task_struct *p)
  {
@@ -2991,7 +3072,7 @@
  }
  
  /*
-@@ -370,7 +388,7 @@ static inline int tracehook_check_releas
+@@ -381,7 +399,7 @@ static inline int tracehook_check_releas
  static inline int tracehook_notify_cldstop(struct task_struct *tsk,
  					   const siginfo_t *info)
  {
@@ -3000,7 +3081,7 @@
  }
  
  /*
-@@ -384,7 +402,11 @@ static inline int tracehook_notify_cldst
+@@ -395,7 +413,11 @@ static inline int tracehook_notify_cldst
  static inline int tracehook_notify_death(struct task_struct *tsk,
  					 int *noreap, void **death_cookie)
  {
@@ -3013,7 +3094,7 @@
  	*noreap = 0;
  	return 0;
  }
-@@ -397,7 +419,8 @@ static inline int tracehook_notify_death
+@@ -408,7 +430,8 @@ static inline int tracehook_notify_death
  static inline int tracehook_consider_fatal_signal(struct task_struct *tsk,
  						  int sig)
  {
@@ -3023,7 +3104,7 @@
  }
  
  /*
-@@ -410,7 +433,7 @@ static inline int tracehook_consider_ign
+@@ -421,7 +444,7 @@ static inline int tracehook_consider_ign
  						    int sig,
  						    void __user *handler)
  {
@@ -3032,7 +3113,7 @@
  }
  
  
-@@ -421,7 +444,7 @@ static inline int tracehook_consider_ign
+@@ -432,7 +455,7 @@ static inline int tracehook_consider_ign
   */
  static inline int tracehook_induce_sigpending(struct task_struct *tsk)
  {
@@ -3041,7 +3122,7 @@
  }
  
  /*
-@@ -436,6 +459,8 @@ static inline int tracehook_get_signal(s
+@@ -447,6 +470,8 @@ static inline int tracehook_get_signal(s
  				       siginfo_t *info,
  				       struct k_sigaction *return_ka)
  {
@@ -3050,7 +3131,7 @@
  	return 0;
  }
  
-@@ -448,6 +473,8 @@ static inline int tracehook_get_signal(s
+@@ -459,6 +484,8 @@ static inline int tracehook_get_signal(s
   */
  static inline int tracehook_finish_stop(int last_one)
  {
@@ -3059,7 +3140,7 @@
  	return 0;
  }
  
-@@ -459,7 +486,7 @@ static inline int tracehook_finish_stop(
+@@ -470,7 +497,7 @@ static inline int tracehook_finish_stop(
   */
  static inline int tracehook_inhibit_wait_stopped(struct task_struct *child)
  {
@@ -3068,7 +3149,7 @@
  }
  
  /*
-@@ -469,7 +496,7 @@ static inline int tracehook_inhibit_wait
+@@ -480,7 +507,7 @@ static inline int tracehook_inhibit_wait
   */
  static inline int tracehook_inhibit_wait_zombie(struct task_struct *child)
  {
@@ -3077,7 +3158,7 @@
  }
  
  /*
-@@ -479,7 +506,7 @@ static inline int tracehook_inhibit_wait
+@@ -490,7 +517,7 @@ static inline int tracehook_inhibit_wait
   */
  static inline int tracehook_inhibit_wait_continued(struct task_struct *child)
  {
@@ -3086,7 +3167,7 @@
  }
  
  
-@@ -489,13 +516,9 @@ static inline int tracehook_inhibit_wait
+@@ -500,13 +527,9 @@ static inline int tracehook_inhibit_wait
   */
  static inline int tracehook_unsafe_exec(struct task_struct *tsk)
  {
@@ -3102,7 +3183,7 @@
  }
  
  /*
-@@ -510,6 +533,8 @@ static inline int tracehook_unsafe_exec(
+@@ -521,6 +544,8 @@ static inline int tracehook_unsafe_exec(
   */
  static inline struct task_struct *tracehook_tracer_task(struct task_struct *p)
  {
@@ -3111,7 +3192,7 @@
  	return NULL;
  }
  
-@@ -521,6 +546,8 @@ static inline int tracehook_allow_access
+@@ -532,6 +557,8 @@ static inline int tracehook_allow_access
  {
  	if (tsk == current)
  		return 1;
@@ -3120,7 +3201,7 @@
  	return 0;
  }
  
-@@ -532,7 +559,7 @@ static inline int tracehook_allow_access
+@@ -543,7 +570,7 @@ static inline int tracehook_allow_access
   */
  static inline int tracehook_expect_breakpoints(struct task_struct *tsk)
  {
@@ -3129,7 +3210,7 @@
  }
  
  
-@@ -555,6 +582,10 @@ static inline int tracehook_expect_break
+@@ -566,6 +593,10 @@ static inline int tracehook_expect_break
  static inline void tracehook_report_death(struct task_struct *tsk,
  					  int exit_state, void *death_cookie)
  {
@@ -3140,7 +3221,7 @@
  }
  
  /*
-@@ -564,14 +595,18 @@ static inline void tracehook_report_deat
+@@ -575,14 +606,18 @@ static inline void tracehook_report_deat
   */
  static inline void tracehook_report_delayed_group_leader(struct task_struct *p)
  {
@@ -3160,7 +3241,7 @@
  }
  
  /*
-@@ -580,6 +615,8 @@ static inline void tracehook_report_exec
+@@ -591,6 +626,8 @@ static inline void tracehook_report_exec
   */
  static inline void tracehook_report_exit(long *exit_code)
  {
@@ -3169,7 +3250,7 @@
  }
  
  /*
-@@ -594,6 +631,8 @@ static inline void tracehook_report_exit
+@@ -605,6 +642,8 @@ static inline void tracehook_report_exit
  static inline void tracehook_report_clone(unsigned long clone_flags,
  					  struct task_struct *child)
  {
@@ -3178,7 +3259,7 @@
  }
  
  /*
-@@ -607,6 +646,8 @@ static inline void tracehook_report_clon
+@@ -618,6 +657,8 @@ static inline void tracehook_report_clon
  						   pid_t pid,
  						   struct task_struct *child)
  {
@@ -3187,7 +3268,7 @@
  }
  
  /*
-@@ -618,6 +659,8 @@ static inline void tracehook_report_clon
+@@ -629,6 +670,8 @@ static inline void tracehook_report_clon
  static inline void tracehook_report_vfork_done(struct task_struct *child,
  					       pid_t child_pid)
  {
@@ -3196,7 +3277,7 @@
  }
  
  /*
-@@ -625,6 +668,9 @@ static inline void tracehook_report_vfor
+@@ -636,6 +679,9 @@ static inline void tracehook_report_vfor
   */
  static inline void tracehook_report_syscall(struct pt_regs *regs, int is_exit)
  {
@@ -3206,7 +3287,7 @@
  }
  
  /*
-@@ -644,6 +690,11 @@ static inline void tracehook_report_hand
+@@ -655,6 +701,11 @@ static inline void tracehook_report_hand
  						  const sigset_t *oldset,
  						  struct pt_regs *regs)
  {

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

Index: linux-2.6-utrace-ptrace-compat.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-7/linux-2.6-utrace-ptrace-compat.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- linux-2.6-utrace-ptrace-compat.patch	20 Jul 2007 18:48:03 -0000	1.3
+++ linux-2.6-utrace-ptrace-compat.patch	5 Sep 2007 16:18:54 -0000	1.4
@@ -28,9 +28,9 @@
  kernel/Makefile                 |    3 
  kernel/exit.c                   |   13 
  kernel/fork.c                   |    2 
- kernel/ptrace.c                 | 2051 +++++++++++++++++++++++++++++++++++++---
+ kernel/ptrace.c                 | 2052 +++++++++++++++++++++++++++++++++++++---
  kernel/sys_ni.c                 |    4 
- 18 files changed, 2632 insertions(+), 174 deletions(-)
+ 18 files changed, 2633 insertions(+), 174 deletions(-)
 
 Index: b/fs/proc/base.c
 ===================================================================
@@ -87,7 +87,7 @@
 ===================================================================
 --- a/arch/i386/kernel/ptrace.c
 +++ b/arch/i386/kernel/ptrace.c
-@@ -735,6 +735,46 @@ const struct utrace_regset_view *utrace_
+@@ -739,6 +739,46 @@ const struct utrace_regset_view *utrace_
  	return &utrace_i386_native;
  }
  
@@ -138,7 +138,7 @@
 ===================================================================
 --- a/arch/x86_64/ia32/ptrace32.c
 +++ b/arch/x86_64/ia32/ptrace32.c
-@@ -166,11 +166,6 @@ static int getreg32(struct task_struct *
+@@ -167,11 +167,6 @@ static int getreg32(struct task_struct *
  
  #undef R32
  
@@ -150,7 +150,7 @@
  static int
  ia32_genregs_get(struct task_struct *target,
  		 const struct utrace_regset *regset,
-@@ -600,3 +595,54 @@ const struct utrace_regset_view utrace_i
+@@ -604,3 +599,54 @@ const struct utrace_regset_view utrace_i
  	.name = "i386", .e_machine = EM_386,
  	.regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
  };
@@ -222,7 +222,7 @@
 ===================================================================
 --- a/arch/x86_64/kernel/ptrace.c
 +++ b/arch/x86_64/kernel/ptrace.c
-@@ -714,6 +714,52 @@ const struct utrace_regset_view *utrace_
+@@ -717,6 +717,52 @@ const struct utrace_regset_view *utrace_
  }
  
  
@@ -683,7 +683,7 @@
 ===================================================================
 --- a/kernel/ptrace.c
 +++ b/kernel/ptrace.c
-@@ -19,194 +19,2007 @@
+@@ -19,194 +19,2008 @@
  #include <linux/security.h>
  #include <linux/signal.h>
  #include <linux/syscalls.h>
@@ -746,19 +746,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 = task->mm->dumpable;
+-	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;
@@ -818,17 +865,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;
@@ -893,9 +937,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
@@ -907,42 +950,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 = task->mm->dumpable;
--	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;
@@ -1087,8 +1095,6 @@
 +	if (retval)
 +		(void) utrace_detach(task, engine);
 +	else {
-+		int stopped = 0;
-+
 +		NO_LOCKS;
 +
 +		/*
@@ -1098,48 +1104,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);
 +	}
  
@@ -1488,7 +1460,13 @@
 +			else
 +				ret = (*regset->get)(target, regset,
 +						     pos, n, kdata, udata);
-+		}
+ 		}
+-		if (copy_to_user(dst, buf, retval))
+-			return -EFAULT;
+-		copied += retval;
+-		src += retval;
+-		dst += retval;
+-		len -= retval;			
 +
 +		if (kdata)
 +			kdata += n;
@@ -1536,7 +1514,8 @@
 +	if (request == PTRACE_ATTACH) {
 +		ret = ptrace_attach(child);
 +		goto out_tsk;
-+	}
+ 	}
+-	return copied;
 +
 +	rcu_read_lock();
 +	engine = utrace_attach(child, UTRACE_ATTACH_MATCH_OPS,
@@ -1563,13 +1542,7 @@
 +			if (child->state == TASK_STOPPED)
 +				ret = 0;
 +			unlock_task_sighand(child, &flags);
- 		}
--		if (copy_to_user(dst, buf, retval))
--			return -EFAULT;
--		copied += retval;
--		src += retval;
--		dst += retval;
--		len -= retval;			
++		}
 +		if (ret == 0) {
 +			ret = ptrace_update(child, state,
 +					    UTRACE_ACTION_QUIESCE, 0);
@@ -1586,8 +1559,7 @@
 +		}
 +
 +		ret = -ESRCH;  /* Return value for exit_state bail-out.  */
- 	}
--	return copied;
++	}
 +
 +	rcu_read_unlock();
 +
@@ -1783,11 +1755,7 @@
 +		if (ret == 0) {
 +			ret = val;
 +			force_successful_syscall_return();
- 		}
--		copied += retval;
--		src += retval;
--		dst += retval;
--		len -= retval;			
++		}
 +		goto out_tsk;
 +	}
 +
@@ -1807,8 +1775,7 @@
 +			break;
 +		ret = put_user(tmp, (unsigned long __user *) data);
 +		break;
- 	}
--	return copied;
++	}
 +
 +	case PTRACE_POKETEXT: /* write the word at location addr. */
 +	case PTRACE_POKEDATA:
@@ -1837,9 +1804,14 @@
 +					   (siginfo_t __user *) data,
 +					   sizeof(siginfo_t)))
 +				ret = -EFAULT;
-+		}
+ 		}
+-		copied += retval;
+-		src += retval;
+-		dst += retval;
+-		len -= retval;			
 +		break;
-+	}
+ 	}
+-	return copied;
 +
 +out_tsk:
 +	NO_LOCKS;
@@ -1936,13 +1908,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.
   */
@@ -2104,7 +2076,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
@@ -2155,6 +2149,7 @@
 +	}
 +	else {
 +		why = CLD_TRAPPED;
++		exit_code &= ~PTRACE_TRAPPED_MASK;
 +		status = exit_code;
 +		exit_code = (status << 8) | 0x7f;
 +	}
@@ -2333,8 +2328,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",

linux-2.6-utrace-regset.patch:

Index: linux-2.6-utrace-regset.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-7/linux-2.6-utrace-regset.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- linux-2.6-utrace-regset.patch	20 Jul 2007 18:48:03 -0000	1.3
+++ linux-2.6-utrace-regset.patch	5 Sep 2007 16:18:54 -0000	1.4
@@ -12,25 +12,27 @@
 ---
 
  arch/i386/kernel/i387.c             |  143 +++---
- arch/i386/kernel/ptrace.c           |  822 ++++++++++++++++++++---------------
- arch/x86_64/ia32/ptrace32.c         |  719 ++++++++++++++++++++-----------
- arch/x86_64/ia32/fpu32.c            |   92 +++-
- arch/x86_64/kernel/ptrace.c         |  730 +++++++++++++++++++------------
+ arch/i386/kernel/ptrace.c           |  826 ++++++++++++++++++++----------------
  arch/powerpc/kernel/Makefile        |    4 
- arch/powerpc/kernel/ptrace32.c      |  443 -------------------
- arch/powerpc/kernel/ptrace.c        |  718 +++++++++++++++----------------
  arch/powerpc/kernel/ptrace-common.h |  145 ------
- kernel/ptrace.c                     |    8 
- include/linux/tracehook.h           |  244 ++++++++++
- include/asm-i386/i387.h             |   13 -
+ arch/powerpc/kernel/ptrace.c        |  718 +++++++++++++++----------------
+ arch/powerpc/kernel/ptrace32.c      |  443 -------------------
+ arch/x86_64/ia32/fpu32.c            |   92 +++-
+ arch/x86_64/ia32/ptrace32.c         |  725 ++++++++++++++++++++-----------
+ arch/x86_64/kernel/ptrace.c         |  733 +++++++++++++++++++------------
+ include/asm-i386/i387.h             |   13 
  include/asm-x86_64/fpu32.h          |    3 
  include/asm-x86_64/tracehook.h      |    8 
- 14 files changed, 2124 insertions(+), 1968 deletions(-)
+ include/linux/tracehook.h           |  255 ++++++++++-
+ kernel/ptrace.c                     |    8 
+ 14 files changed, 2147 insertions(+), 1969 deletions(-)
  delete arch/powerpc/kernel/ptrace32.c
  delete arch/powerpc/kernel/ptrace-common.h
 
---- linux-2.6/arch/i386/kernel/i387.c
-+++ linux-2.6/arch/i386/kernel/i387.c
+Index: b/arch/i386/kernel/i387.c
+===================================================================
+--- a/arch/i386/kernel/i387.c
++++ b/arch/i386/kernel/i387.c
 @@ -222,14 +222,10 @@ void set_fpu_twd( struct task_struct *ts
   * FXSR floating point environment conversions.
   */
@@ -240,19 +242,22 @@
  }
  
  /*
---- linux-2.6/arch/i386/kernel/ptrace.c
-+++ linux-2.6/arch/i386/kernel/ptrace.c
-@@ -17,7 +17,9 @@
+Index: b/arch/i386/kernel/ptrace.c
+===================================================================
+--- a/arch/i386/kernel/ptrace.c
++++ b/arch/i386/kernel/ptrace.c
+@@ -17,7 +17,10 @@
  #include <linux/audit.h>
  #include <linux/seccomp.h>
  #include <linux/signal.h>
 +#include <linux/module.h>
++#include <linux/elf.h>
  
 +#include <asm/tracehook.h>
  #include <asm/uaccess.h>
  #include <asm/pgtable.h>
  #include <asm/system.h>
-@@ -28,10 +30,6 @@
+@@ -28,10 +31,6 @@
  #include <asm/desc.h>
  #include <asm/tracehook.h>
  
@@ -263,7 +268,7 @@
  
  /*
   * Determines which flags the user has access to [1 = access, 0 = no access].
-@@ -40,9 +38,6 @@
+@@ -40,9 +39,6 @@
   */
  #define FLAG_MASK 0x00050dd5
  
@@ -273,7 +278,7 @@
  /*
   * Offset of eflags on child stack..
   */
-@@ -90,28 +85,35 @@ static int putreg(struct task_struct *ch
+@@ -90,28 +86,35 @@ static int putreg(struct task_struct *ch
  	unsigned long regno, unsigned long value)
  {
  	switch (regno >> 2) {
@@ -331,7 +336,7 @@
  	}
  	if (regno > FS*4)
  		regno -= 1*4;
-@@ -125,20 +127,28 @@ static unsigned long getreg(struct task_
+@@ -125,20 +128,28 @@ static unsigned long getreg(struct task_
  	unsigned long retval = ~0UL;
  
  	switch (regno >> 2) {
@@ -374,7 +379,7 @@
  	}
  	return retval;
  }
-@@ -230,11 +240,11 @@ void tracehook_enable_single_step(struct
+@@ -230,11 +241,11 @@ void tracehook_enable_single_step(struct
  	/*
  	 * If TF was already set, don't do anything else
  	 */
@@ -388,7 +393,7 @@
  
  	/*
  	 * ..but if TF is changed by the instruction we will trace,
-@@ -255,29 +265,311 @@ void tracehook_disable_single_step(struc
+@@ -255,20 +266,300 @@ void tracehook_disable_single_step(struc
  	/* But touch TF only if it was set by us.. */
  	if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF)) {
  		struct pt_regs *regs = get_child_regs(child);
@@ -697,6 +702,9 @@
  /*
   * Perform get_thread_area on behalf of the traced child.
   */
+@@ -273,11 +564,13 @@ void ptrace_disable(struct task_struct *
+  * Perform get_thread_area on behalf of the traced child.
+  */
  static int
 -ptrace_get_thread_area(struct task_struct *child,
 -		       int idx, struct user_desc __user *user_desc)
@@ -712,7 +720,7 @@
  
  /*
   * Get the current Thread-Local Storage area:
-@@ -299,23 +591,29 @@ ptrace_get_thread_area(struct task_struc
+@@ -299,23 +592,29 @@ ptrace_get_thread_area(struct task_struc
  #define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
  #define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
  
@@ -759,7 +767,7 @@
  
  	return 0;
  }
-@@ -324,304 +622,120 @@ ptrace_get_thread_area(struct task_struc
+@@ -324,304 +623,123 @@ ptrace_get_thread_area(struct task_struc
   * Perform set_thread_area on behalf of the traced child.
   */
  static int
@@ -1110,16 +1118,19 @@
 + */
 +static const struct utrace_regset native_regsets[] = {
 +	{
++		.core_note_type = NT_PRSTATUS,
 +		.n = FRAME_SIZE, .size = sizeof(long), .align = sizeof(long),
 +		.get = genregs_get, .set = genregs_set
 +	},
 +	{
++		.core_note_type = NT_PRFPREG,
 +		.n = sizeof(struct user_i387_struct) / sizeof(long),
 +		.size = sizeof(long), .align = sizeof(long),
 +		.active = fpregs_active,
 +		.get = fpregs_get, .set = fpregs_set
 +	},
 +	{
++		.core_note_type = NT_PRXFPREG,
 +		.n = sizeof(struct user_fxsr_struct) / sizeof(long),
 +		.size = sizeof(long), .align = sizeof(long),
 +		.active = fpxregs_active,
@@ -1160,11 +1171,15 @@
  void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
  {
  	struct siginfo info;
---- linux-2.6/arch/x86_64/ia32/ptrace32.c
-+++ linux-2.6/arch/x86_64/ia32/ptrace32.c
-@@ -16,7 +16,11 @@
+Index: b/arch/x86_64/ia32/ptrace32.c
+===================================================================
+--- a/arch/x86_64/ia32/ptrace32.c
++++ b/arch/x86_64/ia32/ptrace32.c
+@@ -15,8 +15,13 @@
+ #include <linux/syscalls.h>
  #include <linux/unistd.h>
  #include <linux/mm.h>
++#include <linux/err.h>
  #include <linux/ptrace.h>
 +#include <linux/tracehook.h>
 +#include <linux/module.h>
@@ -1174,7 +1189,7 @@
  #include <asm/compat.h>
  #include <asm/uaccess.h>
  #include <asm/user32.h>
-@@ -25,7 +29,8 @@
+@@ -25,7 +30,8 @@
  #include <asm/debugreg.h>
  #include <asm/i387.h>
  #include <asm/fpu32.h>
@@ -1184,7 +1199,7 @@
  
  /*
   * Determines which flags the user has access to [1 = access, 0 = no access].
-@@ -35,34 +40,41 @@
+@@ -35,34 +41,41 @@
  #define FLAG_MASK 0x54dd5UL
  
  #define R32(l,q) \
@@ -1239,7 +1254,7 @@
  		if ((val & 3) != 3) return -EIO;
  		stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff;
  		break;
-@@ -78,57 +90,16 @@ static int putreg32(struct task_struct *
+@@ -78,57 +91,16 @@ static int putreg32(struct task_struct *
  	R32(eip, rip);
  	R32(esp, rsp);
  
@@ -1300,7 +1315,7 @@
  	}
  	return 0;
  }
-@@ -136,24 +107,33 @@ static int putreg32(struct task_struct *
+@@ -136,24 +108,33 @@ static int putreg32(struct task_struct *
  #undef R32
  
  #define R32(l,q) \
@@ -1347,7 +1362,7 @@
  		break;
  
  	R32(cs, cs);
-@@ -167,239 +147,456 @@ static int getreg32(struct task_struct *
+@@ -167,239 +148,459 @@ static int getreg32(struct task_struct *
  	R32(eax, rax);
  	R32(orig_eax, orig_rax);
  	R32(eip, rip);
@@ -1396,7 +1411,7 @@
  
 -static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
 +asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
- {
++{
 +	return -ENOSYS;
 +}
 +
@@ -1405,7 +1420,7 @@
 +		 const struct utrace_regset *regset,
 +		 unsigned int pos, unsigned int count,
 +		 void *kbuf, void __user *ubuf)
-+{
+ {
 +	if (kbuf) {
 +		u32 *kp = kbuf;
 +		while (count > 0) {
@@ -1473,7 +1488,13 @@
 +		void *kbuf, void __user *ubuf)
 +{
 +	struct user_i387_ia32_struct fp;
-+	int ret;
+ 	int ret;
+-	compat_siginfo_t __user *si32 = compat_ptr(data);
+-	siginfo_t ssi; 
+-	siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
+-	if (request == PTRACE_SETSIGINFO) {
+-		memset(&ssi, 0, sizeof(siginfo_t));
+-		ret = copy_siginfo_from_user32(&ssi, si32);
 +
 +	if (tsk_used_math(target)) {
 +		if (target == current)
@@ -1497,13 +1518,7 @@
 +		const void *kbuf, const void __user *ubuf)
 +{
 +	struct user_i387_ia32_struct fp;
- 	int ret;
--	compat_siginfo_t __user *si32 = compat_ptr(data);
--	siginfo_t ssi; 
--	siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
--	if (request == PTRACE_SETSIGINFO) {
--		memset(&ssi, 0, sizeof(siginfo_t));
--		ret = copy_siginfo_from_user32(&ssi, si32);
++	int ret;
 +
 +	if (tsk_used_math(target)) {
 +		if (target == current)
@@ -1645,41 +1660,33 @@
 -		else
 -			ret = put_user(val, (unsigned int __user *)datap); 
 -		break; 
-+	target->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
- 
+-
 -	case PTRACE_POKEDATA:
 -	case PTRACE_POKETEXT:
 -		ret = 0;
 -		if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32))
 -			ret = -EIO; 
 -		break;
-+	return ret;
-+}
++	target->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
  
 -	case PTRACE_PEEKUSR:
 -		ret = getreg32(child, addr, &val);
 -		if (ret == 0)
 -			ret = put_user(val, (__u32 __user *)datap);
 -		break;
-+static int
-+ia32_dbregs_active(struct task_struct *tsk, const struct utrace_regset *regset)
-+{
-+	if (tsk->thread.debugreg6 | tsk->thread.debugreg7)
-+		return 8;
-+	return 0;
++	return ret;
 +}
  
 -	case PTRACE_POKEUSR:
 -		ret = putreg32(child, addr, data);
 -		break;
 +static int
-+ia32_dbregs_get(struct task_struct *target,
-+		const struct utrace_regset *regset,
-+		unsigned int pos, unsigned int count,
-+		void *kbuf, void __user *ubuf)
++ia32_dbregs_active(struct task_struct *tsk, const struct utrace_regset *regset)
 +{
-+	for (pos >>= 2, count >>= 2; count > 0; --count, ++pos) {
-+		u32 val;
++	if (tsk->thread.debugreg6 | tsk->thread.debugreg7)
++		return 8;
++	return 0;
++}
  
 -	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 -		int i;
@@ -1692,6 +1699,15 @@
 -			getreg32(child, i, &val);
 -			ret |= __put_user(val,(u32 __user *)datap);
 -			datap += sizeof(u32);
++static int
++ia32_dbregs_get(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	for (pos >>= 2, count >>= 2; count > 0; --count, ++pos) {
++		u32 val;
++
 +		/*
 +		 * The hardware updates the status register on a debug trap,
 +		 * but do_debug (traps.c) saves it for us when that happens.
@@ -1934,8 +1950,8 @@
 +	put_cpu();
 +
 +	return 0;
- }
- 
++}
++
 +/*
 + * Determine how many TLS slots are in use.
 + */
@@ -1950,8 +1966,8 @@
 +			break;
 +	}
 +	return i;
-+}
-+
+ }
+ 
 +
 +/*
 + * This should match arch/i386/kernel/ptrace.c:native_regsets.
@@ -1959,17 +1975,20 @@
 + */
 +static const struct utrace_regset ia32_regsets[] = {
 +	{
++		.core_note_type = NT_PRSTATUS,
 +		.n = sizeof(struct user_regs_struct32)/4,
 +		.size = 4, .align = 4,
 +		.get = ia32_genregs_get, .set = ia32_genregs_set
 +	},
 +	{
++		.core_note_type = NT_PRFPREG,
 +		.n = sizeof(struct user_i387_ia32_struct) / 4,
 +		.size = 4, .align = 4,
 +		.active = ia32_fpregs_active,
 +		.get = ia32_fpregs_get, .set = ia32_fpregs_set
 +	},
 +	{
++		.core_note_type = NT_PRXFPREG,
 +		.n = sizeof(struct user32_fxsr_struct) / 4,
 +		.size = 4, .align = 4,
 +		.active = ia32_fpxregs_active,
@@ -1994,8 +2013,10 @@
 +	.name = "i386", .e_machine = EM_386,
 +	.regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
 +};
---- linux-2.6/arch/x86_64/ia32/fpu32.c
-+++ linux-2.6/arch/x86_64/ia32/fpu32.c
+Index: b/arch/x86_64/ia32/fpu32.c
+===================================================================
+--- a/arch/x86_64/ia32/fpu32.c
++++ b/arch/x86_64/ia32/fpu32.c
 @@ -9,6 +9,7 @@
  #include <asm/processor.h>
  #include <asm/uaccess.h>
@@ -2148,19 +2169,22 @@
 +
 +	return 0;
 +}
---- linux-2.6/arch/x86_64/kernel/ptrace.c
-+++ linux-2.6/arch/x86_64/kernel/ptrace.c
-@@ -19,7 +19,9 @@
+Index: b/arch/x86_64/kernel/ptrace.c
+===================================================================
+--- a/arch/x86_64/kernel/ptrace.c
++++ b/arch/x86_64/kernel/ptrace.c
+@@ -19,7 +19,10 @@
  #include <linux/audit.h>
  #include <linux/seccomp.h>
  #include <linux/signal.h>
 +#include <linux/module.h>
++#include <linux/elf.h>
  
 +#include <asm/tracehook.h>
  #include <asm/uaccess.h>
  #include <asm/pgtable.h>
  #include <asm/system.h>
-@@ -30,6 +32,7 @@
+@@ -30,6 +33,7 @@
  #include <asm/desc.h>
  #include <asm/proto.h>
  #include <asm/ia32.h>
@@ -2168,7 +2192,7 @@
  
  /*
   * does not yet catch signals sent when the child dies.
-@@ -228,52 +231,61 @@ static int putreg(struct task_struct *ch
+@@ -228,52 +232,61 @@ static int putreg(struct task_struct *ch
  	if (test_tsk_thread_flag(child, TIF_IA32))
  		value &= 0xffffffff;
  	switch (regno) {
@@ -2276,7 +2300,7 @@
  	}
  	put_stack_long(child, regno - sizeof(struct pt_regs), value);
  	return 0;
-@@ -282,298 +294,426 @@ static int putreg(struct task_struct *ch
+@@ -282,295 +295,380 @@ static int putreg(struct task_struct *ch
  static unsigned long getreg(struct task_struct *child, unsigned long regno)
  {
  	unsigned long val;
@@ -2906,6 +2930,10 @@
  	return ret;
  }
  
+@@ -574,6 +672,51 @@ long arch_ptrace(struct task_struct *chi
+ 	return ret;
+ }
+ 
 +
 +/*
 + * These are our native regset flavors.
@@ -2913,10 +2941,12 @@
 + */
 +static const struct utrace_regset native_regsets[] = {
 +	{
++		.core_note_type = NT_PRSTATUS,
 +		.n = sizeof(struct user_regs_struct)/8, .size = 8, .align = 8,
 +		.get = genregs_get, .set = genregs_set
 +	},
 +	{
++		.core_note_type = NT_PRFPREG,
 +		.n = sizeof(struct user_i387_struct) / sizeof(long),
 +		.size = sizeof(long), .align = sizeof(long),
 +		.active = fpregs_active,
@@ -2952,8 +2982,10 @@
  asmlinkage void syscall_trace_enter(struct pt_regs *regs)
  {
  	/* do the secure computing check first */
---- linux-2.6/arch/powerpc/kernel/Makefile
-+++ linux-2.6/arch/powerpc/kernel/Makefile
+Index: b/arch/powerpc/kernel/Makefile
+===================================================================
+--- a/arch/powerpc/kernel/Makefile
++++ b/arch/powerpc/kernel/Makefile
 @@ -10,12 +10,14 @@ CFLAGS_prom_init.o      += -fPIC
  CFLAGS_btext.o		+= -fPIC
  endif
@@ -2970,8 +3002,10 @@
  				   paca.o cpu_setup_ppc970.o \
  				   cpu_setup_pa6t.o \
  				   firmware.o sysfs.o nvram_64.o
---- linux-2.6/arch/powerpc/kernel/ptrace32.c
-+++ linux-2.6/arch/powerpc/kernel/ptrace32.c
+Index: b/arch/powerpc/kernel/ptrace32.c
+===================================================================
+--- a/arch/powerpc/kernel/ptrace32.c
++++ /dev/null
 @@ -1,443 +0,0 @@
 -/*
 - * ptrace for 32-bit processes running on a 64-bit kernel.
@@ -3416,8 +3450,10 @@
 -	unlock_kernel();
 -	return ret;
 -}
---- linux-2.6/arch/powerpc/kernel/ptrace.c
-+++ linux-2.6/arch/powerpc/kernel/ptrace.c
+Index: b/arch/powerpc/kernel/ptrace.c
+===================================================================
+--- a/arch/powerpc/kernel/ptrace.c
++++ b/arch/powerpc/kernel/ptrace.c
 @@ -27,9 +27,8 @@
  #include <linux/signal.h>
  #include <linux/seccomp.h>
@@ -4229,8 +4265,10 @@
  
  void do_syscall_trace_enter(struct pt_regs *regs)
  {
---- linux-2.6/arch/powerpc/kernel/ptrace-common.h
-+++ linux-2.6/arch/powerpc/kernel/ptrace-common.h
+Index: b/arch/powerpc/kernel/ptrace-common.h
+===================================================================
+--- a/arch/powerpc/kernel/ptrace-common.h
++++ /dev/null
 @@ -1,145 +0,0 @@
 -/*
 - *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
@@ -4377,8 +4415,10 @@
 -}
 -
 -#endif /* _PPC64_PTRACE_COMMON_H */
---- linux-2.6/kernel/ptrace.c
-+++ linux-2.6/kernel/ptrace.c
+Index: b/kernel/ptrace.c
+===================================================================
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
 @@ -99,12 +99,6 @@ int ptrace_detach(struct task_struct *ch
  	if (!valid_signal(data))
  		return -EIO;
@@ -4402,8 +4442,10 @@
  	return -ENOSYS;
  }
 -#endif /* __ARCH_SYS_PTRACE */
---- linux-2.6/include/linux/tracehook.h
-+++ linux-2.6/include/linux/tracehook.h
+Index: b/include/linux/tracehook.h
+===================================================================
+--- a/include/linux/tracehook.h
++++ b/include/linux/tracehook.h
 @@ -52,10 +52,10 @@ struct pt_regs;
   * should be one that can be evaluated in modules, i.e. uses exported symbols.
   *
@@ -4419,7 +4461,7 @@
   * Enabling or disabling redundantly is harmless.
   *
   *	void tracehook_enable_block_step(struct task_struct *tsk);
-@@ -93,6 +93,242 @@ struct pt_regs;
+@@ -93,6 +93,253 @@ struct pt_regs;
   */
  
  
@@ -4459,6 +4501,17 @@
 +	unsigned int bias;	/* Bias from natural indexing.  */
 +
 +	/*
++	 * If nonzero, this gives the n_type field (NT_* value) of the
++	 * core file note in which this regset's data appears.
++	 * NT_PRSTATUS is a special case in that the regset data starts
++	 * at offsetof(struct elf_prstatus, pr_reg) into the note data;
++	 * that is part of the per-machine ELF formats userland knows
++	 * about.  In other cases, the core file note contains exactly
++	 * the whole regset (n*size) and nothing else.
++	 */
++	unsigned int core_note_type;
++
++	/*
 +	 * Return -%ENODEV if not available on the hardware found.
 +	 * Return %0 if no interesting state in this thread.
 +	 * Return >%0 number of @size units of interesting state.
@@ -4662,8 +4715,10 @@
  /*
   * Following are entry points from core code, where the user debugging
   * support can affect the normal behavior.  The locking situation is
---- linux-2.6/include/asm-i386/i387.h
-+++ linux-2.6/include/asm-i386/i387.h
+Index: b/include/asm-i386/i387.h
+===================================================================
+--- a/include/asm-i386/i387.h
++++ b/include/asm-i386/i387.h
 @@ -130,17 +130,12 @@ extern int save_i387( struct _fpstate __
  extern int restore_i387( struct _fpstate __user *buf );
  
@@ -4686,8 +4741,10 @@
  
  /*
   * FPU state for core dumps...
---- linux-2.6/include/asm-x86_64/fpu32.h
-+++ linux-2.6/include/asm-x86_64/fpu32.h
+Index: b/include/asm-x86_64/fpu32.h
+===================================================================
+--- a/include/asm-x86_64/fpu32.h
++++ b/include/asm-x86_64/fpu32.h
 @@ -7,4 +7,7 @@ int restore_i387_ia32(struct task_struct
  int save_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, 
  		   struct pt_regs *regs, int fsave);
@@ -4696,8 +4753,10 @@
 +int set_fpregs32(struct task_struct *, const struct user_i387_ia32_struct *);
 +
  #endif
---- linux-2.6/include/asm-x86_64/tracehook.h
-+++ linux-2.6/include/asm-x86_64/tracehook.h
+Index: b/include/asm-x86_64/tracehook.h
+===================================================================
+--- a/include/asm-x86_64/tracehook.h
++++ b/include/asm-x86_64/tracehook.h
 @@ -48,4 +48,12 @@ static inline void tracehook_abort_sysca
  	regs->orig_rax = -1L;
  }




More information about the fedora-extras-commits mailing list