rpms/kernel/devel kernel-2.6.spec, 1.2825, 1.2826 linux-2.6-utrace.patch, 1.37, 1.38

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Fri Nov 17 21:54:46 UTC 2006


Author: roland

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

Modified Files:
	kernel-2.6.spec linux-2.6-utrace.patch 
Log Message:
utrace rebased, some fixes


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.2825
retrieving revision 1.2826
diff -u -r1.2825 -r1.2826
--- kernel-2.6.spec	17 Nov 2006 21:07:49 -0000	1.2825
+++ kernel-2.6.spec	17 Nov 2006 21:54:44 -0000	1.2826
@@ -725,7 +725,7 @@
 # Patches 10 through 100 are meant for core subsystem upgrades
 
 # Roland's utrace ptrace replacement.
-#%patch10 -p1
+%patch10 -p1
 
 # sysrq works always
 %patch20 -p1

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               |  537 +++++++++
 arch/ia64/kernel/asm-offsets.c          |    2 
 arch/ia64/kernel/fsys.S                 |   16 
 arch/ia64/kernel/mca.c                  |    2 
 arch/ia64/kernel/ptrace.c               | 1680 +++++++++++++++---------------
 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               | 1073 +++++++++----------
 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             |  723 ++++++++-----
 arch/x86_64/ia32/sys_ia32.c             |    5 
 arch/x86_64/kernel/process.c            |    5 
 arch/x86_64/kernel/ptrace.c             |  657 +++++++-----
 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                         |   12 
 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            |   83 +
 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                           |  244 +---
 kernel/fork.c                           |   62 -
 kernel/ptrace.c                         | 1598 +++++++++++++++++++++++------
 kernel/signal.c                         |  211 ---
 kernel/sys.c                            |    2 
 kernel/timer.c                          |    6 
 kernel/tsacct.c                         |    2 
 kernel/utrace.c                         | 1735 ++++++++++++++++++++++++++++++++
 security/selinux/hooks.c                |   54 
 security/selinux/include/objsec.h       |    1 
 98 files changed, 10201 insertions(+), 5056 deletions(-)

Index: linux-2.6-utrace.patch
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/linux-2.6-utrace.patch,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- linux-2.6-utrace.patch	6 Nov 2006 21:15:10 -0000	1.37
+++ linux-2.6-utrace.patch	17 Nov 2006 21:54:44 -0000	1.38
@@ -11,11 +11,11 @@
  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/ia32/sys_ia32.c               |  537 +++++++++-
  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/ptrace.c               | 1680 +++++++++++++++---------------
  arch/ia64/kernel/signal.c               |    4 
  arch/mips/kernel/ptrace.c               |   21 
  arch/mips/kernel/sysirix.c              |    2 
@@ -52,7 +52,7 @@
  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             |  721 +++++++++----
+ arch/x86_64/ia32/ptrace32.c             |  723 +++++++++----
  arch/x86_64/ia32/sys_ia32.c             |    5 
  arch/x86_64/kernel/process.c            |    5 
  arch/x86_64/kernel/ptrace.c             |  657 +++++++-----
@@ -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            |   83 +
  include/asm-powerpc/tracehook.h         |   80 +
  include/asm-s390/tracehook.h            |   53 +
  include/asm-sparc64/tracehook.h         |   44 +
@@ -89,7 +89,7 @@
  kernel/Makefile                         |    1 
  kernel/exit.c                           |  244 +---
  kernel/fork.c                           |   62 -
- kernel/ptrace.c                         | 1581 +++++++++++++++++++++++-----
+ kernel/ptrace.c                         | 1598 +++++++++++++++++++++++------
  kernel/signal.c                         |  211 +---
  kernel/sys.c                            |    2 
  kernel/timer.c                          |    6 
@@ -97,7 +97,7 @@
  kernel/utrace.c                         | 1735 +++++++++++++++++++++++++++++++
  security/selinux/hooks.c                |   54 +
  security/selinux/include/objsec.h       |    1 
- 99 files changed, 9656 insertions(+), 5056 deletions(-)
+ 99 files changed, 10201 insertions(+), 5056 deletions(-)
  create mode 100644 Documentation/utrace.txt
  delete arch/powerpc/kernel/ptrace-common.h
  delete arch/powerpc/kernel/ptrace32.c
@@ -229,7 +229,7 @@
  typedef unsigned long elf_greg_t;
 --- linux-2.6/include/asm-ia64/tracehook.h.utrace-ptrace-compat
 +++ linux-2.6/include/asm-ia64/tracehook.h
-@@ -0,0 +1,81 @@
+@@ -0,0 +1,83 @@
 +/*
 + * Copyright (C)2006 Intel Co
 + *	Anil S Keshavamurthy <anil.s.keshavamurthy at intel.com>
@@ -293,24 +293,26 @@
 +
 +static inline void tracehook_abort_syscall(struct pt_regs *regs)
 +{
-+	regs->r15 = -1L;
++	if (IS_IA32_PROCESS(regs))
++		regs->r1 = -1UL;
++	else
++		regs->r15 = -1UL;
 +}
 +
 +extern const struct utrace_regset_view utrace_ia64_native;
 +static inline const struct utrace_regset_view *
 +utrace_native_view(struct task_struct *tsk)
 +{
-+#if 0 //CONFIG_IA32_SUPPORT
++#ifdef CONFIG_IA32_SUPPORT
 +	extern const struct utrace_regset_view utrace_ia32_view;
-+
-+	struct pt_regs *pt = task_pt_regs(tsk);
-+	if (pt->cr_ipsr & IA64_PSR_IS)
++	if (IS_IA32_PROCESS(task_pt_regs(tsk)))
 +		return &utrace_ia32_view;
 +#endif
 +	return &utrace_ia64_native;
 +}
 +
-+#endif
++
++#endif	/* asm/tracehook.h */
 --- linux-2.6/include/asm-i386/i387.h.utrace-ptrace-compat
 +++ linux-2.6/include/asm-i386/i387.h
 @@ -126,17 +126,12 @@ extern int save_i387( struct _fpstate __
@@ -2708,7 +2710,7 @@
  	return 0;
  }
  
-@@ -4402,6 +4403,7 @@ static int selinux_setprocattr(struct ta
+@@ -4408,6 +4409,7 @@ static int selinux_setprocattr(struct ta
  			       char *name, void *value, size_t size)
  {
  	struct task_security_struct *tsec;
@@ -2716,7 +2718,7 @@
  	u32 sid = 0;
  	int error;
  	char *str = value;
-@@ -4490,18 +4492,24 @@ static int selinux_setprocattr(struct ta
+@@ -4496,18 +4498,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);
@@ -2938,7 +2940,7 @@
  		set_tsk_thread_flag(t, TIF_SIGPENDING);
  	else
  		clear_tsk_thread_flag(t, TIF_SIGPENDING);
-@@ -587,8 +586,6 @@ static int check_kill_permission(int sig
+@@ -594,8 +593,6 @@ static int check_kill_permission(int sig
  	return error;
  }
  
@@ -2947,7 +2949,7 @@
  
  /*
   * Handle magic process-wide effects of stop/continue signals.
-@@ -894,7 +891,7 @@ __group_complete_signal(int sig, struct 
+@@ -901,7 +898,7 @@ __group_complete_signal(int sig, struct 
  	 */
  	if (sig_fatal(p, sig) && !(p->signal->flags & SIGNAL_GROUP_EXIT) &&
  	    !sigismember(&t->real_blocked, sig) &&
@@ -2956,7 +2958,7 @@
  		/*
  		 * This signal will be fatal to the whole group.
  		 */
-@@ -1473,8 +1470,7 @@ void do_notify_parent(struct task_struct
+@@ -1480,8 +1477,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));
  
@@ -2966,7 +2968,7 @@
  
  	info.si_signo = sig;
  	info.si_errno = 0;
-@@ -1499,7 +1495,7 @@ void do_notify_parent(struct task_struct
+@@ -1506,7 +1502,7 @@ void do_notify_parent(struct task_struct
  
  	psig = tsk->parent->sighand;
  	spin_lock_irqsave(&psig->siglock, flags);
@@ -2975,7 +2977,7 @@
  	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
  	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
  		/*
-@@ -1527,20 +1523,13 @@ void do_notify_parent(struct task_struct
+@@ -1534,20 +1530,13 @@ void do_notify_parent(struct task_struct
  	spin_unlock_irqrestore(&psig->siglock, flags);
  }
  
@@ -2997,7 +2999,7 @@
  	info.si_signo = SIGCHLD;
  	info.si_errno = 0;
  	info.si_pid = tsk->pid;
-@@ -1565,6 +1554,15 @@ static void do_notify_parent_cldstop(str
+@@ -1572,6 +1561,15 @@ static void do_notify_parent_cldstop(str
   		BUG();
   	}
  
@@ -3013,7 +3015,7 @@
  	sighand = parent->sighand;
  	spin_lock_irqsave(&sighand->siglock, flags);
  	if (sighand->action[SIGCHLD-1].sa.sa_handler != SIG_IGN &&
-@@ -1577,110 +1575,6 @@ static void do_notify_parent_cldstop(str
+@@ -1584,110 +1582,6 @@ static void do_notify_parent_cldstop(str
  	spin_unlock_irqrestore(&sighand->siglock, flags);
  }
  
@@ -3124,7 +3126,7 @@
  static void
  finish_stop(int stop_count)
  {
-@@ -1689,7 +1583,7 @@ finish_stop(int stop_count)
+@@ -1696,7 +1590,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.
  	 */
@@ -3133,7 +3135,7 @@
  		read_lock(&tasklist_lock);
  		do_notify_parent_cldstop(current, CLD_STOPPED);
  		read_unlock(&tasklist_lock);
-@@ -1814,44 +1708,24 @@ relock:
+@@ -1821,44 +1715,24 @@ relock:
  		    handle_group_stop())
  			goto relock;
  
@@ -3194,7 +3196,7 @@
  		if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
  			continue;
  		if (ka->sa.sa_handler != SIG_DFL) {
-@@ -1896,7 +1770,7 @@ relock:
+@@ -1903,7 +1777,7 @@ relock:
  				spin_lock_irq(&current->sighand->siglock);
  			}
  
@@ -3203,7 +3205,7 @@
  				/* It released the siglock.  */
  				goto relock;
  			}
-@@ -1923,13 +1797,13 @@ relock:
+@@ -1930,13 +1804,13 @@ relock:
  			 * first and our do_group_exit call below will use
  			 * that value and ignore the one we pass it.
  			 */
@@ -3219,7 +3221,7 @@
  		/* NOTREACHED */
  	}
  	spin_unlock_irq(&current->sighand->siglock);
-@@ -1942,7 +1816,6 @@ EXPORT_SYMBOL(flush_signals);
+@@ -1949,7 +1823,6 @@ EXPORT_SYMBOL(flush_signals);
  EXPORT_SYMBOL(force_sig);
  EXPORT_SYMBOL(kill_pg);
  EXPORT_SYMBOL(kill_proc);
@@ -3558,7 +3560,7 @@
 +			engine = ERR_PTR(-EEXIST);
 +		return engine;
 +	}
-+	return NULL;
++	return ERR_PTR(-ENOENT);
 +}
 +
 +/*
@@ -3628,7 +3630,7 @@
 +		if (flags & UTRACE_ATTACH_EXCLUSIVE) {
 +			struct utrace_attached_engine *old;
 +			old = matching_engine(utrace, flags, ops, data);
-+			if (old != NULL) {
++			if (!IS_ERR(old)) {
 +				utrace_unlock(utrace);
 +				rcu_read_unlock();
 +				kmem_cache_free(utrace_engine_cachep, engine);
@@ -5592,7 +5594,7 @@
  
  static int may_attach(struct task_struct *task)
  {
-@@ -157,334 +71,1369 @@ int ptrace_may_attach(struct task_struct
+@@ -157,334 +71,1386 @@ int ptrace_may_attach(struct task_struct
  	return !err;
  }
  
@@ -5722,7 +5724,8 @@
 + * Update the tracing engine state to match the new ptrace state.
 + */
 +static void
-+ptrace_update(struct task_struct *target, struct utrace_attached_engine *engine,
++ptrace_update(struct task_struct *target,
++	      struct utrace_attached_engine *engine,
 +	      unsigned long flags)
 +{
 +	struct ptrace_state *state = (struct ptrace_state *) engine->data;
@@ -5731,7 +5734,7 @@
 +	 * These events are always reported.
 +	 */
 +	flags |= (UTRACE_EVENT(DEATH) | UTRACE_EVENT(EXEC)
-+		  | UTRACE_EVENT_SIGNAL_ALL);
++		  | UTRACE_EVENT_SIGNAL_ALL | UTRACE_EVENT(JCTL));
 +
 +	/*
 +	 * We always have to examine clone events to check for CLONE_PTRACE.
@@ -5758,6 +5761,13 @@
 +			state->u.live.u.siginfo = NULL;
 +		if (!(target->flags & PF_EXITING))
 +			target->exit_code = 0;
++
++		if (target->state == TASK_STOPPED) {
++			spin_lock_irq(&target->sighand->siglock);
++			if (target->state == TASK_STOPPED)
++				target->signal->flags &= ~SIGNAL_STOP_STOPPED;
++			spin_unlock_irq(&target->sighand->siglock);
++		}
 +	}
 +	utrace_set_flags(target, engine, flags);
 +}
@@ -6485,11 +6495,13 @@
  	case PTRACE_SETSIGINFO:
 -		ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
 +		ret = -EINVAL;
-+		if (!state->u.live.have_eventmsg && state->u.live.u.siginfo
-+		    && copy_from_user(state->u.live.u.siginfo,
-+				      (siginfo_t __user *) data,
-+				      sizeof(siginfo_t)))
-+			ret = -EFAULT;
++		if (!state->u.live.have_eventmsg && state->u.live.u.siginfo) {
++			ret = 0;
++			if (copy_from_user(state->u.live.u.siginfo,
++					   (siginfo_t __user *) data,
++					   sizeof(siginfo_t)))
++				ret = -EFAULT;
++		}
  		break;
 +	}
 +
@@ -6613,7 +6625,7 @@
 +	struct ptrace_state *state;
 +	struct task_struct *p;
 +	int err = -ECHILD;
-+	int why, status;
++	int exit_code, why, status;
 +
 +	rcu_read_lock();
 +	list_for_each_entry_rcu(state, &tsk->ptracees, entry) {
@@ -6671,17 +6683,19 @@
 +			 * the normal wait_task_zombie path instead.
 +			 */
 +			return 0;
-+		if ((p->exit_code & 0x7f) == 0) {
++		exit_code = p->exit_code;
++		if ((exit_code & 0x7f) == 0) {
 +			why = CLD_EXITED;
-+			status = p->exit_code >> 8;
++			status = exit_code >> 8;
 +		} else {
-+			why = (p->exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
-+			status = p->exit_code & 0xff;
++			why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
++			status = exit_code & 0x7f;
 +		}
 +	}
 +	else {
 +		why = CLD_TRAPPED;
-+		status = (p->exit_code << 8) | 0x7f;
++		status = p->exit_code;
++		exit_code = (status << 8) | 0x7f;
 +	}
  
  	/*
@@ -6711,7 +6725,7 @@
 +			err = put_user(status, &infop->si_status);
 +	}
 +	if (!err && stat_addr)
-+		err = put_user(status, stat_addr);
++		err = put_user(exit_code, stat_addr);
 +
 +	if (!err) {
 +		struct utrace *utrace;
@@ -6846,26 +6860,26 @@
 +		       si->si_addr);
 +	}
 +#endif
-+
-+	/*
+ 
+ 	/*
+-	 * This lock_kernel fixes a subtle race with suid exec
 +	 * Set our QUIESCE flag right now, before notifying the tracer.
 +	 * We do this before setting state->u.live.stopped rather than
 +	 * by using UTRACE_ACTION_NEWSTATE in our return value, to
 +	 * ensure that the tracer can't get the notification and then
 +	 * try to resume us with PTRACE_CONT before we set the flag.
-+	 */
+ 	 */
+-	lock_kernel();
+-	if (request == PTRACE_TRACEME) {
+-		ret = ptrace_traceme();
 +	utrace_set_flags(tsk, engine, engine->flags | UTRACE_ACTION_QUIESCE);
- 
- 	/*
--	 * This lock_kernel fixes a subtle race with suid exec
++
++	/*
 +	 * If regset 0 has a writeback call, do it now.  On register window
 +	 * machines, this makes sure the user memory backing the register
 +	 * data is up to date by the time wait_task_inactive returns to
 +	 * ptrace_start in our tracer doing a PTRACE_PEEKDATA or the like.
- 	 */
--	lock_kernel();
--	if (request == PTRACE_TRACEME) {
--		ret = ptrace_traceme();
++	 */
 +	regset = utrace_regset(tsk, engine, utrace_native_view(tsk), 0);
 +	if (regset->writeback)
 +		(*regset->writeback)(tsk, regset, 0);
@@ -7057,6 +7071,11 @@
 +		   struct task_struct *tsk, int type)
 +{
 +	struct ptrace_state *state = (struct ptrace_state *) engine->data;
++#ifdef PTRACE_DEBUG
++	printk("ptrace %d jctl notify %d type %x exit_code %x\n",
++	       tsk->pid, state->parent->pid, type, tsk->exit_code);
++#endif
++	state->u.live.reported = 0;
 +	do_notify(tsk, state->parent, type);
 +	return UTRACE_JCTL_NOSIGCHLD;
 +}
@@ -7414,7 +7433,7 @@
  
 --- linux-2.6/init/Kconfig.utrace-ptrace-compat
 +++ linux-2.6/init/Kconfig
-@@ -541,6 +541,35 @@ config STOP_MACHINE
+@@ -540,6 +540,35 @@ config STOP_MACHINE
  	  Need stop_machine() primitive.
  endmenu
  
@@ -8922,7 +8941,7 @@
  
 --- linux-2.6/arch/powerpc/lib/sstep.c.utrace-ptrace-compat
 +++ linux-2.6/arch/powerpc/lib/sstep.c
-@@ -12,6 +12,9 @@
+@@ -13,6 +13,9 @@
  #include <linux/ptrace.h>
  #include <asm/sstep.h>
  #include <asm/processor.h>
@@ -12197,7 +12216,7 @@
  obj-y		:= process.o setup.o cpu.o idprom.o \
 --- linux-2.6/arch/sparc64/kernel/entry.S.utrace-ptrace-compat
 +++ linux-2.6/arch/sparc64/kernel/entry.S
-@@ -1410,7 +1410,6 @@ execve_merge:
+@@ -1409,7 +1409,6 @@ execve_merge:
  
  	.globl	sys_pipe, sys_sigpause, sys_nis_syscall
  	.globl	sys_rt_sigreturn
@@ -12205,7 +12224,7 @@
  	.globl	sys_sigaltstack
  	.align	32
  sys_pipe:	ba,pt		%xcc, sparc_pipe
-@@ -1453,11 +1452,6 @@ sys32_rt_sigreturn:
+@@ -1452,11 +1451,6 @@ sys32_rt_sigreturn:
  		 add		%o7, 1f-.-4, %o7
  		nop
  #endif
@@ -12776,21 +12795,21 @@
 -			break;
 -		      case PT_B7:
 -			ptr = pt_reg_addr(pt, b7);
+-			break;
+-		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:
+-		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:
+-			ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);
 +	pt = task_pt_regs(target);
 +	switch (addr) {
 +		case ELF_GR_OFFSET(1):
 +			ptr = &pt->r1;
  			break;
--		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:
--		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:
--			ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);
+-		      case PT_AR_BSPSTORE:
+-			ptr = pt_reg_addr(pt, ar_bspstore);
 +		case ELF_GR_OFFSET(2):
 +		case ELF_GR_OFFSET(3):
 +			ptr = (void *)&pt->r2 + (addr - ELF_GR_OFFSET(2));
  			break;
--		      case PT_AR_BSPSTORE:
--			ptr = pt_reg_addr(pt, ar_bspstore);
--			break;
 -		      case PT_AR_UNAT:
 -			ptr = pt_reg_addr(pt, ar_unat);
 -			break;
@@ -12893,7 +12912,7 @@
  	}
  	if (write_access)
  		*ptr = *data;
-@@ -1104,567 +840,809 @@ access_uarea (struct task_struct *child,
+@@ -1104,567 +840,823 @@ access_uarea (struct task_struct *child,
  	return 0;
  }
  
@@ -12911,11 +12930,11 @@
 -	long ret, retval = 0;
 -	char nat = 0;
 -	int i;
--
--	if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
--		return -EIO;
 +	unsigned long *ptr = NULL;
  
+-	if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
+-		return -EIO;
+-
 -	pt = task_pt_regs(child);
 -	sw = (struct switch_stack *) (child->thread.ksp + 16);
 -	unw_init_from_blocked_task(&info, child);
@@ -13318,12 +13337,12 @@
  	struct pt_regs *pt;
 -	long ret, retval = 0;
 -	int i;
--
--	memset(&fpval, 0, sizeof(fpval));
 +	utrace_getset_t *dst = arg;
 +	elf_greg_t tmp[16];
 +	unsigned int i, index;
  
+-	memset(&fpval, 0, sizeof(fpval));
+-
 -	if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))
 -		return -EIO;
 +	if (unw_unwind_to_user(info) < 0)
@@ -13621,10 +13640,6 @@
 -	ia64_sync_fph(child);
 -	retval |= __copy_from_user(&child->thread.fph, &ppr->fr[32],
 -				   sizeof(ppr->fr[32]) * 96);
--
--	/* preds */
--
--	retval |= __get_user(pt->pr, &ppr->pr);
 +static int
 +do_regset_call(void (*call)(struct unw_frame_info *, void *),
 +	       struct task_struct *target,
@@ -13637,7 +13652,7 @@
 +				 .u.set = { .kbuf = kbuf, .ubuf = ubuf },
 +				 .ret = 0 };
  
--	/* nat bits */
+-	/* preds */
 +	if (target == current)
 +		unw_init_running(call, &info);
 +	else {
@@ -13647,18 +13662,11 @@
 +		(*call)(&ufi, &info);
 +	}
  
--	retval |= __get_user(nat_bits, &ppr->nat);
+-	retval |= __get_user(pt->pr, &ppr->pr);
 +	return info.ret;
 +}
  
--	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
--	retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);
--	retval |= access_uarea(child, PT_AR_EC, &ec, 1);
--	retval |= access_uarea(child, PT_AR_LC, &lc, 1);
--	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
--	retval |= access_uarea(child, PT_AR_BSP, &bsp, 1);
--	retval |= access_uarea(child, PT_CFM, &cfm, 1);
--	retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1);
+-	/* nat bits */
 +static int
 +gpregs_get(struct task_struct *target,
 +	   const struct utrace_regset *regset,
@@ -13668,16 +13676,38 @@
 +	return do_regset_call(do_gpregs_get, target, regset, pos, count, kbuf, ubuf);
 +}
  
--	ret = retval ? -EIO : 0;
--	return ret;
+-	retval |= __get_user(nat_bits, &ppr->nat);
 +static int gpregs_set(struct task_struct *target,
 +		const struct utrace_regset *regset,
 +		unsigned int pos, unsigned int count,
 +		const void *kbuf, const void __user *ubuf)
 +{
 +	return do_regset_call(do_gpregs_set, target, regset, pos, count, kbuf, ubuf);
- }
++}
  
+-	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+-	retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);
+-	retval |= access_uarea(child, PT_AR_EC, &ec, 1);
+-	retval |= access_uarea(child, PT_AR_LC, &lc, 1);
+-	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
+-	retval |= access_uarea(child, PT_AR_BSP, &bsp, 1);
+-	retval |= access_uarea(child, PT_CFM, &cfm, 1);
+-	retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1);
++static void do_gpregs_writeback(struct unw_frame_info *info, void *arg)
++{
++	struct pt_regs *pt;
++	utrace_getset_t *dst = arg;
++	unsigned long urbs_end;
+ 
+-	ret = retval ? -EIO : 0;
+-	return ret;
++	if (unw_unwind_to_user(info) < 0)
++		return;
++	pt = task_pt_regs(dst->target);
++	urbs_end = ia64_get_user_rbs_end(dst->target, pt, NULL);
++	dst->ret = ia64_sync_user_rbs(dst->target, info->sw, pt->ar_bspstore, urbs_end);
+ }
+-
  /*
 - * Called by kernel/ptrace.c when detaching..
 - *
@@ -13688,22 +13718,17 @@
   */
 -void
 -ptrace_disable (struct task_struct *child)
--{
++static int
++gpregs_writeback(struct task_struct *target,
++		 const struct utrace_regset *regset,
++		 int now)
+ {
 -	struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
 -
 -	/* make sure the single step/taken-branch trap bits are not set: */
 -	child_psr->ss = 0;
 -	child_psr->tb = 0;
-+static int
-+gpregs_writeback(struct task_struct *target,
-+		 const struct utrace_regset *regset,
-+		 int now)
-+{
-+	unsigned long urbs_end, cfm;
-+	struct pt_regs *pt = task_pt_regs(target);
-+	struct switch_stack *sw = (void *) (target->thread.ksp + 16);
-+	urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
-+	return ia64_sync_user_rbs(target, sw, pt->ar_bspstore, urbs_end);
++	return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, NULL, NULL);
  }
  
 -asmlinkage long
@@ -14085,18 +14110,24 @@
 +	offsetof(struct pt_all_user_regs, member), \
 +	offsetof(struct pt_all_user_regs, member) + num * sizeof(long)
 +static const struct ptrace_layout_segment pt_all_user_regs_layout[] = {
-+	{WORD(nat, 1),		0,	ELF_NAT_OFFSET},
-+	{WORD(cr_iip, 1),	0,	ELF_CR_IIP_OFFSET},
-+	{WORD(cfm, 1),		0,	ELF_CFM_OFFSET},
-+	{WORD(cr_ipsr, 1),	0,	ELF_CR_IPSR_OFFSET},
-+	{WORD(pr, 1),		0,	ELF_PR_OFFSET},
-+	{WORD(gr[0], 32),	0,	ELF_GR_OFFSET(0)},
-+	{WORD(br[0], 8),	0, 	ELF_BR_OFFSET(0)},
-+	{WORD(ar[PT_AUR_RSC], 4),  0,	ELF_AR_RSC_OFFSET},
-+	{WORD(ar[PT_AUR_CCV], 1),  0,	ELF_AR_CCV_OFFSET},
-+	{WORD(ar[PT_AUR_UNAT], 1), 0,	ELF_AR_UNAT_OFFSET},
-+	{WORD(ar[PT_AUR_FPSR], 1), 0,	ELF_AR_FPSR_OFFSET},
-+	{WORD(ar[PT_AUR_PFS], 3),  0,	ELF_AR_PFS_OFFSET},
++	{WORD(nat, 1),			0,	ELF_NAT_OFFSET},
++	{WORD(cr_iip, 1),		0,	ELF_CR_IIP_OFFSET},
++	{WORD(cfm, 1),			0,	ELF_CFM_OFFSET},
++	{WORD(cr_ipsr, 1),		0,	ELF_CR_IPSR_OFFSET},
++	{WORD(pr, 1),			0,	ELF_PR_OFFSET},
++	{WORD(gr[0], 32),		0,	ELF_GR_OFFSET(0)},
++	{WORD(br[0], 8),		0, 	ELF_BR_OFFSET(0)},
++	{WORD(ar[0], 16),		-1,	0},
++	{WORD(ar[PT_AUR_RSC], 4),	0,	ELF_AR_RSC_OFFSET},
++	{WORD(ar[PT_AUR_RNAT+1], 12),	-1,	0},
++	{WORD(ar[PT_AUR_CCV], 1),	0,	ELF_AR_CCV_OFFSET},
++	{WORD(ar[PT_AUR_CCV+1], 3),	-1,	0},
++	{WORD(ar[PT_AUR_UNAT], 1), 	0,	ELF_AR_UNAT_OFFSET},
++	{WORD(ar[PT_AUR_UNAT+1], 3),	-1,	0},
++	{WORD(ar[PT_AUR_FPSR], 1), 	0,	ELF_AR_FPSR_OFFSET},
++	{WORD(ar[PT_AUR_FPSR+1], 24), 	-1,	0},
++	{WORD(ar[PT_AUR_PFS], 3),  	0,	ELF_AR_PFS_OFFSET},
++	{WORD(ar[PT_AUR_EC+1], 62),	-1,	0},
 +	{offsetof(struct pt_all_user_regs, fr[0]),
 +	 offsetof(struct pt_all_user_regs, fr[128]),
 +	 1, 0},
@@ -14206,7 +14237,15 @@
  	data8 sys32_pause
 --- linux-2.6/arch/ia64/ia32/sys_ia32.c.utrace-ptrace-compat
 +++ linux-2.6/arch/ia64/ia32/sys_ia32.c
-@@ -1432,25 +1432,6 @@ sys32_waitpid (int pid, unsigned int *st
+@@ -44,6 +44,7 @@
+ #include <linux/eventpoll.h>
+ #include <linux/personality.h>
+ #include <linux/ptrace.h>
++#include <linux/tracehook.h>
+ #include <linux/stat.h>
+ #include <linux/ipc.h>
+ #include <linux/capability.h>
+@@ -1432,25 +1433,6 @@ sys32_waitpid (int pid, unsigned int *st
  	return compat_sys_wait4(pid, stat_addr, options, NULL);
  }
  
@@ -14232,7 +14271,7 @@
  /*
   *  The order in which registers are stored in the ptrace regs structure
   */
-@@ -1748,6 +1729,7 @@ restore_ia32_fpxstate (struct task_struc
+@@ -1748,6 +1730,7 @@ restore_ia32_fpxstate (struct task_struc
  	return 0;
  }
  
@@ -14240,7 +14279,7 @@
  asmlinkage long
  sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data)
  {
-@@ -1855,9 +1837,11 @@ sys32_ptrace (int request, pid_t pid, un
+@@ -1855,9 +1838,11 @@ sys32_ptrace (int request, pid_t pid, un
  					    compat_ptr(data));
  		break;
  
@@ -14252,11 +14291,524 @@
  
  	      case PTRACE_SYSCALL:	/* continue, stop after next syscall */
  	      case PTRACE_CONT:		/* restart after signal. */
-@@ -1878,6 +1862,7 @@ sys32_ptrace (int request, pid_t pid, un
+@@ -1878,6 +1863,520 @@ sys32_ptrace (int request, pid_t pid, un
  	unlock_kernel();
  	return ret;
  }
 +#endif
++
++#ifdef CONFIG_UTRACE
++typedef struct utrace_get {
++	void *kbuf;
++	void __user *ubuf;
++} utrace_get_t;
++
++typedef struct utrace_set {
++	const void *kbuf;
++	const void __user *ubuf;
++} utrace_set_t;
++
++typedef struct utrace_getset {
++	struct task_struct *target;
++	const struct utrace_regset *regset;
++	union {
++		utrace_get_t get;
++		utrace_set_t set;
++	} u;
++	unsigned int pos;
++	unsigned int count;
++	int ret;
++} utrace_getset_t;
++
++static void getfpreg(struct task_struct *task, int regno,int *val)
++{
++	switch (regno / sizeof(int)) {
++		case 0: *val = task->thread.fcr & 0xffff; break;
++		case 1: *val = task->thread.fsr & 0xffff; break;
++		case 2: *val = (task->thread.fsr>>16) & 0xffff; break;
++		case 3: *val = task->thread.fir; break;
++		case 4: *val = (task->thread.fir>>32) & 0xffff; break;
++		case 5: *val = task->thread.fdr; break;
++		case 6: *val = (task->thread.fdr >> 32) & 0xffff; break;
++	}
++}
++
++static void setfpreg(struct task_struct *task, int regno, int val)
++{
++	switch (regno / sizeof(int)) {
++		case 0:
++			task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++				| (val & 0x1f3f);
++			break;
++		case 1:
++			task->thread.fsr = (task->thread.fsr & (~0xffff)) | val;
++			break;
++		case 2:
++			task->thread.fsr = (task->thread.fsr & (~0xffff0000))
++				| (val << 16);
++			break;
++		case 3:
++			task->thread.fir = (task->thread.fir & (~0xffffffff)) | val;
++			break;
++		case 5:
++			task->thread.fdr = (task->thread.fdr & (~0xffffffff)) | val;
++			break;
++	}
++}
++
++static void access_fpreg_ia32(int regno, void *reg,
++		struct pt_regs *pt, struct switch_stack *sw,
++		int tos, int write)
++{
++	void *f;
++
++	if ((regno += tos) >= 8)
++		regno -= 8;
++	if (regno <= 4)
++		f = &pt->f8 + regno;
++	else if (regno <= 7)
++		f = &sw->f12 + (regno - 4);
++	else {
++		printk(" regno must be less than 7 \n");
++		 return;
++	}
++
++	if (write)
++		memcpy(f, reg, sizeof(struct _fpreg_ia32));
++	else
++		memcpy(reg, f, sizeof(struct _fpreg_ia32));
++}
++
++static void do_fpregs_get(struct unw_frame_info *info, void *arg)
++{
++	utrace_getset_t *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	int start, end, tos;
++	char buf[80];
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++	if (dst->pos < 7 * sizeof(int)) {
++		end = min((dst->pos + dst->count), (unsigned int)(7 * sizeof(int)));
++		for (start = dst->pos; start < end; start += sizeof(int))
++			getfpreg(task, start,(int *)( buf + start));
++		dst->ret = utrace_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++				0, 7 * sizeof(int));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = min(dst->pos + dst->count, 
++				(unsigned int)(sizeof(struct ia32_user_i387_struct)));
++		start = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		end = (end - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		for (; start < end; start++)
++			access_fpreg_ia32(start, (struct _fpreg_ia32 *)buf + start,
++					pt, info->sw, tos, 0);
++		dst->ret = utrace_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				buf, 7 * sizeof(int),
++				sizeof(struct ia32_user_i387_struct));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++}
++
++static void do_fpregs_set(struct unw_frame_info *info, void *arg)
++{
++	utrace_getset_t *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	char buf[80];
++	int end, start, tos;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++
++	if (dst->pos < 7 * sizeof(int)) {
++		start = dst->pos;
++		dst->ret = utrace_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, buf,
++				0, 7 * sizeof(int));
++		if (dst->ret)
++			return;
++		for (; start < dst->pos; start += sizeof(int))
++			setfpreg(task, start, *((int*)(buf + start)));
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++		start = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		dst->ret = utrace_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, 7 * sizeof(int),
++				sizeof(struct ia32_user_i387_struct));
++		if (dst->ret)
++			return;
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		for (; start < end; start++)
++			access_fpreg_ia32(start, (struct _fpreg_ia32 *)buf + start,
++					pt, info->sw, tos, 0);
++		if (dst->count == 0)
++			return;
++	}
++}
++
++#define OFFSET(member) ((int)(offsetof(struct ia32_user_fxsr_struct, member)))
++static void getfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++	int min_val;
++
++	min_val = min(end, OFFSET(fop));
++	while (start < min_val) {
++		if (start == OFFSET(cwd))
++			*((short *)buf) = task->thread.fcr & 0xffff;
++		else if (start == OFFSET(swd))
++			*((short *)buf) = task->thread.fsr & 0xffff;
++		else if (start == OFFSET(twd))
++			*((short *)buf) = (task->thread.fsr>>16) & 0xffff;
++		buf += 2;
++		start += 2;
++	}
++	/* skip fop element */
++	if (start == OFFSET(fop)) {
++		start += 2;
++		buf += 2;
++	}
++	while (start < end) {
++		if (start == OFFSET(fip))
++			*((int *)buf) = task->thread.fir;
++		else if (start == OFFSET(fcs))
++			*((int *)buf) = (task->thread.fir>>32) & 0xffff;
++		else if (start == OFFSET(foo))
++			*((int *)buf) = task->thread.fdr;
++		else if (start == OFFSET(fos))
++			*((int *)buf) = (task->thread.fdr>>32) & 0xffff;
++		else if (start == OFFSET(mxcsr))
++			*((int *)buf) = ((task->thread.fcr>>32) & 0xff80)
++					 | ((task->thread.fsr>>32) & 0x3f);
++		buf += 4;
++		start += 4;
++	}
++}
++
++static void setfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++	int min_val, num32;
++	short num;
++	unsigned long num64;
++
++	min_val = min(end, OFFSET(fop));
++	while (start < min_val) {
++		num = *((short *)buf);
++		if (start == OFFSET(cwd)) {
++			task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++						| (num & 0x1f3f);
++		} else if (start == OFFSET(swd)) {
++			task->thread.fsr = (task->thread.fsr & (~0xffff)) | num;
++		} else if (start == OFFSET(twd)) {
++			task->thread.fsr = (task->thread.fsr & (~0xffff0000)) | num;
++		}
++		buf += 2;
++		start += 2;
++	}
++	/* skip fop element */
++	if (start == OFFSET(fop)) {
++		start += 2;
++		buf += 2;
++	}
++	while (start < end) {
++		num32 = *((int *)buf);
++		if (start == OFFSET(fip))
++			task->thread.fir = (task->thread.fir & (~0xffffffff))
++						 | num32;
++		else if (start == OFFSET(foo))
++			task->thread.fdr = (task->thread.fdr & (~0xffffffff))
++						 | num32;
++		else if (start == OFFSET(mxcsr)) {
++			num64 = num32 & 0xff10;
++			task->thread.fcr = (task->thread.fcr & (~0xff1000000000UL))
++						 | (num64<<32);
++			num64 = num32 & 0x3f;
++			task->thread.fsr = (task->thread.fsr & (~0x3f00000000UL))
++						 | (num64<<32);
++		}
++		buf += 4;
++		start += 4;
++	}
++}
++
++static void do_fpxregs_get(struct unw_frame_info *info, void *arg)
++{
++	utrace_getset_t *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	char buf[128];
++	int start, end, tos;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++	if (dst->pos < OFFSET(st_space[0])) {
++		end = min(dst->pos + dst->count, (unsigned int)32);
++		getfpxreg(task, dst->pos, end, buf);
++		dst->ret = utrace_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++				0, OFFSET(st_space[0]));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(xmm_space[0])) {
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = min(dst->pos + dst->count, 
++				(unsigned int)OFFSET(xmm_space[0]));
++		start = (dst->pos - OFFSET(st_space[0])) / 16;
++		end = (end - OFFSET(st_space[0])) / 16;
++		for (; start < end; start++)
++			access_fpreg_ia32(start, buf + 16 * start, pt, 
++						info->sw, tos, 0);
++		dst->ret = utrace_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(padding[0]))
++		dst->ret = utrace_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				&info->sw->f16, OFFSET(xmm_space[0]),
++				OFFSET(padding[0]));
++}
++
++static void do_fpxregs_set(struct unw_frame_info *info, void *arg)
++{
++	utrace_getset_t *dst = arg;
++	struct task_struct *task = dst->target;
++	char buf[128];
++	int start, end;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++
++	if (dst->pos < OFFSET(st_space[0])) {
++		start = dst->pos;
++		dst->ret = utrace_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, 0, OFFSET(st_space[0]));
++		if (dst->ret)
++			return;
++		setfpxreg(task, start, dst->pos, buf);
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(xmm_space[0])) {
++		struct pt_regs *pt;
++		int tos;
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		start = (dst->pos - OFFSET(st_space[0])) / 16;
++		dst->ret = utrace_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++		if (dst->ret)
++			return;
++		end = (dst->pos - OFFSET(st_space[0])) / 16;
++		for (; start < end; start++)
++			access_fpreg_ia32(start, buf + 16 * start, pt, info->sw,
++						 tos, 1);
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(padding[0]))
++		dst->ret = utrace_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				&info->sw->f16, OFFSET(xmm_space[0]),
++				 OFFSET(padding[0]));
++}
++#undef OFFSET
++
++static int do_regset_call(void (*call)(struct unw_frame_info *, void *),
++		struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	utrace_getset_t info = { .target = target, .regset = regset,
++		.pos = pos, .count = count,
++		.u.set = { .kbuf = kbuf, .ubuf = ubuf },
++		.ret = 0 };
++
++	if (target == current)
++		unw_init_running(call, &info);
++	else {
++		struct unw_frame_info ufi;
++		memset(&ufi, 0, sizeof(ufi));
++		unw_init_from_blocked_task(&ufi, target);
++		(*call)(&ufi, &info);
++	}
++
++	return info.ret;
++}
++
++static int ia32_fpregs_get(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_get, target, regset, pos, count, kbuf, ubuf);
++}
++
++static int ia32_fpregs_set(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_set, target, regset, pos, count, kbuf, ubuf);
++}
++
++static int ia32_fpxregs_get(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_fpxregs_get, target, regset, pos, count, kbuf, ubuf);
++}
++
++static int ia32_fpxregs_set(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_fpxregs_set, target, regset, pos, count, kbuf, ubuf);
++}
++
++static int ia32_genregs_get(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	if (kbuf) {
++		u32 *kp = kbuf;
++		while (count > 0) {
++			*kp++ = getreg(target, pos);
++			pos += 4;
++			count -= 4;
++		}
++	} else {
++		u32 __user *up = ubuf;
++		while (count > 0) {
++			if (__put_user(getreg(target, pos), up++))
++				return -EFAULT;
++			pos += 4;
++			count -= 4;
++		}
++	}
++	return 0;
++}
++
++static int ia32_genregs_set(struct task_struct *target,
++		const struct utrace_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	int ret = 0;
++
++	if (kbuf) {
++		const u32 *kp = kbuf;
++		while (!ret && count > 0) {
++			putreg(target, pos, *kp++);
++			pos += 4;
++			count -= 4;
++		}
++	} else {
++		const u32 __user *up = ubuf;
++		u32 val;
++		while (!ret && count > 0) {
++			ret = __get_user(val, up++);
++			if (!ret)
++				putreg(target, pos, val);
++			pos += 4;
++			count -= 4;
++		}
++	}
++	return ret;
++}
++
++/*
++ * This should match arch/i386/kernel/ptrace.c:native_regsets.
++ * XXX ioperm? vm86?
++ */
++static const struct utrace_regset ia32_regsets[] = {
++	{
++		.n = sizeof(struct user_regs_struct32)/4,
++		.size = 4, .align = 4,
++		.get = ia32_genregs_get, .set = ia32_genregs_set
++	},
++	{
++		.n = sizeof(struct ia32_user_i387_struct) / 4,
++		.size = 4, .align = 4,
++		.get = ia32_fpregs_get, .set = ia32_fpregs_set
++	},
++	{
++		.n = sizeof(struct ia32_user_fxsr_struct) / 4,
++		.size = 4, .align = 4,
++		.get = ia32_fpxregs_get, .set = ia32_fpxregs_set
++	},
++};
++
++const struct utrace_regset_view utrace_ia32_view = {
++	.name = "i386", .e_machine = EM_386,
++	.regsets = ia32_regsets,
++	.n = sizeof ia32_regsets / sizeof ia32_regsets[0],
++};
++EXPORT_SYMBOL_GPL(utrace_ia32_view);
++#endif
++
++#ifdef CONFIG_PTRACE
++/*
++ * This matches the arch/i386/kernel/ptrace.c definitions.
++ */
++
++static const struct ptrace_layout_segment ia32_uarea[] = {
++	{0, sizeof(struct user_regs_struct32), 0, 0},
++	{0, 0, -1, 0}
++};
++
++fastcall int arch_compat_ptrace(compat_long_t *request,
++		struct task_struct *child,
++		struct utrace_attached_engine *engine,
++		compat_ulong_t addr, compat_ulong_t data,
++		compat_long_t *retval)
++{
++	switch (*request) {
++		case PTRACE_PEEKUSR:
++			return ptrace_compat_peekusr(child, engine, ia32_uarea,
++					addr, data);
++		case PTRACE_POKEUSR:
++			return ptrace_compat_pokeusr(child, engine, ia32_uarea,
++					addr, data);
++		case IA32_PTRACE_GETREGS:
++			return ptrace_whole_regset(child, engine, data, 0, 0);
++		case IA32_PTRACE_SETREGS:
++			return ptrace_whole_regset(child, engine, data, 0, 1);
++		case IA32_PTRACE_GETFPREGS:
++			return ptrace_whole_regset(child, engine, data, 1, 0);
++		case IA32_PTRACE_SETFPREGS:
++			return ptrace_whole_regset(child, engine, data, 1, 1);
++		case IA32_PTRACE_GETFPXREGS:
++			return ptrace_whole_regset(child, engine, data, 2, 0);
++		case IA32_PTRACE_SETFPXREGS:
++			return ptrace_whole_regset(child, engine, data, 2, 1);
++	}
++	return -ENOSYS;
++}
++#endif
  
  typedef struct {
  	unsigned int	ss_sp;
@@ -15644,7 +16196,7 @@
  	return ret;
 --- linux-2.6/arch/x86_64/kernel/process.c.utrace-ptrace-compat
 +++ linux-2.6/arch/x86_64/kernel/process.c
-@@ -675,11 +675,6 @@ long sys_execve(char __user *name, char 
+@@ -674,11 +674,6 @@ long sys_execve(char __user *name, char 
  	if (IS_ERR(filename)) 
  		return error;
  	error = do_execve(filename, argv, envp, &regs); 
@@ -16614,7 +17166,7 @@
  		break;
  
  	R32(cs, cs);
-@@ -167,234 +131,503 @@ static int getreg32(struct task_struct *
+@@ -167,236 +131,503 @@ static int getreg32(struct task_struct *
  	R32(eax, rax);
  	R32(orig_eax, orig_rax);
  	R32(eip, rip);
@@ -16667,7 +17219,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) {
@@ -16724,7 +17276,7 @@
 +static int
 +ia32_fpregs_active(struct task_struct *target,
 +		   const struct utrace_regset *regset)
-+{
+ {
 +	return tsk_used_math(target) ? regset->n : 0;
 +}
 +
@@ -16735,13 +17287,7 @@
 +		void *kbuf, 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)
@@ -16765,7 +17311,13 @@
 +		const void *kbuf, const 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)
@@ -16825,6 +17377,8 @@
 -	case PTRACE_DETACH:
 -	case PTRACE_SYSCALL:
 -	case PTRACE_SETOPTIONS:
+-	case PTRACE_SET_THREAD_AREA:
+-	case PTRACE_GET_THREAD_AREA:
 -		return sys_ptrace(request, pid, addr, data); 
 +static int
 +ia32_fpxregs_get(struct task_struct *target,




More information about the fedora-cvs-commits mailing list