rpms/kernel/devel kernel.spec, 1.144, 1.145 linux-2.6-utrace-core.patch, 1.5, 1.6 linux-2.6-utrace-ptrace-compat.patch, 1.4, 1.5 linux-2.6-utrace-tracehook.patch, 1.8, 1.9
Roland McGrath (roland)
fedora-extras-commits at redhat.com
Tue Sep 4 20:54:01 UTC 2007
Author: roland
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv8604
Modified Files:
kernel.spec linux-2.6-utrace-core.patch
linux-2.6-utrace-ptrace-compat.patch
linux-2.6-utrace-tracehook.patch
Log Message:
utrace update (#232837, #248532)
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.144
retrieving revision 1.145
diff -u -r1.144 -r1.145
--- kernel.spec 2 Sep 2007 05:40:37 -0000 1.144
+++ kernel.spec 4 Sep 2007 20:53:27 -0000 1.145
@@ -1789,6 +1789,9 @@
%changelog
+* Tue Sep 4 2007 Roland McGrath <roland at redhat.com>
+- utrace update (#232837, #248532)
+
* Sun Sep 02 2007 Dave Jones <davej at redhat.com>
- Fix oops in IPv4.
linux-2.6-utrace-core.patch:
Index: linux-2.6-utrace-core.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-core.patch,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- linux-2.6-utrace-core.patch 21 Aug 2007 19:42:55 -0000 1.5
+++ linux-2.6-utrace-core.patch 4 Sep 2007 20:53:27 -0000 1.6
@@ -20,7 +20,7 @@
---
kernel/Makefile | 1
- kernel/utrace.c | 2263 +++++++++++++++++++++++++++++++++++++
+ kernel/utrace.c | 2344 +++++++++++++++++++++++++++++++++++++
Documentation/utrace.txt | 579 +++++++++
Documentation/DocBook/Makefile | 2
Documentation/DocBook/utrace.tmpl | 23
@@ -28,7 +28,7 @@
include/linux/utrace.h | 544 +++++++++
include/linux/sched.h | 5
init/Kconfig | 20
- 9 files changed, 3504 insertions(+), 18 deletions(-)
+ 9 files changed, 3585 insertions(+), 18 deletions(-)
create kernel/utrace.c
create Documentation/utrace.txt
create Documentation/DocBook/utrace.tmpl
@@ -46,7 +46,7 @@
# According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
--- linux-2.6/kernel/utrace.c
+++ linux-2.6/kernel/utrace.c
-@@ -0,0 +1,2263 @@
+@@ -0,0 +1,2344 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -522,7 +522,7 @@
+ */
+struct utrace_attached_engine *
+utrace_attach(struct task_struct *target, int flags,
-+ const struct utrace_engine_ops *ops, void *data)
++ const struct utrace_engine_ops *ops, void *data)
+{
+ struct utrace *utrace;
+ struct utrace_attached_engine *engine;
@@ -624,10 +624,13 @@
+EXPORT_SYMBOL_GPL(utrace_attach);
+
+/*
-+ * When an engine is detached, the target thread may still see it and make
-+ * callbacks until it quiesces. We reset its event flags to just QUIESCE
-+ * and install a special ops vector whose callback is dead_engine_delete.
-+ * When the target thread quiesces, it can safely free the engine itself.
++ * When an engine is detached, the target thread may still see it
++ * and make callbacks until it quiesces. We install a special ops
++ * vector whose callbacks are all dead_engine_delete. When the
++ * target thread quiesces, it can safely free the engine itself.
++ * We must cover all callbacks in case of races between checking
++ * engine->flags and utrace_detach changing engine->ops.
++ * Only report_reap is never called due to a special case in utrace_reap.
+ */
+static u32
+dead_engine_delete(struct utrace_attached_engine *engine,
@@ -636,9 +639,38 @@
+ return UTRACE_ACTION_DETACH;
+}
+
++/*
++ * Don't use .report_xxx = ... style here because this way makes it easier
++ * to be sure we're forced to have an initializer here for every member.
++ */
+static const struct utrace_engine_ops dead_engine_ops =
+{
-+ .report_quiesce = &dead_engine_delete
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ unsigned long, struct task_struct *)) &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ pid_t)) &dead_engine_delete,
++ &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ struct pt_regs *, u32, siginfo_t *,
++ const struct k_sigaction *, struct k_sigaction *))
++ &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ int)) &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ const struct linux_binprm *, struct pt_regs *))
++ &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ struct pt_regs *)) &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ struct pt_regs *)) &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *,
++ long, long *)) &dead_engine_delete,
++ (u32 (*)(struct utrace_attached_engine *, struct task_struct *))
++ &dead_engine_delete,
++ NULL, /* report_reap */
++ NULL, /* allow_access_process_vm */
++ NULL, /* unsafe_exec */
++ NULL, /* tracer_task */
+};
+
+
@@ -844,9 +876,32 @@
+ return ret;
+ }
+
-+ flags = engine->flags;
-+ engine->flags = UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_QUIESCE;
++ /*
++ * This must work while the target thread races with us doing:
++ * if (engine->flags & UTRACE_EVENT(x)) REPORT(x, ...);
++ * The REPORT macro uses smp_rmb() between checking engine->flags
++ * and using engine->ops. Here we change engine->ops first, then
++ * use smp_wmb() before changing engine->flags. This ensures it
++ * can check the old flags before using the old ops, or check the
++ * old flags before using the new ops, or check the new flags
++ * before using the new ops, but can never check the new flags
++ * before using the old ops. Hence, dead_engine_ops might be used
++ * with any old flags in place. So, it has report_* callback
++ * pointers for every event type. Since it has to have those
++ * anyway, we enable (for after any potential race) all the events
++ * that have no overhead to enable. We want it to get into that
++ * callback and complete the detach ASAP.
++ */
+ rcu_assign_pointer(engine->ops, &dead_engine_ops);
++ smp_wmb();
++ flags = engine->flags;
++ engine->flags = (UTRACE_EVENT(QUIESCE)
++ | UTRACE_EVENT(CLONE)
++ | UTRACE_EVENT(VFORK_DONE)
++ | UTRACE_EVENT(EXEC)
++ | UTRACE_EVENT(EXIT)
++ | UTRACE_EVENT(JCTL)
++ | UTRACE_ACTION_QUIESCE);
+
+ if (quiesce(target, 1)) {
+ remove_engine(engine, target, utrace);
@@ -971,7 +1026,7 @@
+{
+ struct utrace *utrace;
+ int report;
-+ unsigned long old_flags, old_utrace_flags;
++ unsigned long old_flags, old_utrace_flags, set_utrace_flags;
+ int ret = -EALREADY;
+
+#ifdef ARCH_HAS_SINGLE_STEP
@@ -1005,6 +1060,22 @@
+ }
+
+ /*
++ * When it's in TASK_STOPPED state, do not set UTRACE_EVENT(JCTL).
++ * That bit indicates utrace_report_jctl has not run yet and so the
++ * target cannot be considered quiescent. But if the bit wasn't
++ * already set, it can't be in running in there and really is
++ * quiescent now in its existing job control stop. We set
++ * UTRACE_ACTION_QUIESCE to be sure that once it resumes it will
++ * recompute its flags in utrace_quiescent.
++ */
++ set_utrace_flags = flags;
++ if (((set_utrace_flags &~ old_utrace_flags) & UTRACE_EVENT(JCTL))
++ && target->state == TASK_STOPPED) {
++ set_utrace_flags &= ~UTRACE_EVENT(JCTL);
++ set_utrace_flags |= UTRACE_ACTION_QUIESCE;
++ }
++
++ /*
+ * When setting these flags, it's essential that we really
+ * synchronize with exit_notify. They cannot be set after
+ * exit_notify takes the tasklist_lock. By holding the read
@@ -1014,20 +1085,20 @@
+ * knows positively that utrace_report_death will be called or
+ * that it won't.
+ */
-+ if ((flags &~ old_utrace_flags) & (UTRACE_ACTION_NOREAP
-+ | DEATH_EVENTS)) {
++ if ((set_utrace_flags &~ old_utrace_flags) & (UTRACE_ACTION_NOREAP
++ | DEATH_EVENTS)) {
+ read_lock(&tasklist_lock);
+ if (unlikely(target->exit_state)) {
+ read_unlock(&tasklist_lock);
+ spin_unlock(&utrace->lock);
+ return ret;
+ }
-+ target->utrace_flags |= flags;
++ target->utrace_flags |= set_utrace_flags;
+ read_unlock(&tasklist_lock);
+ }
+
+ engine->flags = flags;
-+ target->utrace_flags |= flags;
++ target->utrace_flags |= set_utrace_flags;
+ ret = 0;
+
+ report = 0;
@@ -1149,10 +1220,20 @@
+ return ret;
+}
+
-+#define REPORT(callback, ...) do { \
-+ u32 ret = (*rcu_dereference(engine->ops)->callback) \
-+ (engine, tsk, ##__VA_ARGS__); \
-+ action = update_action(tsk, utrace, engine, ret); \
++/*
++ * This macro is always used after checking engine->flags.
++ * The smp_rmb() here pairs with smp_wmb() in utrace_detach.
++ * engine->ops changes before engine->flags, so the flags we
++ * just tested properly enabled this report for the real ops,
++ * or harmlessly enabled it for dead_engine_ops.
++ */
++#define REPORT(callback, ...) \
++ do { \
++ u32 ret; \
++ smp_rmb(); \
++ ret = (*rcu_dereference(engine->ops)->callback) \
++ (engine, tsk, ##__VA_ARGS__); \
++ action = update_action(tsk, utrace, engine, ret); \
+ } while (0)
+
+
@@ -3755,7 +3836,7 @@
+#endif /* linux/utrace.h */
--- linux-2.6/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
-@@ -1080,6 +1080,11 @@ struct task_struct {
+@@ -1081,6 +1081,11 @@ struct task_struct {
struct audit_context *audit_context;
seccomp_t seccomp;
linux-2.6-utrace-ptrace-compat.patch:
Index: linux-2.6-utrace-ptrace-compat.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-ptrace-compat.patch,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- linux-2.6-utrace-ptrace-compat.patch 21 Aug 2007 19:42:55 -0000 1.4
+++ linux-2.6-utrace-ptrace-compat.patch 4 Sep 2007 20:53:27 -0000 1.5
@@ -24,7 +24,7 @@
arch/powerpc/lib/sstep.c | 3
kernel/fork.c | 2
kernel/exit.c | 13
- kernel/ptrace.c | 2054 +++++++++++++++++++++++++++++++++++++--
+ kernel/ptrace.c | 2055 +++++++++++++++++++++++++++++++++++++--
kernel/sys_ni.c | 4
kernel/Makefile | 3
include/linux/sched.h | 4
@@ -32,7 +32,7 @@
include/asm-x86_64/tracehook.h | 1
include/asm-x86_64/ptrace-abi.h | 3
init/Kconfig | 15
- 20 files changed, 2641 insertions(+), 780 deletions(-)
+ 20 files changed, 2642 insertions(+), 780 deletions(-)
delete arch/powerpc/kernel/ptrace32.c
--- linux-2.6/fs/proc/base.c
@@ -1331,7 +1331,7 @@
tsk = next_thread(tsk);
--- linux-2.6/kernel/ptrace.c
+++ linux-2.6/kernel/ptrace.c
-@@ -19,213 +19,2007 @@
+@@ -19,213 +19,2008 @@
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/syscalls.h>
@@ -1394,19 +1394,66 @@
+};
+
+static const struct utrace_engine_ops ptrace_utrace_ops; /* Initialized below. */
+
+ /*
+- * Check that we have indeed attached to the thing..
++ * We use this bit in task_struct.exit_code of a ptrace'd task to indicate
++ * a ptrace stop. It must not overlap with any bits used in real exit_code's.
++ * Those are (PTRACE_EVENT_* << 8) | 0xff.
+ */
+-int ptrace_check_attach(struct task_struct *child, int kill)
++#define PTRACE_TRAPPED_MASK 0x10000
++
+
+static void
+ptrace_state_unlink(struct ptrace_state *state)
-+{
+ {
+- return -ENOSYS;
+ task_lock(state->parent);
+ list_del_rcu(&state->entry);
+ task_unlock(state->parent);
-+}
-+
+ }
+
+-static int may_attach(struct task_struct *task)
+static struct ptrace_state *
+ptrace_setup(struct task_struct *target, struct utrace_attached_engine *engine,
+ struct task_struct *parent, u8 options, int cap_sys_ptrace)
-+{
+ {
+- /* May we inspect the given task?
+- * This check is used both for attaching with ptrace
+- * and for allowing access to sensitive information in /proc.
+- *
+- * ptrace_attach denies several cases that /proc allows
+- * because setting up the necessary parent/child relationship
+- * or halting the specified task is impossible.
+- */
+- int dumpable = 0;
+- /* Don't let security modules deny introspection */
+- if (task == current)
+- return 0;
+- if (((current->uid != task->euid) ||
+- (current->uid != task->suid) ||
+- (current->uid != task->uid) ||
+- (current->gid != task->egid) ||
+- (current->gid != task->sgid) ||
+- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+- return -EPERM;
+- smp_rmb();
+- if (task->mm)
+- dumpable = get_dumpable(task->mm);
+- if (!dumpable && !capable(CAP_SYS_PTRACE))
+- return -EPERM;
+-
+- return security_ptrace(current, task);
+-}
+-
+-int ptrace_may_attach(struct task_struct *task)
+-{
+- int err;
+- task_lock(task);
+- err = may_attach(task);
+- task_unlock(task);
+- return !err;
+ struct ptrace_state *state;
+
+ NO_LOCKS;
@@ -1466,17 +1513,14 @@
+ BUG_ON(state->rcu.next);
+ call_rcu(&state->rcu, ptrace_state_free);
+}
-
- /*
-- * Check that we have indeed attached to the thing..
++
++/*
+ * Update the tracing engine state to match the new ptrace state.
- */
--int ptrace_check_attach(struct task_struct *child, int kill)
++ */
+static int __must_check
+ptrace_update(struct task_struct *target, struct ptrace_state *state,
+ unsigned long flags, int from_stopped)
- {
-- return -ENOSYS;
++{
+ int ret;
+
+ START_CHECK;
@@ -1541,9 +1585,8 @@
+ END_CHECK;
+
+ return ret;
- }
-
--static int may_attach(struct task_struct *task)
++}
++
+/*
+ * This does ptrace_update and also installs state in engine->data.
+ * Only after utrace_set_flags succeeds (in ptrace_update) inside
@@ -1555,42 +1598,7 @@
+ */
+static int __must_check
+ptrace_setup_finish(struct task_struct *target, struct ptrace_state *state)
- {
-- /* May we inspect the given task?
-- * This check is used both for attaching with ptrace
-- * and for allowing access to sensitive information in /proc.
-- *
-- * ptrace_attach denies several cases that /proc allows
-- * because setting up the necessary parent/child relationship
-- * or halting the specified task is impossible.
-- */
-- int dumpable = 0;
-- /* Don't let security modules deny introspection */
-- if (task == current)
-- return 0;
-- if (((current->uid != task->euid) ||
-- (current->uid != task->suid) ||
-- (current->uid != task->uid) ||
-- (current->gid != task->egid) ||
-- (current->gid != task->sgid) ||
-- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-- return -EPERM;
-- smp_rmb();
-- if (task->mm)
-- dumpable = get_dumpable(task->mm);
-- if (!dumpable && !capable(CAP_SYS_PTRACE))
-- return -EPERM;
--
-- return security_ptrace(current, task);
--}
--
--int ptrace_may_attach(struct task_struct *task)
--{
-- int err;
-- task_lock(task);
-- err = may_attach(task);
-- task_unlock(task);
-- return !err;
++{
+ int ret;
+
+ NO_LOCKS;
@@ -1607,12 +1615,11 @@
+ NO_LOCKS;
+
+ return ret;
- }
-
--int ptrace_attach(struct task_struct *task)
++}
++
+
+static int ptrace_traceme(void)
- {
++{
+ struct utrace_attached_engine *engine;
+ struct ptrace_state *state;
+ int retval;
@@ -1664,10 +1671,11 @@
+ NO_LOCKS;
+
+ return retval;
-+}
-+
+ }
+
+-int ptrace_attach(struct task_struct *task)
+static int ptrace_attach(struct task_struct *task)
-+{
+ {
+ struct utrace_attached_engine *engine;
+ struct ptrace_state *state;
int retval;
@@ -1685,9 +1693,8 @@
- retval = may_attach(task);
- if (retval)
+ if (!task->mm) /* kernel threads */
- goto bad;
-
-- retval = -ENOSYS;
++ goto bad;
++
+ pr_debug("%d ptrace_attach %d state %lu exit_code %x\n",
+ current->pid, task->pid, task->state, task->exit_code);
+
@@ -1699,9 +1706,10 @@
+ retval = PTR_ERR(engine);
+ if (retval == -EEXIST)
+ retval = -EPERM;
-+ goto bad;
+ goto bad;
+ }
-+
+
+- retval = -ENOSYS;
+ pr_debug("%d ptrace_attach %d after utrace_attach: %lu exit_code %x\n",
+ current->pid, task->pid, task->state, task->exit_code);
+
@@ -1735,8 +1743,6 @@
+ if (retval)
+ (void) utrace_detach(task, engine);
+ else {
-+ int stopped = 0;
-+
+ NO_LOCKS;
+
+ /*
@@ -1746,48 +1752,14 @@
+ * We cannot call into the signal code if it's dead.
+ */
+ read_lock(&tasklist_lock);
-+ if (likely(!task->exit_state)) {
++ if (likely(!task->exit_state))
+ force_sig_specific(SIGSTOP, task);
-+
-+ spin_lock_irq(&task->sighand->siglock);
-+ stopped = (task->state == TASK_STOPPED);
-+ spin_unlock_irq(&task->sighand->siglock);
-+ }
+ read_unlock(&tasklist_lock);
+
-+ if (stopped) {
-+ const struct utrace_regset *regset;
-+
-+ /*
-+ * Set QUIESCE immediately, so we can allow
-+ * ptrace requests while he's in TASK_STOPPED.
-+ */
-+ retval = ptrace_update(task, state, /* XXX child death+other thread waits race could have freed state already */
-+ UTRACE_ACTION_QUIESCE, 0);
-+ if (retval)
-+ /*
-+ * Anything is possible here. It might not
-+ * really have been quiescent yet. It
-+ * might have just woken up and died.
-+ */
-+ BUG_ON(retval != -ESRCH && retval != -EALREADY);
-+ retval = 0;
-+
-+ /*
-+ * Do now the regset 0 writeback that we do on every
-+ * stop, since it's never been done. On register
-+ * window machines, this makes sure the user memory
-+ * backing the register data is up to date.
-+ */
-+ regset = utrace_regset(task, engine,
-+ utrace_native_view(task), 0);
-+ if (regset->writeback)
-+ (*regset->writeback)(task, regset, 1);
-+ }
-+
+ pr_debug("%d ptrace_attach %d complete (%sstopped)"
+ " state %lu code %x",
-+ current->pid, task->pid, stopped ? "" : "not ",
++ current->pid, task->pid,
++ task->state == TASK_STOPPED ? "" : "not ",
+ task->state, task->exit_code);
+ }
@@ -2584,13 +2556,13 @@
+ return ret;
}
+#endif
++
-/**
- * ptrace_traceme -- helper for PTRACE_TRACEME
- *
- * Performs checks and sets PT_PTRACED.
- * Should be used by all ptrace implementations for PTRACE_TRACEME.
-+
+/*
+ * Detach the zombie being reported for wait.
*/
@@ -2752,7 +2724,29 @@
+ * check fails we are sure to get a wakeup if it stops.
+ */
+ exit_code = xchg(&p->exit_code, 0);
-+ if (exit_code)
++ if (exit_code & PTRACE_TRAPPED_MASK)
++ goto found;
++
++ /*
++ * If p was in job-control stop (TASK_STOPPED) rather than
++ * ptrace stop (TASK_TRACED), then SIGCONT can asynchronously
++ * clear it back to TASK_RUNNING. Until it gets scheduled
++ * and clears its own ->exit_code, our xchg below will see
++ * its stop signal. But, we must not report it if it's no
++ * longer in TASK_STOPPED, as vanilla wait would not--the
++ * caller can tell if it sent the SIGCONT before calling
++ * wait. We must somehow distinguish this from the case
++ * where p is in TASK_RUNNING with p->exit_code set because
++ * it is on its way to entering TASK_TRACED (QUIESCE) for our
++ * stop. So, ptrace_report sets the PTRACE_TRAPPED_MASK bit
++ * in exit_code when it's setting QUIESCE. For a job control
++ * control stop, that bit will never have been set. Since
++ * the bit's not set now, we should only report right now if
++ * p is still stopped. For this case we are protected by
++ * races the same wait that vanilla do_wait (exit.c) is:
++ * wait_chldexit is woken after p->state is set to TASK_STOPPED.
++ */
++ if (p->state == TASK_STOPPED)
+ goto found;
+
+ // XXX should handle WCONTINUED
@@ -2803,6 +2797,7 @@
+ }
+ else {
+ why = CLD_TRAPPED;
++ exit_code &= ~PTRACE_TRAPPED_MASK;
+ status = exit_code;
+ exit_code = (status << 8) | 0x7f;
+ }
@@ -2981,8 +2976,14 @@
+ */
+ utrace_set_flags(tsk, engine, engine->flags | UTRACE_ACTION_QUIESCE);
+
++ /*
++ * The PTRACE_TRAPPED_MASK bit distinguishes to ptrace_do_wait that
++ * this is a ptrace report, so we expect to enter TASK_TRACED but
++ * might not be there yet when examined.
++ */
+ BUG_ON(code == 0);
-+ tsk->exit_code = code;
++ WARN_ON(code &~ 0x7ff);
++ tsk->exit_code = code | PTRACE_TRAPPED_MASK;
+ do_notify(tsk, state->parent, CLD_TRAPPED);
+
+ pr_debug("%d ptrace_report quiescing exit_code %x\n",
@@ -3178,15 +3179,13 @@
+ NO_LOCKS;
+ printk(KERN_ERR "ptrace out of memory, lost child %d of %d",
+ child->pid, parent->pid);
- }
-
--int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
++}
++
+static u32
+ptrace_report_clone(struct utrace_attached_engine *engine,
+ struct task_struct *parent,
+ unsigned long clone_flags, struct task_struct *child)
- {
-- int copied;
++{
+ int event, option;
+ struct ptrace_state *state;
+
@@ -3217,9 +3216,7 @@
+ }
+ else
+ event = 0;
-
-- copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
-- return (copied == sizeof(data)) ? 0 : -EIO;
++
+ if (!(clone_flags & CLONE_UNTRACED)
+ && (event || (clone_flags & CLONE_PTRACE))) {
+ /*
@@ -3279,7 +3276,7 @@
+ state->have_eventmsg = 0;
+ state->u.siginfo = info;
+ return ptrace_report(engine, tsk, state, signo) | UTRACE_SIGNAL_IGN;
- }
++}
+
+static u32
+ptrace_report_jctl(struct utrace_attached_engine *engine,
@@ -3370,12 +3367,14 @@
+ struct task_struct *tsk, struct pt_regs *regs)
+{
+ return ptrace_report_syscall(engine, tsk, regs, 0);
-+}
-+
+ }
+
+-int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
+static u32
+ptrace_report_exit(struct utrace_attached_engine *engine,
+ struct task_struct *tsk, long orig_code, long *code)
-+{
+ {
+- int copied;
+ struct ptrace_state *state = get_ptrace_state(engine, tsk);
+ if (unlikely(state == NULL))
+ return UTRACE_ACTION_RESUME;
@@ -3402,9 +3401,11 @@
+ }
+
+ END_CHECK;
-+
+
+- copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+- return (copied == sizeof(data)) ? 0 : -EIO;
+ return unsafe;
-+}
+ }
+
+static struct task_struct *
+ptrace_tracer_task(struct utrace_attached_engine *engine,
@@ -3503,7 +3504,7 @@
# According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
--- linux-2.6/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
-@@ -1178,6 +1178,10 @@ struct task_struct {
+@@ -1179,6 +1179,10 @@ struct task_struct {
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
linux-2.6-utrace-tracehook.patch:
Index: linux-2.6-utrace-tracehook.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace-tracehook.patch,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- linux-2.6-utrace-tracehook.patch 1 Sep 2007 00:32:50 -0000 1.8
+++ linux-2.6-utrace-tracehook.patch 4 Sep 2007 20:53:27 -0000 1.9
@@ -221,7 +221,7 @@
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid);
-@@ -427,7 +433,7 @@ static int do_task_stat(struct task_stru
+@@ -441,7 +447,7 @@ static int do_task_stat(struct task_stru
sid = signal_session(sig);
pgid = process_group(task);
@@ -257,7 +257,7 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
-@@ -1161,13 +1161,7 @@ EXPORT_SYMBOL(prepare_binprm);
+@@ -1153,13 +1153,7 @@ EXPORT_SYMBOL(prepare_binprm);
static int unsafe_exec(struct task_struct *p)
{
@@ -272,7 +272,7 @@
if (atomic_read(&p->fs->count) > 1 ||
atomic_read(&p->files->count) > 1 ||
atomic_read(&p->sighand->count) > 1)
-@@ -1311,6 +1305,7 @@ int search_binary_handler(struct linux_b
+@@ -1303,6 +1297,7 @@ int search_binary_handler(struct linux_b
bprm->file = NULL;
current->did_exec = 1;
proc_exec_connector(current);
@@ -382,7 +382,7 @@
}
}
tsec->sid = sid;
-@@ -2754,11 +2760,6 @@ static int selinux_task_alloc_security(s
+@@ -2757,11 +2763,6 @@ static int selinux_task_alloc_security(s
tsec2->keycreate_sid = tsec1->keycreate_sid;
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
@@ -394,7 +394,7 @@
return 0;
}
-@@ -4541,6 +4542,7 @@ static int selinux_setprocattr(struct ta
+@@ -4544,6 +4545,7 @@ static int selinux_setprocattr(struct ta
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
@@ -402,7 +402,7 @@
u32 sid = 0;
int error;
char *str = value;
-@@ -4629,18 +4631,24 @@ static int selinux_setprocattr(struct ta
+@@ -4632,18 +4634,24 @@ static int selinux_setprocattr(struct ta
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
task_lock(p);
@@ -2621,7 +2621,7 @@
/*
* This signal will be fatal to the whole group.
*/
-@@ -1448,8 +1445,7 @@ void do_notify_parent(struct task_struct
+@@ -1447,8 +1444,7 @@ void do_notify_parent(struct task_struct
/* do_notify_parent_cldstop should have been called instead. */
BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
@@ -2631,7 +2631,7 @@
info.si_signo = sig;
info.si_errno = 0;
-@@ -1474,7 +1470,7 @@ void do_notify_parent(struct task_struct
+@@ -1473,7 +1469,7 @@ void do_notify_parent(struct task_struct
psig = tsk->parent->sighand;
spin_lock_irqsave(&psig->siglock, flags);
@@ -2640,7 +2640,7 @@
(psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
(psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
/*
-@@ -1502,20 +1498,13 @@ void do_notify_parent(struct task_struct
+@@ -1501,20 +1497,13 @@ void do_notify_parent(struct task_struct
spin_unlock_irqrestore(&psig->siglock, flags);
}
@@ -2662,7 +2662,7 @@
info.si_signo = SIGCHLD;
info.si_errno = 0;
info.si_pid = tsk->pid;
-@@ -1540,6 +1529,15 @@ static void do_notify_parent_cldstop(str
+@@ -1539,6 +1528,15 @@ static void do_notify_parent_cldstop(str
BUG();
}
@@ -2678,7 +2678,7 @@
sighand = parent->sighand;
spin_lock_irqsave(&sighand->siglock, flags);
if (sighand->action[SIGCHLD-1].sa.sa_handler != SIG_IGN &&
-@@ -1552,107 +1550,6 @@ static void do_notify_parent_cldstop(str
+@@ -1551,107 +1549,6 @@ static void do_notify_parent_cldstop(str
spin_unlock_irqrestore(&sighand->siglock, flags);
}
@@ -2786,7 +2786,7 @@
static void
finish_stop(int stop_count)
{
-@@ -1661,7 +1558,7 @@ finish_stop(int stop_count)
+@@ -1660,7 +1557,7 @@ finish_stop(int stop_count)
* a group stop in progress and we are the last to stop,
* report to the parent. When ptraced, every thread reports itself.
*/
@@ -2795,7 +2795,7 @@
read_lock(&tasklist_lock);
do_notify_parent_cldstop(current, CLD_STOPPED);
read_unlock(&tasklist_lock);
-@@ -1788,44 +1685,24 @@ relock:
+@@ -1787,44 +1684,24 @@ relock:
handle_group_stop())
goto relock;
@@ -2856,7 +2856,7 @@
if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
continue;
if (ka->sa.sa_handler != SIG_DFL) {
-@@ -1874,7 +1751,7 @@ relock:
+@@ -1873,7 +1750,7 @@ relock:
spin_lock_irq(¤t->sighand->siglock);
}
@@ -2865,7 +2865,7 @@
/* It released the siglock. */
goto relock;
}
-@@ -1903,13 +1780,13 @@ relock:
+@@ -1902,13 +1779,13 @@ relock:
* first and our do_group_exit call below will use
* that value and ignore the one we pass it.
*/
@@ -2881,7 +2881,7 @@
/* NOTREACHED */
}
spin_unlock_irq(¤t->sighand->siglock);
-@@ -1921,7 +1798,6 @@ EXPORT_SYMBOL_GPL(dequeue_signal);
+@@ -1920,7 +1797,6 @@ EXPORT_SYMBOL_GPL(dequeue_signal);
EXPORT_SYMBOL(flush_signals);
EXPORT_SYMBOL(force_sig);
EXPORT_SYMBOL(kill_proc);
@@ -2902,12 +2902,12 @@
stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
--- linux-2.6/kernel/sys.c
+++ linux-2.6/kernel/sys.c
-@@ -1470,7 +1470,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
+@@ -1469,7 +1469,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
if (!thread_group_leader(p))
goto out;
- if (p->real_parent->tgid == group_leader->tgid) {
-+ if (p->parent == group_leader) {
++ if (p->parent->tgid == group_leader->tgid) {
err = -EPERM;
if (task_session(p) != task_session(group_leader))
goto out;
@@ -3100,7 +3100,7 @@
--- linux-2.6/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
-@@ -938,7 +938,6 @@ struct task_struct {
+@@ -939,7 +939,6 @@ struct task_struct {
void *stack;
atomic_t usage;
unsigned int flags; /* per process flags, defined below */
@@ -3108,7 +3108,7 @@
int lock_depth; /* BKL lock depth */
-@@ -972,12 +971,6 @@ struct task_struct {
+@@ -973,12 +972,6 @@ struct task_struct {
#endif
struct list_head tasks;
@@ -3121,7 +3121,7 @@
struct mm_struct *mm, *active_mm;
-@@ -997,15 +990,13 @@ struct task_struct {
+@@ -998,15 +991,13 @@ struct task_struct {
unsigned long stack_canary;
#endif
/*
@@ -3139,7 +3139,7 @@
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
-@@ -1145,8 +1136,6 @@ struct task_struct {
+@@ -1146,8 +1137,6 @@ struct task_struct {
struct io_context *io_context;
@@ -3148,7 +3148,7 @@
/*
* current io wait handle: wait queue entry to use for io waits
* If this thread is processing aio, this points at the waitqueue
-@@ -1523,6 +1512,7 @@ extern int kill_pgrp(struct pid *pid, in
+@@ -1526,6 +1515,7 @@ extern int kill_pgrp(struct pid *pid, in
extern int kill_pid(struct pid *pid, int sig, int priv);
extern int kill_proc_info(int, struct siginfo *, pid_t);
extern void do_notify_parent(struct task_struct *, int);
More information about the fedora-extras-commits
mailing list