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(¤t->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(¤t->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, ®s);
@@ -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