rpms/kernel/devel kernel.spec, 1.759, 1.760 linux-2.6-ptrace-cleanup.patch, 1.2, 1.3 linux-2.6-tracehook.patch, 1.2, 1.3 linux-2.6-utrace.patch, 1.80, 1.81
Roland McGrath (roland)
fedora-extras-commits at redhat.com
Mon Jul 14 07:52:18 UTC 2008
Author: roland
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv21410
Modified Files:
kernel.spec linux-2.6-ptrace-cleanup.patch
linux-2.6-tracehook.patch linux-2.6-utrace.patch
Log Message:
utrace update
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.759
retrieving revision 1.760
diff -u -r1.759 -r1.760
--- kernel.spec 14 Jul 2008 00:33:14 -0000 1.759
+++ kernel.spec 14 Jul 2008 07:51:15 -0000 1.760
@@ -1788,6 +1788,9 @@
%kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL}.xen -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.xen.conf %{with_xen} xen
%changelog
+* Mon Jul 14 2008 Roland McGrath <roland at redhat.com>
+- utrace update
+
* Sun Jul 13 2008 Kyle McMartin <kmcmartin at redhat.com>
- Linux 2.6.26
linux-2.6-ptrace-cleanup.patch:
Index: linux-2.6-ptrace-cleanup.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-ptrace-cleanup.patch,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- linux-2.6-ptrace-cleanup.patch 12 Jul 2008 00:14:30 -0000 1.2
+++ linux-2.6-ptrace-cleanup.patch 14 Jul 2008 07:51:15 -0000 1.3
@@ -19,10 +19,10 @@
include/asm-x86/thread_info_64.h | 17 ++-
include/linux/init_task.h | 4 +-
include/linux/sched.h | 26 +--
- kernel/exit.c | 450 +++++++++++++++++++++++--------------
+ kernel/exit.c | 451 +++++++++++++++++++++++--------------
kernel/fork.c | 6 +-
kernel/ptrace.c | 37 ++-
- 24 files changed, 510 insertions(+), 373 deletions(-)
+ 24 files changed, 511 insertions(+), 373 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0c8614d..3a05e9f 100644
@@ -926,7 +926,7 @@
#define for_each_process(p) \
diff --git a/kernel/exit.c b/kernel/exit.c
-index 8f6185e..981a3bd 100644
+index 8f6185e..fa7b700 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -70,7 +70,7 @@ static void __unhash_process(struct task
@@ -978,7 +978,7 @@
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
-@@ -691,37 +701,96 @@ static void exit_mm(struct task_struct *
+@@ -691,37 +701,97 @@ static void exit_mm(struct task_struct *
mmput(mm);
}
@@ -996,10 +996,11 @@
- group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
+ int ret;
+ struct sighand_struct *psig = parent->sighand;
-+ spin_lock(&psig->siglock);
++ unsigned long flags;
++ spin_lock_irqsave(&psig->siglock, flags);
+ ret = (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
+ (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT));
-+ spin_unlock(&psig->siglock);
++ spin_unlock_irqrestore(&psig->siglock, flags);
+ return ret;
+}
@@ -1098,7 +1099,7 @@
/* If this is a threaded reparent there is no need to
* notify anyone anything has happened.
-@@ -736,7 +805,8 @@ reparent_thread(struct task_struct *p, s
+@@ -736,7 +806,8 @@ reparent_thread(struct task_struct *p, s
/* If we'd notified the old parent about this child's death,
* also notify the new parent.
*/
@@ -1108,7 +1109,7 @@
!task_detached(p) && thread_group_empty(p))
do_notify_parent(p, p->exit_signal);
-@@ -753,12 +823,15 @@ reparent_thread(struct task_struct *p, s
+@@ -753,12 +824,15 @@ reparent_thread(struct task_struct *p, s
static void forget_original_parent(struct task_struct *father)
{
struct task_struct *p, *n, *reaper = father;
@@ -1127,7 +1128,7 @@
do {
reaper = next_thread(reaper);
if (reaper == father) {
-@@ -767,58 +840,19 @@ static void forget_original_parent(struc
+@@ -767,58 +841,19 @@ static void forget_original_parent(struc
}
} while (reaper->flags & PF_EXITING);
@@ -1192,7 +1193,7 @@
}
/*
-@@ -1179,13 +1213,6 @@ static int eligible_child(enum pid_type
+@@ -1179,13 +1214,6 @@ static int eligible_child(enum pid_type
return 0;
}
@@ -1206,7 +1207,7 @@
/* Wait for all children (clone and not) if __WALL is set;
* otherwise, wait for clone children *only* if __WCLONE is
* set; otherwise, wait for non-clone children *only*. (Note:
-@@ -1196,14 +1223,10 @@ static int eligible_child(enum pid_type
+@@ -1196,14 +1224,10 @@ static int eligible_child(enum pid_type
return 0;
err = security_task_wait(p);
@@ -1224,7 +1225,7 @@
}
static int wait_noreap_copyout(struct task_struct *p, pid_t pid, uid_t uid,
-@@ -1237,7 +1260,7 @@ static int wait_noreap_copyout(struct ta
+@@ -1237,7 +1261,7 @@ static int wait_noreap_copyout(struct ta
* the lock and this task is uninteresting. If we return nonzero, we have
* released the lock and the system call should return.
*/
@@ -1233,7 +1234,7 @@
struct siginfo __user *infop,
int __user *stat_addr, struct rusage __user *ru)
{
-@@ -1245,7 +1268,10 @@ static int wait_task_zombie(struct task_
+@@ -1245,7 +1269,10 @@ static int wait_task_zombie(struct task_
int retval, status, traced;
pid_t pid = task_pid_vnr(p);
@@ -1245,7 +1246,7 @@
uid_t uid = p->uid;
int exit_code = p->exit_code;
int why, status;
-@@ -1395,21 +1421,24 @@ static int wait_task_zombie(struct task_
+@@ -1395,21 +1422,24 @@ static int wait_task_zombie(struct task_
* the lock and this task is uninteresting. If we return nonzero, we have
* released the lock and the system call should return.
*/
@@ -1273,7 +1274,7 @@
/*
* A group stop is in progress and this is the group leader.
* We won't report until all threads have stopped.
-@@ -1420,7 +1449,7 @@ static int wait_task_stopped(struct task
+@@ -1420,7 +1450,7 @@ static int wait_task_stopped(struct task
if (!exit_code)
goto unlock_sig;
@@ -1282,7 +1283,7 @@
p->exit_code = 0;
uid = p->uid;
-@@ -1438,10 +1467,10 @@ unlock_sig:
+@@ -1438,10 +1468,10 @@ unlock_sig:
*/
get_task_struct(p);
pid = task_pid_vnr(p);
@@ -1295,7 +1296,7 @@
return wait_noreap_copyout(p, pid, uid,
why, exit_code,
infop, ru);
-@@ -1475,7 +1504,7 @@ unlock_sig:
+@@ -1475,7 +1505,7 @@ unlock_sig:
* the lock and this task is uninteresting. If we return nonzero, we have
* released the lock and the system call should return.
*/
@@ -1304,7 +1305,7 @@
struct siginfo __user *infop,
int __user *stat_addr, struct rusage __user *ru)
{
-@@ -1483,6 +1512,9 @@ static int wait_task_continued(struct ta
+@@ -1483,6 +1513,9 @@ static int wait_task_continued(struct ta
pid_t pid;
uid_t uid;
@@ -1314,7 +1315,7 @@
if (!(p->signal->flags & SIGNAL_STOP_CONTINUED))
return 0;
-@@ -1492,7 +1524,7 @@ static int wait_task_continued(struct ta
+@@ -1492,7 +1525,7 @@ static int wait_task_continued(struct ta
spin_unlock_irq(&p->sighand->siglock);
return 0;
}
@@ -1323,7 +1324,7 @@
p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
spin_unlock_irq(&p->sighand->siglock);
-@@ -1518,89 +1550,161 @@ static int wait_task_continued(struct ta
+@@ -1518,89 +1551,161 @@ static int wait_task_continued(struct ta
return retval;
}
@@ -1550,7 +1551,7 @@
if (options & __WNOTHREAD)
break;
tsk = next_thread(tsk);
-@@ -1608,16 +1712,14 @@ repeat:
+@@ -1608,16 +1713,14 @@ repeat:
} while (tsk != current);
read_unlock(&tasklist_lock);
linux-2.6-tracehook.patch:
Index: linux-2.6-tracehook.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-tracehook.patch,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- linux-2.6-tracehook.patch 12 Jul 2008 00:14:30 -0000 1.2
+++ linux-2.6-tracehook.patch 14 Jul 2008 07:51:15 -0000 1.3
@@ -6,9 +6,9 @@
arch/ia64/kernel/signal.c | 8 +
arch/mips/kernel/irixelf.c | 2 -
arch/powerpc/Kconfig | 1 +
- arch/powerpc/kernel/entry_32.S | 4 +-
- arch/powerpc/kernel/entry_64.S | 3 +-
- arch/powerpc/kernel/ptrace.c | 33 +--
+ arch/powerpc/kernel/entry_32.S | 11 +-
+ arch/powerpc/kernel/entry_64.S | 10 +-
+ arch/powerpc/kernel/ptrace.c | 47 ++--
arch/powerpc/kernel/signal.c | 21 ++-
arch/sparc64/Kconfig | 1 +
arch/sparc64/kernel/ptrace.c | 24 +--
@@ -16,7 +16,7 @@
arch/sparc64/kernel/signal.c | 5 +
arch/x86/Kconfig | 1 +
arch/x86/ia32/ia32_aout.c | 6 -
- arch/x86/kernel/ptrace.c | 31 +--
+ arch/x86/kernel/ptrace.c | 34 +--
arch/x86/kernel/signal_32.c | 11 +-
arch/x86/kernel/signal_64.c | 49 +---
fs/binfmt_aout.c | 6 -
@@ -27,22 +27,22 @@
fs/exec.c | 12 +-
fs/proc/array.c | 9 +-
fs/proc/base.c | 39 +++-
- include/asm-generic/syscall.h | 137 +++++++++
+ include/asm-generic/syscall.h | 141 +++++++++
include/asm-ia64/thread_info.h | 3 -
include/asm-powerpc/ptrace.h | 1 +
include/asm-powerpc/signal.h | 3 +-
- include/asm-powerpc/syscall.h | 72 +++++
+ include/asm-powerpc/syscall.h | 73 +++++
include/asm-powerpc/thread_info.h | 5 +-
include/asm-sparc64/ptrace.h | 1 +
- include/asm-sparc64/syscall.h | 75 +++++
+ include/asm-sparc64/syscall.h | 70 +++++
include/asm-sparc64/thread_info.h | 8 +-
include/asm-x86/ptrace.h | 5 +
- include/asm-x86/syscall.h | 213 ++++++++++++++
+ include/asm-x86/syscall.h | 210 ++++++++++++++
include/asm-x86/thread_info_32.h | 2 +
include/asm-x86/thread_info_64.h | 4 +-
include/linux/ptrace.h | 72 +++++
include/linux/sched.h | 10 +-
- include/linux/tracehook.h | 566 +++++++++++++++++++++++++++++++++++++
+ include/linux/tracehook.h | 575 +++++++++++++++++++++++++++++++++++++
kernel/exit.c | 53 ++---
kernel/fork.c | 74 ++---
kernel/kthread.c | 2 +-
@@ -53,7 +53,7 @@
lib/syscall.c | 75 +++++
mm/nommu.c | 4 +-
security/selinux/hooks.c | 22 +--
- 55 files changed, 1555 insertions(+), 368 deletions(-)
+ 55 files changed, 1589 insertions(+), 371 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 3ea332b..1955fbd 100644
@@ -350,10 +350,24 @@
config EARLY_PRINTK
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
-index 3a05e9f..e057790 100644
+index 3a05e9f..eb40c67 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
-@@ -938,8 +938,8 @@ do_user_signal: /* r10 contains MSR_KE
+@@ -299,7 +299,12 @@ syscall_dotrace:
+ stw r0,_TRAP(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl do_syscall_trace_enter
+- lwz r0,GPR0(r1) /* Restore original registers */
++ /*
++ * Restore argument registers possibly just changed.
++ * We use the return value of do_syscall_trace_enter
++ * for call number to look up in the table (r0).
++ */
++ mr r0,r3
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+@@ -938,8 +943,8 @@ do_user_signal: /* r10 contains MSR_KE
SAVE_NVGPRS(r1)
rlwinm r3,r3,0,0,30
stw r3,_TRAP(r1)
@@ -365,10 +379,24 @@
REST_NVGPRS(r1)
b recheck
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
-index c0db5b7..9139ee6 100644
+index c0db5b7..2a13029 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
-@@ -632,8 +632,7 @@ user_work:
+@@ -213,7 +213,12 @@ syscall_dotrace:
+ bl .save_nvgprs
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .do_syscall_trace_enter
+- ld r0,GPR0(r1) /* Restore original registers */
++ /*
++ * Restore argument registers possibly just changed.
++ * We use the return value of do_syscall_trace_enter
++ * for the call number to look up in the table (r0).
++ */
++ mr r0,r3
+ ld r3,GPR3(r1)
+ ld r4,GPR4(r1)
+ ld r5,GPR5(r1)
+@@ -632,8 +637,7 @@ user_work:
b .ret_from_except_lite
1: bl .save_nvgprs
@@ -379,7 +407,7 @@
b .ret_from_except
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
-index 91ee077..9d2dd06 100644
+index 91ee077..b9bf411 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -22,6 +22,7 @@
@@ -390,12 +418,17 @@
#include <linux/elf.h>
#include <linux/user.h>
#include <linux/security.h>
-@@ -866,31 +867,12 @@ long arch_ptrace(struct task_struct *chi
+@@ -866,31 +867,24 @@ long arch_ptrace(struct task_struct *chi
return ret;
}
-static void do_syscall_trace(void)
--{
++/*
++ * We must return the syscall number to actually look up in the table.
++ * This can be -1L to skip running any syscall at all.
++ */
++long do_syscall_trace_enter(struct pt_regs *regs)
+ {
- /* the 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
@@ -411,20 +444,33 @@
- current->exit_code = 0;
- }
-}
--
- void do_syscall_trace_enter(struct pt_regs *regs)
- {
++ long ret = 0;
+
+-void do_syscall_trace_enter(struct pt_regs *regs)
+-{
secure_computing(regs->gpr[0]);
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- && (current->ptrace & PT_PTRACED))
- do_syscall_trace();
-+ if (test_thread_flag(TIF_SYSCALL_TRACE))
-+ tracehook_report_syscall_entry(regs);
++ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
++ tracehook_report_syscall_entry(regs))
++ /*
++ * Tracing decided this syscall should not happen.
++ * We'll return a bogus call number to get an ENOSYS
++ * error, but leave the original number in regs->gpr[0].
++ */
++ ret = -1L;
if (unlikely(current->audit_context)) {
#ifdef CONFIG_PPC64
-@@ -912,12 +894,13 @@ void do_syscall_trace_enter(struct pt_re
+@@ -908,16 +902,19 @@ void do_syscall_trace_enter(struct pt_re
+ regs->gpr[5] & 0xffffffff,
+ regs->gpr[6] & 0xffffffff);
+ }
++
++ return ret ?: regs->gpr[0];
+ }
void do_syscall_trace_leave(struct pt_regs *regs)
{
@@ -631,7 +677,7 @@
}
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
-index 652f550..8a194ed 100644
+index 652f550..d537484 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -14,6 +14,7 @@
@@ -673,16 +719,19 @@
#ifdef CONFIG_X86_32
# define IS_IA32 1
-@@ -1433,7 +1410,7 @@ asmregparm long syscall_trace_enter(stru
+@@ -1432,8 +1409,9 @@ asmregparm long syscall_trace_enter(stru
+ if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
ret = -1L;
- if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
+- if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
- syscall_trace(regs);
-+ tracehook_report_syscall_entry(regs);
++ if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
++ tracehook_report_syscall_entry(regs))
++ ret = -1L;
if (unlikely(current->audit_context)) {
if (IS_IA32)
-@@ -1459,7 +1436,7 @@ asmregparm void syscall_trace_leave(stru
+@@ -1459,7 +1437,7 @@ asmregparm void syscall_trace_leave(stru
audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
if (test_thread_flag(TIF_SYSCALL_TRACE))
@@ -691,7 +740,7 @@
/*
* If TIF_SYSCALL_EMU is set, we only get here because of
-@@ -1475,6 +1452,6 @@ asmregparm void syscall_trace_leave(stru
+@@ -1475,6 +1453,6 @@ asmregparm void syscall_trace_leave(stru
* system call instruction.
*/
if (test_thread_flag(TIF_SINGLESTEP) &&
@@ -1083,10 +1132,10 @@
ONE("statm", S_IRUGO, pid_statm),
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
new file mode 100644
-index ...2a9d2be 100644
+index ...fd57a55 100644
--- /dev/null
+++ b/include/asm-generic/syscall.h
-@@ -0,0 +1,137 @@
+@@ -0,0 +1,141 @@
+/*
+ * Access to user system call parameters and results
+ *
@@ -1126,18 +1175,22 @@
+long syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
+
+/**
-+ * syscall_abort - abort a traced system call about to begin
-+ * @task: task of interest, must be in system call entry tracing
++ * syscall_rollback - roll back registers after an aborted system call
++ * @task: task of interest, must be in system call exit tracing
+ * @regs: task_pt_regs() of @task
+ *
+ * It's only valid to call this when @task is stopped for system
-+ * call tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT).
-+ * It aborts the system call entry so no system call is made.
-+ * If @task ever returns to user mode after this, its register state
-+ * is unspecified, but should be something harmless like an
-+ * %ENOSYS error return.
++ * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT),
++ * after tracehook_report_syscall_entry() returned nonzero to prevent
++ * the system call from taking place.
++ *
++ * This rolls back the register state in @regs so it's as if the
++ * system call instruction was a no-op. The registers containing
++ * the system call number and arguments are as they were before the
++ * system call instruction. This may not be the same as what the
++ * register state looked like at system call entry tracing.
+ */
-+void syscall_abort(struct task_struct *task, struct pt_regs *regs);
++void syscall_rollback(struct task_struct *task, struct pt_regs *regs);
+
+/**
+ * syscall_get_error - check result of traced system call
@@ -1266,10 +1319,10 @@
diff --git a/include/asm-powerpc/syscall.h b/include/asm-powerpc/syscall.h
new file mode 100644
-index ...4b37467 100644
+index ...174e1ad 100644
--- /dev/null
+++ b/include/asm-powerpc/syscall.h
-@@ -0,0 +1,72 @@
+@@ -0,0 +1,73 @@
+/*
+ * Access to user system call parameters and results
+ *
@@ -1293,9 +1346,10 @@
+ return regs->trap == 0xc01 ? regs->gpr[0] : -1L;
+}
+
-+static inline void syscall_abort(struct task_struct *task, struct pt_regs *regs)
++static inline void syscall_rollback(struct task_struct *task,
++ struct pt_regs *regs)
+{
-+ regs->gpr[0] = -1L;
++ regs->gpr[3] = regs->orig_gpr3;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
@@ -1384,10 +1438,10 @@
extern unsigned long profile_pc(struct pt_regs *);
diff --git a/include/asm-sparc64/syscall.h b/include/asm-sparc64/syscall.h
new file mode 100644
-index ...78e8a96 100644
+index ...c00fb1a 100644
--- /dev/null
+++ b/include/asm-sparc64/syscall.h
-@@ -0,0 +1,75 @@
+@@ -0,0 +1,70 @@
+/*
+ * Access to user system call parameters and results
+ *
@@ -1412,11 +1466,6 @@
+ return pt_regs_is_syscall(regs) ? regs->u_regs[UREG_G1] : -1L;
+}
+
-+static inline void syscall_abort(struct task_struct *task, struct pt_regs *regs)
-+{
-+ regs->u_regs[UREG_G1] = -1L;
-+}
-+
+static inline long syscall_get_error(struct task_struct *task,
+ struct pt_regs *regs)
+{
@@ -1514,10 +1563,10 @@
*/
diff --git a/include/asm-x86/syscall.h b/include/asm-x86/syscall.h
new file mode 100644
-index ...464addc 100644
+index ...7de35f0 100644
--- /dev/null
+++ b/include/asm-x86/syscall.h
-@@ -0,0 +1,213 @@
+@@ -0,0 +1,210 @@
+/*
+ * Access to user system call parameters and results
+ *
@@ -1545,13 +1594,10 @@
+ return regs->orig_ax;
+}
+
-+static inline void syscall_abort(struct task_struct *task, struct pt_regs *regs)
++static inline void syscall_rollback(struct task_struct *task,
++ struct pt_regs *regs)
+{
-+ /*
-+ * This will make it diagnose -1 as out of range for
-+ * syscall numbers and return what's in regs->ax (-ENOSYS).
-+ */
-+ regs->orig_ax = -1L;
++ regs->ax = regs->orig_ax;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
@@ -1901,10 +1947,10 @@
#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
new file mode 100644
-index ...88ce8af 100644
+index ...61d4ca4 100644
--- /dev/null
+++ b/include/linux/tracehook.h
-@@ -0,0 +1,566 @@
+@@ -0,0 +1,575 @@
+/*
+ * Tracing hooks
+ *
@@ -2006,11 +2052,20 @@
+ * in @regs can affect the system call number and arguments to be tried.
+ * It is safe to block here, preventing the system call from beginning.
+ *
++ * Returns zero normally, or nonzero if the calling arch code should abort
++ * the system call. That must prevent normal entry so no system call is
++ * made. If @task ever returns to user mode after this, its register state
++ * is unspecified, but should be something harmless like an %ENOSYS error
++ * return. It should preserve enough information so that syscall_rollback()
++ * can work (see asm-generic/syscall.h).
++ *
+ * Called without locks, just after entering kernel mode.
+ */
-+static inline void tracehook_report_syscall_entry(struct pt_regs *regs)
++static inline __must_check int tracehook_report_syscall_entry(
++ struct pt_regs *regs)
+{
+ ptrace_report_syscall(regs);
++ return 0;
+}
+
+/**
@@ -2472,7 +2527,7 @@
+
+#endif /* <linux/tracehook.h> */
diff --git a/kernel/exit.c b/kernel/exit.c
-index 981a3bd..a119a53 100644
+index fa7b700..a0225e2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -45,6 +45,7 @@
@@ -2527,7 +2582,7 @@
}
write_unlock_irq(&tasklist_lock);
-@@ -861,7 +859,8 @@ static void forget_original_parent(struc
+@@ -862,7 +860,8 @@ static void forget_original_parent(struc
*/
static void exit_notify(struct task_struct *tsk, int group_dead)
{
@@ -2537,7 +2592,7 @@
/*
* This does two things:
-@@ -898,22 +897,11 @@ static void exit_notify(struct task_stru
+@@ -899,22 +898,11 @@ static void exit_notify(struct task_stru
!capable(CAP_KILL))
tsk->exit_signal = SIGCHLD;
@@ -2565,7 +2620,7 @@
/* mt-exec, de_thread() is waiting for us */
if (thread_group_leader(tsk) &&
-@@ -923,8 +911,10 @@ static void exit_notify(struct task_stru
+@@ -924,8 +912,10 @@ static void exit_notify(struct task_stru
write_unlock_irq(&tasklist_lock);
@@ -2577,7 +2632,7 @@
release_task(tsk);
}
-@@ -1003,10 +993,7 @@ NORET_TYPE void do_exit(long code)
+@@ -1004,10 +994,7 @@ NORET_TYPE void do_exit(long code)
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
linux-2.6-utrace.patch:
Index: linux-2.6-utrace.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace.patch,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -r1.80 -r1.81
--- linux-2.6-utrace.patch 12 Jul 2008 00:14:30 -0000 1.80
+++ linux-2.6-utrace.patch 14 Jul 2008 07:51:15 -0000 1.81
@@ -4,14 +4,14 @@
fs/proc/array.c | 3 +
include/linux/ptrace.h | 15 +
include/linux/sched.h | 6 +
- include/linux/tracehook.h | 59 +
- include/linux/utrace.h | 501 +++++++++
+ include/linux/tracehook.h | 60 +
+ include/linux/utrace.h | 534 +++++++++
init/Kconfig | 28 +
kernel/Makefile | 1 +
- kernel/ptrace.c | 472 ++++++++-
+ kernel/ptrace.c | 542 +++++++++-
kernel/signal.c | 14 +-
- kernel/utrace.c | 2210 +++++++++++++++++++++++++++++++++++++
- 13 files changed, 3907 insertions(+), 4 deletions(-)
+ kernel/utrace.c | 2222 +++++++++++++++++++++++++++++++++++++
+ 13 files changed, 4023 insertions(+), 4 deletions(-)
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 0eb0d02..49a78b7 100644
@@ -717,7 +717,7 @@
extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
-index 88ce8af..a68801f 100644
+index 61d4ca4..8e7ff75 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -49,6 +49,7 @@
@@ -737,16 +737,17 @@
return (task_ptrace(task) & PT_PTRACED);
}
-@@ -103,6 +106,8 @@ static inline void ptrace_report_syscall
- */
- static inline void tracehook_report_syscall_entry(struct pt_regs *regs)
+@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall
+ static inline __must_check int tracehook_report_syscall_entry(
+ struct pt_regs *regs)
{
-+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY))
-+ utrace_report_syscall_entry(regs);
++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) &&
++ utrace_report_syscall_entry(regs))
++ return 1;
ptrace_report_syscall(regs);
+ return 0;
}
-
-@@ -125,6 +130,8 @@ static inline void tracehook_report_sysc
+@@ -134,6 +140,8 @@ static inline __must_check int tracehook
*/
static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
{
@@ -755,7 +756,7 @@
ptrace_report_syscall(regs);
}
-@@ -146,6 +153,8 @@ static inline int tracehook_unsafe_exec(
+@@ -155,6 +163,8 @@ static inline int tracehook_unsafe_exec(
else
unsafe |= LSM_UNSAFE_PTRACE;
}
@@ -764,7 +765,7 @@
return unsafe;
}
-@@ -164,6 +173,8 @@ static inline struct task_struct *traceh
+@@ -173,6 +183,8 @@ static inline struct task_struct *traceh
{
if (task_ptrace(tsk) & PT_PTRACED)
return rcu_dereference(tsk->parent);
@@ -773,7 +774,7 @@
return NULL;
}
-@@ -185,6 +196,8 @@ static inline void tracehook_report_exec
+@@ -194,6 +206,8 @@ static inline void tracehook_report_exec
struct linux_binprm *bprm,
struct pt_regs *regs)
{
@@ -782,7 +783,7 @@
if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
unlikely(task_ptrace(current) & PT_PTRACED))
send_sig(SIGTRAP, current, 0);
-@@ -202,6 +215,8 @@ static inline void tracehook_report_exec
+@@ -211,6 +225,8 @@ static inline void tracehook_report_exec
*/
static inline void tracehook_report_exit(long *exit_code)
{
@@ -791,7 +792,7 @@
ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXIT, *exit_code);
}
-@@ -245,6 +260,7 @@ static inline int tracehook_prepare_clon
+@@ -254,6 +270,7 @@ static inline int tracehook_prepare_clon
static inline void tracehook_finish_clone(struct task_struct *child,
unsigned long clone_flags, int trace)
{
@@ -799,7 +800,7 @@
ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
}
-@@ -270,6 +286,8 @@ static inline void tracehook_report_clon
+@@ -279,6 +296,8 @@ static inline void tracehook_report_clon
unsigned long clone_flags,
pid_t pid, struct task_struct *child)
{
@@ -808,7 +809,7 @@
if (unlikely(trace)) {
/*
* The child starts up with an immediate SIGSTOP.
-@@ -335,6 +353,9 @@ static inline void tracehook_report_vfor
+@@ -344,6 +363,9 @@ static inline void tracehook_report_vfor
*/
static inline void tracehook_prepare_release_task(struct task_struct *task)
{
@@ -818,7 +819,7 @@
}
/**
-@@ -348,7 +369,21 @@ static inline void tracehook_prepare_rel
+@@ -357,7 +379,21 @@ static inline void tracehook_prepare_rel
*/
static inline void tracehook_finish_release_task(struct task_struct *task)
{
@@ -840,7 +841,7 @@
}
/**
-@@ -370,8 +405,12 @@ static inline void tracehook_signal_hand
+@@ -379,8 +415,12 @@ static inline void tracehook_signal_hand
const struct k_sigaction *ka,
struct pt_regs *regs, int stepping)
{
@@ -853,7 +854,7 @@
}
/**
-@@ -390,6 +429,8 @@ static inline int tracehook_consider_ign
+@@ -399,6 +439,8 @@ static inline int tracehook_consider_ign
int sig,
void __user *handler)
{
@@ -862,7 +863,7 @@
return (task_ptrace(task) & PT_PTRACED);
}
-@@ -411,6 +452,9 @@ static inline int tracehook_consider_fat
+@@ -420,6 +462,9 @@ static inline int tracehook_consider_fat
int sig,
void __user *handler)
{
@@ -872,7 +873,7 @@
return (task_ptrace(task) & PT_PTRACED);
}
-@@ -425,6 +469,8 @@ static inline int tracehook_consider_fat
+@@ -434,6 +479,8 @@ static inline int tracehook_consider_fat
*/
static inline int tracehook_force_sigpending(void)
{
@@ -881,7 +882,7 @@
return 0;
}
-@@ -454,6 +500,8 @@ static inline int tracehook_get_signal(s
+@@ -463,6 +510,8 @@ static inline int tracehook_get_signal(s
siginfo_t *info,
struct k_sigaction *return_ka)
{
@@ -890,7 +891,7 @@
return 0;
}
-@@ -474,6 +522,8 @@ static inline int tracehook_get_signal(s
+@@ -483,6 +532,8 @@ static inline int tracehook_get_signal(s
*/
static inline int tracehook_notify_jctl(int notify, int why)
{
@@ -899,7 +900,7 @@
return notify || (current->ptrace & PT_PTRACED);
}
-@@ -491,6 +541,8 @@ static inline int tracehook_notify_jctl(
+@@ -500,6 +551,8 @@ static inline int tracehook_notify_jctl(
static inline int tracehook_notify_death(struct task_struct *task,
void **death_cookie, int group_dead)
{
@@ -908,7 +909,7 @@
if (task->exit_signal == -1)
return task->ptrace ? SIGCHLD : -1;
-@@ -527,6 +579,10 @@ static inline void tracehook_report_deat
+@@ -536,6 +589,10 @@ static inline void tracehook_report_deat
int signal, void *death_cookie,
int group_dead)
{
@@ -919,7 +920,7 @@
}
#ifdef TIF_NOTIFY_RESUME
-@@ -560,6 +616,9 @@ static inline void set_notify_resume(str
+@@ -569,6 +626,9 @@ static inline void set_notify_resume(str
*/
static inline void tracehook_notify_resume(struct pt_regs *regs)
{
@@ -931,10 +932,10 @@
diff --git a/include/linux/utrace.h b/include/linux/utrace.h
new file mode 100644
-index ...4622ed0 100644
+index ...b264763 100644
--- /dev/null
+++ b/include/linux/utrace.h
-@@ -0,0 +1,501 @@
+@@ -0,0 +1,534 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -1059,7 +1060,7 @@
+void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *,
+ struct pt_regs *regs)
+ __attribute__((weak));
-+void utrace_report_syscall_entry(struct pt_regs *)
++bool utrace_report_syscall_entry(struct pt_regs *)
+ __attribute__((weak));
+void utrace_report_syscall_exit(struct pt_regs *)
+ __attribute__((weak));
@@ -1220,6 +1221,34 @@
+
+#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */
+
++/**
++ * enum utrace_syscall_action - disposition of signal
++ * @UTRACE_SYSCALL_RUN: Run the system call.
++ * @UTRACE_SYSCALL_ABORT: Don't run the system call.
++ *
++ * This is encoded in the @action argument and the return value for
++ * a @report_syscall_entry callback.
++ */
++enum utrace_syscall_action {
++ UTRACE_SYSCALL_RUN = 0x00,
++ UTRACE_SYSCALL_ABORT = 0x10
++};
++#define UTRACE_SYSCALL_MASK 0xf0
++
++/**
++ * utrace_syscall_action - &enum utrace_syscall_action from callback action
++ * @action: @report_syscall_entry callback @action or return value
++ *
++ * This extracts the &enum utrace_syscall_action from @action, which
++ * is the @action argument to a @report_syscall_entry callback or the
++ * return value from one.
++ */
++static inline enum utrace_syscall_action utrace_syscall_action(u32 action)
++{
++ return action & UTRACE_SYSCALL_MASK;
++}
++
++
+#define UTRACE_HIDE_EVENT XXX
+
+/*
@@ -1334,8 +1363,13 @@
+ /*
+ * Thread has entered the kernel to request a system call.
+ * The user register state is handy to be tweaked directly.
++ * The @action argument contains an &enum utrace_syscall_action,
++ * use utrace_syscall_action() to extract it. The return value
++ * overrides the last engine's action for the system call.
++ * If the final action is %UTRACE_SYSCALL_ABORT, no system call
++ * is made.
+ */
-+ u32 (*report_syscall_entry)(enum utrace_resume_action action,
++ u32 (*report_syscall_entry)(u32 action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *task,
+ struct pt_regs *regs);
@@ -1488,7 +1522,7 @@
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
-index ef66127..9003b0e 100644
+index ef66127..dcf30f5 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -16,6 +16,7 @@
@@ -1549,7 +1583,7 @@
/*
* Check that we have indeed attached to the thing..
*/
-@@ -113,6 +137,367 @@ int ptrace_check_attach(struct task_stru
+@@ -113,6 +137,440 @@ int ptrace_check_attach(struct task_stru
return ret;
}
@@ -1623,16 +1657,23 @@
+ return target->parent;
+}
+
++static void ptrace_set_action(struct task_struct *task,
++ enum utrace_resume_action action,
++ enum utrace_syscall_action syscall)
++{
++ task->ptrace &= ~((UTRACE_SYSCALL_MASK | UTRACE_RESUME_MASK) << 16);
++ task->ptrace |= ((UTRACE_RESUME - action) | syscall) << 16;
++}
++
+static enum utrace_resume_action ptrace_resume_action(struct task_struct *task)
+{
-+ return UTRACE_RESUME - (task->ptrace >> 16);
++ return UTRACE_RESUME - ((task->ptrace >> 16) & UTRACE_RESUME_MASK);
+}
+
-+static void ptrace_set_action(struct task_struct *task,
-+ enum utrace_resume_action action)
++static enum utrace_syscall_action ptrace_syscall_action(
++ struct task_struct *task)
+{
-+ task->ptrace &= ~(UTRACE_RESUME_MASK << 16);
-+ task->ptrace |= (UTRACE_RESUME - action) << 16;
++ return (task->ptrace >> 16) & UTRACE_SYSCALL_MASK;
+}
+
+static u32 utrace_ptrace_report(u32 action, struct task_struct *task, int code)
@@ -1642,7 +1683,7 @@
+ * and calls do_notify_parent_cldstop() for us. This kludge
+ * is necessary to keep that wakeup after we enter TASK_TRACED.
+ */
-+ ptrace_set_action(task, UTRACE_STOP);
++ ptrace_set_action(task, UTRACE_STOP, 0);
+
+ task->exit_code = code;
+
@@ -1681,6 +1722,8 @@
+ return utrace_ptrace_event(task, PTRACE_EVENT_EXIT, *code);
+}
+
++#define PT_VFORKING PT_DTRACE /* reuse obsolete bit */
++
+static u32 ptrace_report_clone(enum utrace_resume_action action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *parent,
@@ -1692,15 +1735,18 @@
+
+ /*
+ * To simulate vfork-done tracing, we'll have to catch the
-+ * parent's syscall-exit event for this vfork system call.
++ * parent's syscall-exit event for this vfork/clone system call.
++ * Since PTRACE_SETOPTIONS can enable PTRACE_O_TRACEVFORKDONE
++ * during the PTRACE_EVENT_VFORK stop, we must do this if either
++ * is enabled right now.
+ */
-+ if (parent->ptrace & PT_TRACE_VFORK_DONE) {
++ if ((clone_flags & CLONE_VFORK) &&
++ (parent->ptrace & (PT_TRACE_VFORK | PT_TRACE_VFORK_DONE))) {
+ if (!(engine->flags & UTRACE_EVENT(SYSCALL_EXIT)))
+ utrace_set_events(parent, engine,
+ engine->flags |
+ UTRACE_EVENT(SYSCALL_EXIT));
-+ // XXX
-+ WARN_ON(1);
++ parent->ptrace |= PT_VFORKING;
+ }
+
+ if (clone_flags & CLONE_UNTRACED)
@@ -1742,31 +1788,69 @@
+ return utrace_ptrace_event(parent, event, child->pid);
+}
+
-+static u32 ptrace_report_syscall(enum utrace_resume_action action,
-+ struct utrace_attached_engine *engine,
-+ struct task_struct *task,
-+ struct pt_regs *regs)
++
++static u32 ptrace_report_syscall(u32 action, struct task_struct *task)
+{
+ int code = SIGTRAP;
+ if (task->ptrace & PT_TRACESYSGOOD)
+ code |= 0x80;
-+ return utrace_ptrace_report(0, task, code);
++ return utrace_ptrace_report(action, task, code);
++}
++
++static u32 ptrace_report_syscall_entry(u32 action,
++ struct utrace_attached_engine *engine,
++ struct task_struct *task,
++ struct pt_regs *regs)
++{
++ /*
++ * If we're doing PTRACE_SYSEMU, just punt here and report
++ * at the exit stop instead.
++ */
++ if (ptrace_syscall_action(task))
++ return UTRACE_SYSCALL_ABORT | UTRACE_RESUME;
++
++ return ptrace_report_syscall(UTRACE_SYSCALL_RUN, task);
+}
+
-+#ifndef TIF_SYSCALL_EMU
-+# define ptrace_report_syscall_exit ptrace_report_syscall
-+#else
+static u32 ptrace_report_syscall_exit(enum utrace_resume_action action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *task,
+ struct pt_regs *regs)
+{
-+ if (test_tsk_thread_flag(task, TIF_SYSCALL_EMU))
-+ return ptrace_resume_action(task);
-+ return ptrace_report_syscall(action, engine, task, regs);
-+}
-+#endif
++ if (!(engine->flags & UTRACE_EVENT(SYSCALL_ENTRY))) {
++ /*
++ * We were not really using PTRACE_SYSCALL.
++ * SYSCALL_EXIT was only caught for vfork-done tracing.
++ */
++ utrace_set_events(task, engine,
++ engine->flags & ~UTRACE_EVENT(SYSCALL_EXIT));
++ WARN_ON(!(task->ptrace & PT_VFORKING));
++ task->ptrace &= ~PT_VFORKING;
++ return utrace_ptrace_event(task, PTRACE_EVENT_VFORK_DONE, 0);
++ }
++
++ if (task->ptrace & PT_VFORKING) {
++ /*
++ * If we're reporting vfork-done, we'll have to
++ * remember to report syscall-exit after that.
++ */
++ if (task->ptrace & PT_TRACE_VFORK_DONE)
++ return utrace_ptrace_event(task,
++ PTRACE_EVENT_VFORK_DONE, 0);
++ task->ptrace &= ~PT_VFORKING;
++ }
++
++ if (unlikely(ptrace_syscall_action(task)) &&
++ unlikely(ptrace_resume_action(task) == UTRACE_SINGLESTEP))
++ /*
++ * This is PTRACE_SYSEMU_SINGLESTEP.
++ * Kludge: Prevent arch code from sending a SIGTRAP
++ * after tracehook_report_syscall_exit() returns.
++ */
++ user_disable_single_step(task);
+
++ return ptrace_report_syscall(0, task);
++}
+
+static u32 ptrace_resumed(struct task_struct *task, struct pt_regs *regs,
+ siginfo_t *info, struct k_sigaction *return_ka)
@@ -1816,6 +1900,23 @@
+ const struct k_sigaction *orig_ka,
+ struct k_sigaction *return_ka)
+{
++ /*
++ * Deal with a pending vfork-done event. We'll stop again now
++ * for the syscall-exit report that was replaced with vfork-done.
++ */
++ if (unlikely(task->ptrace & PT_VFORKING)) {
++ task->ptrace &= ~PT_VFORKING;
++ if ((engine->flags & UTRACE_EVENT(SYSCALL_ENTRY)) &&
++ utrace_signal_action(action) == UTRACE_SIGNAL_REPORT) {
++ /*
++ * Make sure we get another report on wakeup.
++ */
++ utrace_control(task, engine, UTRACE_INTERRUPT);
++ return ptrace_report_syscall(UTRACE_SIGNAL_REPORT,
++ task);
++ }
++ }
++
+ switch (utrace_signal_action(action)) {
+ default:
+ break;
@@ -1847,6 +1948,12 @@
+ struct task_struct *task,
+ unsigned long event)
+{
++ /*
++ * Make sure we deal with a pending vfork-done event (see above).
++ */
++ if (unlikely(task->ptrace & PT_VFORKING))
++ return UTRACE_INTERRUPT;
++
+ task->last_siginfo = NULL;
+ return ptrace_resume_action(task);
+}
@@ -1859,7 +1966,7 @@
+ .report_exec = ptrace_report_exec,
+ .report_exit = ptrace_report_exit,
+ .report_clone = ptrace_report_clone,
-+ .report_syscall_entry = ptrace_report_syscall,
++ .report_syscall_entry = ptrace_report_syscall_entry,
+ .report_syscall_exit = ptrace_report_syscall_exit,
+};
+
@@ -1917,7 +2024,7 @@
int __ptrace_may_attach(struct task_struct *task)
{
/* May we inspect the given task?
-@@ -156,6 +541,7 @@ int ptrace_attach(struct task_struct *ta
+@@ -156,6 +614,7 @@ int ptrace_attach(struct task_struct *ta
{
int retval;
unsigned long flags;
@@ -1925,7 +2032,7 @@
audit_ptrace(task);
-@@ -163,6 +549,13 @@ int ptrace_attach(struct task_struct *ta
+@@ -163,6 +622,13 @@ int ptrace_attach(struct task_struct *ta
if (same_thread_group(task, current))
goto out;
@@ -1939,7 +2046,7 @@
repeat:
/*
* Nasty, nasty.
-@@ -202,6 +595,8 @@ repeat:
+@@ -202,6 +668,8 @@ repeat:
bad:
write_unlock_irqrestore(&tasklist_lock, flags);
task_unlock(task);
@@ -1948,7 +2055,7 @@
out:
return retval;
}
-@@ -309,6 +704,8 @@ static int ptrace_setoptions(struct task
+@@ -309,6 +777,8 @@ static int ptrace_setoptions(struct task
if (data & PTRACE_O_TRACEEXIT)
child->ptrace |= PT_TRACE_EXIT;
@@ -1957,7 +2064,7 @@
return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
}
-@@ -367,6 +764,7 @@ static int ptrace_setsiginfo(struct task
+@@ -367,6 +837,7 @@ static int ptrace_setsiginfo(struct task
#define is_sysemu_singlestep(request) 0
#endif
@@ -1965,7 +2072,7 @@
static int ptrace_resume(struct task_struct *child, long request, long data)
{
if (!valid_signal(data))
-@@ -401,6 +799,69 @@ static int ptrace_resume(struct task_str
+@@ -401,6 +872,66 @@ static int ptrace_resume(struct task_str
return 0;
}
@@ -1974,7 +2081,7 @@
+{
+ struct utrace_attached_engine *engine;
+ enum utrace_resume_action action;
-+ int sysemu = 0;
++ enum utrace_syscall_action syscall;
+
+ if (!valid_signal(data))
+ return -EIO;
@@ -1984,16 +2091,13 @@
+ if (IS_ERR(engine))
+ return -ESRCH;
+
-+#ifdef TIF_SYSCALL_EMU
-+ sysemu = (request == PTRACE_SYSEMU ||
-+ request == PTRACE_SYSEMU_SINGLESTEP);
-+ if (sysemu)
-+ set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
-+ else
-+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
++ syscall = UTRACE_SYSCALL_RUN;
++#ifdef PTRACE_SYSEMU
++ if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)
++ syscall = UTRACE_SYSCALL_ABORT;
+#endif
+
-+ if (sysemu || request == PTRACE_SYSCALL) {
++ if (syscall != UTRACE_SYSCALL_RUN || request == PTRACE_SYSCALL) {
+ if (!(engine->flags & UTRACE_EVENT_SYSCALL))
+ utrace_set_events(child, engine,
+ engine->flags | UTRACE_EVENT_SYSCALL);
@@ -2015,7 +2119,7 @@
+
+ child->exit_code = data;
+
-+ ptrace_set_action(child, action);
++ ptrace_set_action(child, action, syscall);
+
+ if (task_is_stopped(child)) {
+ spin_lock_irq(&child->sighand->siglock);
@@ -2035,7 +2139,7 @@
int ptrace_request(struct task_struct *child, long request,
long addr, long data)
-@@ -480,6 +941,11 @@ int ptrace_request(struct task_struct *c
+@@ -480,6 +1011,11 @@ int ptrace_request(struct task_struct *c
int ptrace_traceme(void)
{
int ret = -EPERM;
@@ -2047,7 +2151,7 @@
/*
* Are we already being traced?
-@@ -513,6 +979,8 @@ repeat:
+@@ -513,6 +1049,8 @@ repeat:
write_unlock_irqrestore(&tasklist_lock, flags);
}
task_unlock(current);
@@ -2111,10 +2215,10 @@
struct pt_regs *regs, void *cookie)
diff --git a/kernel/utrace.c b/kernel/utrace.c
new file mode 100644
-index ...f0fed73 100644
+index ...84540a4 100644
--- /dev/null
+++ b/kernel/utrace.c
-@@ -0,0 +1,2210 @@
+@@ -0,0 +1,2222 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -3288,13 +3392,14 @@
+ */
+struct utrace_report {
+ enum utrace_resume_action action;
++ u32 result;
+ bool detaches;
+ bool takers;
+ bool killed;
+};
+
+#define INIT_REPORT(var) \
-+ struct utrace_report var = { UTRACE_RESUME, false, false, false }
++ struct utrace_report var = { UTRACE_RESUME, 0, false, false, false }
+
+/*
+ * We are now making the report, so clear the flag saying we need one.
@@ -3349,8 +3454,10 @@
+static bool finish_callback(struct utrace *utrace,
+ struct utrace_report *report,
+ struct utrace_attached_engine *engine,
-+ enum utrace_resume_action ret)
++ u32 ret)
+{
++ enum utrace_resume_action action = utrace_resume_action(ret);
++
+ /*
+ * This is a good place to make sure tracing engines don't
+ * introduce too much latency under voluntary preemption.
@@ -3358,16 +3465,18 @@
+ if (need_resched())
+ cond_resched();
+
-+ if (ret == UTRACE_DETACH) {
++ if (action == UTRACE_DETACH) {
+ rcu_assign_pointer(engine->ops, &utrace_detached_ops);
+ report->detaches = true;
+ return true;
+ }
+
-+ if (ret < report->action)
-+ report->action = ret;
++ report->result = ret & ~UTRACE_RESUME_MASK;
+
-+ if (ret == UTRACE_STOP) {
++ if (action < report->action)
++ report->action = action;
++
++ if (action == UTRACE_STOP) {
+ if (!engine_wants_stop(engine)) {
+ spin_lock(&utrace->lock);
+ mark_engine_wants_stop(engine);
@@ -3436,8 +3545,8 @@
+ do { \
+ start_report(utrace); \
+ REPORT_CALLBACKS(task, utrace, report, event, callback, \
-+ (report)->action, engine, current, \
-+ ## __VA_ARGS__); \
++ (report)->action, engine, current, \
++ ## __VA_ARGS__); \
+ finish_report(report, task, utrace); \
+ } while (0)
+#define REPORT_CALLBACKS(task, utrace, report, event, callback, ...) \
@@ -3471,26 +3580,31 @@
+
+/*
+ * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set.
++ * Return true to prevent the system call.
+ */
-+void utrace_report_syscall_entry(struct pt_regs *regs)
++bool utrace_report_syscall_entry(struct pt_regs *regs)
+{
+ struct task_struct *task = current;
+ struct utrace *utrace = task->utrace;
+ INIT_REPORT(report);
+
-+ REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_ENTRY),
-+ report_syscall_entry, regs);
-+
-+ if (report.action != UTRACE_STOP)
-+ return;
++ start_report(utrace);
++ REPORT_CALLBACKS(task, utrace, &report, UTRACE_EVENT(SYSCALL_ENTRY),
++ report_syscall_entry, report.result | report.action,
++ engine, current, regs);
++ finish_report(&report, task, utrace);
+
-+ if (unlikely(utrace_stop(task, utrace)))
++ if (report.action == UTRACE_STOP && unlikely(utrace_stop(task, utrace)))
+ /*
+ * We are continuing despite UTRACE_STOP because of a
+ * SIGKILL. Don't let the system call actually proceed.
+ */
-+ syscall_abort(task, regs);
-+ else if (signal_pending(task)) {
++ return true;
++
++ if (unlikely(report.result == UTRACE_SYSCALL_ABORT))
++ return true;
++
++ if (signal_pending(task)) {
+ /*
+ * Clear TIF_SIGPENDING if it no longer needs to be set.
+ * It may have been set as part of quiescence, and won't
@@ -3504,6 +3618,8 @@
+ recalc_sigpending();
+ spin_unlock_irq(&task->sighand->siglock);
+ }
++
++ return false;
+}
+
+/*
More information about the fedora-extras-commits
mailing list