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