rpms/kernel/devel kernel.spec, 1.753, 1.754 linux-2.6-ptrace-cleanup.patch, 1.1, 1.2 linux-2.6-tracehook.patch, 1.1, 1.2 linux-2.6-utrace.patch, 1.79, 1.80
Roland McGrath (roland)
fedora-extras-commits at redhat.com
Sat Jul 12 00:15:21 UTC 2008
Author: roland
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv20911
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.753
retrieving revision 1.754
diff -u -r1.753 -r1.754
--- kernel.spec 11 Jul 2008 19:41:33 -0000 1.753
+++ kernel.spec 12 Jul 2008 00:14:30 -0000 1.754
@@ -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
+* Fri Jul 11 2008 Roland McGrath <roland at redhat.com>
+- utrace update
+
* Fri Jul 11 2008 Dave Jones <davej at redhat.com>
- 2.6.26-rc9-git9
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.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-ptrace-cleanup.patch 9 Jul 2008 03:37:06 -0000 1.1
+++ linux-2.6-ptrace-cleanup.patch 12 Jul 2008 00:14:30 -0000 1.2
@@ -3,20 +3,26 @@
arch/powerpc/kernel/signal.c | 12 +-
arch/powerpc/kernel/signal_32.c | 2 +-
arch/ppc/kernel/entry.S | 4 +-
- arch/x86/kernel/entry_32.S | 11 +-
- arch/x86/kernel/ptrace.c | 134 ++++--------
- arch/x86/kernel/step.c | 22 ++-
+ arch/x86/ia32/ia32entry.S | 14 +-
+ arch/x86/kernel/entry_32.S | 23 +--
+ arch/x86/kernel/entry_64.S | 20 +-
+ arch/x86/kernel/ptrace.c | 151 +++++--------
+ arch/x86/kernel/signal_32.c | 6 -
+ arch/x86/kernel/signal_64.c | 6 -
+ arch/x86/kernel/step.c | 35 +++-
include/asm-powerpc/processor.h | 2 +
include/asm-powerpc/ptrace.h | 4 +
include/asm-powerpc/thread_info.h | 17 +-
+ include/asm-x86/calling.h | 6 +-
include/asm-x86/ptrace-abi.h | 6 +-
- include/asm-x86/thread_info_64.h | 2 +
+ include/asm-x86/thread_info_32.h | 12 +-
+ include/asm-x86/thread_info_64.h | 17 ++-
include/linux/init_task.h | 4 +-
include/linux/sched.h | 26 +--
kernel/exit.c | 450 +++++++++++++++++++++++--------------
kernel/fork.c | 6 +-
kernel/ptrace.c | 37 ++-
- 18 files changed, 428 insertions(+), 334 deletions(-)
+ 24 files changed, 510 insertions(+), 373 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0c8614d..3a05e9f 100644
@@ -157,11 +163,97 @@
beq restore_user
do_user_signal: /* r10 contains MSR_KERNEL here */
ori r10,r10,MSR_EE
+diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
+index b5e329d..0b2ab50 100644
+--- a/arch/x86/ia32/ia32entry.S
++++ b/arch/x86/ia32/ia32entry.S
+@@ -37,6 +37,11 @@
+ movq %rax,R8(%rsp)
+ .endm
+
++ /*
++ * Reload arg registers from stack in case ptrace changed them.
++ * We don't reload %eax because syscall_trace_enter() returned
++ * the value it wants us to use in the table lookup.
++ */
+ .macro LOAD_ARGS32 offset
+ movl \offset(%rsp),%r11d
+ movl \offset+8(%rsp),%r10d
+@@ -46,7 +51,6 @@
+ movl \offset+48(%rsp),%edx
+ movl \offset+56(%rsp),%esi
+ movl \offset+64(%rsp),%edi
+- movl \offset+72(%rsp),%eax
+ .endm
+
+ .macro CFI_STARTPROC32 simple
+@@ -124,12 +128,12 @@ ENTRY(ia32_sysenter_target)
+ .previous
+ GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
+- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++ testl $_TIF_WORK_SYSCALL_ENTRY,threadinfo_flags(%r10)
+ CFI_REMEMBER_STATE
+ jnz sysenter_tracesys
+-sysenter_do_call:
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
++sysenter_do_call:
+ IA32_ARG_FIXUP 1
+ call *ia32_sys_call_table(,%rax,8)
+ movq %rax,RAX-ARGOFFSET(%rsp)
+@@ -231,7 +235,7 @@ ENTRY(ia32_cstar_target)
+ .previous
+ GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
+- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++ testl $_TIF_WORK_SYSCALL_ENTRY,threadinfo_flags(%r10)
+ CFI_REMEMBER_STATE
+ jnz cstar_tracesys
+ cstar_do_call:
+@@ -325,7 +329,7 @@ ENTRY(ia32_syscall)
+ SAVE_ARGS 0,0,1
+ GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
+- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++ testl $_TIF_WORK_SYSCALL_ENTRY,threadinfo_flags(%r10)
+ jnz ia32_tracesys
+ ia32_do_syscall:
+ cmpl $(IA32_NR_syscalls-1),%eax
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
-index c778e4f..58a5a11 100644
+index c778e4f..f5d312c 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
-@@ -513,11 +513,7 @@ END(work_pending)
+@@ -331,7 +331,7 @@ sysenter_past_esp:
+ GET_THREAD_INFO(%ebp)
+
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+- testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++ testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ jnz syscall_trace_entry
+ cmpl $(nr_syscalls), %eax
+ jae syscall_badsys
+@@ -369,7 +369,7 @@ ENTRY(system_call)
+ GET_THREAD_INFO(%ebp)
+ # system call tracing in operation / emulation
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+- testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++ testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ jnz syscall_trace_entry
+ cmpl $(nr_syscalls), %eax
+ jae syscall_badsys
+@@ -382,10 +382,6 @@ syscall_exit:
+ # setting need_resched or sigpending
+ # between sampling and the iret
+ TRACE_IRQS_OFF
+- testl $X86_EFLAGS_TF,PT_EFLAGS(%esp) # If tracing set singlestep flag on exit
+- jz no_singlestep
+- orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+-no_singlestep:
+ movl TI_flags(%ebp), %ecx
+ testw $_TIF_ALLWORK_MASK, %cx # current->work
+ jne syscall_exit_work
+@@ -513,12 +509,8 @@ END(work_pending)
syscall_trace_entry:
movl $-ENOSYS,PT_EAX(%esp)
movl %esp, %eax
@@ -170,12 +262,18 @@
- cmpl $0, %eax
- jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU,
- # so must skip actual syscall
+- movl PT_ORIG_EAX(%esp), %eax
+ call syscall_trace_enter
- movl PT_ORIG_EAX(%esp), %eax
++ /* What it returned is what we'll actually use. */
cmpl $(nr_syscalls), %eax
jnae syscall_call
-@@ -530,11 +526,10 @@ syscall_exit_work:
- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
+ jmp syscall_exit
+@@ -527,14 +519,13 @@ END(syscall_trace_entry)
+ # perform syscall exit tracing
+ ALIGN
+ syscall_exit_work:
+- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
++ testb $_TIF_WORK_SYSCALL_EXIT, %cl
jz work_pending
TRACE_IRQS_ON
- ENABLE_INTERRUPTS(CLBR_ANY) # could let do_syscall_trace() call
@@ -188,8 +286,82 @@
jmp resume_userspace
END(syscall_exit_work)
CFI_ENDPROC
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index 556a8df..21c72a9 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -244,7 +244,7 @@ ENTRY(system_call_after_swapgs)
+ movq %rcx,RIP-ARGOFFSET(%rsp)
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
+ GET_THREAD_INFO(%rcx)
+- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
++ testl $_TIF_WORK_SYSCALL_ENTRY,threadinfo_flags(%rcx)
+ jnz tracesys
+ cmpq $__NR_syscall_max,%rax
+ ja badsys
+@@ -305,7 +305,7 @@ sysret_signal:
+ leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
+ xorl %esi,%esi # oldset -> arg2
+ call ptregscall_common
+-1: movl $_TIF_NEED_RESCHED,%edi
++1: movl $_TIF_WORK_MASK,%edi
+ /* Use IRET because user could have changed frame. This
+ works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ DISABLE_INTERRUPTS(CLBR_NONE)
+@@ -323,7 +323,12 @@ tracesys:
+ FIXUP_TOP_OF_STACK %rdi
+ movq %rsp,%rdi
+ call syscall_trace_enter
+- LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
++ /*
++ * Reload arg registers from stack in case ptrace changed them.
++ * We don't reload %rax because syscall_trace_enter() returned
++ * the value it wants us to use in the table lookup.
++ */
++ LOAD_ARGS ARGOFFSET, 1
+ RESTORE_REST
+ cmpq $__NR_syscall_max,%rax
+ ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */
+@@ -376,7 +381,7 @@ int_very_careful:
+ ENABLE_INTERRUPTS(CLBR_NONE)
+ SAVE_REST
+ /* Check for syscall exit trace */
+- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
++ testl $_TIF_WORK_SYSCALL_EXIT,%edx
+ jz int_signal
+ pushq %rdi
+ CFI_ADJUST_CFA_OFFSET 8
+@@ -384,7 +389,7 @@ int_very_careful:
+ call syscall_trace_leave
+ popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
+- andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
++ andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
+ jmp int_restore_rest
+
+ int_signal:
+@@ -393,7 +398,7 @@ int_signal:
+ movq %rsp,%rdi # &ptregs -> arg1
+ xorl %esi,%esi # oldset -> arg2
+ call do_notify_resume
+-1: movl $_TIF_NEED_RESCHED,%edi
++1: movl $_TIF_WORK_MASK,%edi
+ int_restore_rest:
+ RESTORE_REST
+ DISABLE_INTERRUPTS(CLBR_NONE)
+@@ -647,9 +652,8 @@ retint_signal:
+ RESTORE_REST
+ DISABLE_INTERRUPTS(CLBR_NONE)
+ TRACE_IRQS_OFF
+- movl $_TIF_NEED_RESCHED,%edi
+ GET_THREAD_INFO(%rcx)
+- jmp retint_check
++ jmp retint_with_reschedule
+
+ #ifdef CONFIG_PREEMPT
+ /* Returning to kernel space. Check if we need preemption */
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
-index a7835f2..44ee172 100644
+index a7835f2..652f550 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1357,8 +1357,6 @@ const struct user_regset_view *task_user
@@ -293,7 +465,7 @@
#if 0
printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
-@@ -1481,39 +1400,64 @@ static void syscall_trace(struct pt_regs
+@@ -1481,39 +1400,81 @@ static void syscall_trace(struct pt_regs
}
}
@@ -306,15 +478,33 @@
+# define IS_IA32 0
+#endif
+
-+asmregparm void syscall_trace_enter(struct pt_regs *regs)
++/*
++ * We must return the syscall number to actually look up in the table.
++ * This can be -1L to skip running any syscall at all.
++ */
++asmregparm long syscall_trace_enter(struct pt_regs *regs)
{
++ long ret = 0;
++
++ /*
++ * If we stepped into a sysenter/syscall insn, it trapped in
++ * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
++ * If user-mode had set TF itself, then it's still clear from
++ * do_debug() and we need to set it again to restore the user
++ * state. If we entered on the slow path, TF was already set.
++ */
++ if (test_thread_flag(TIF_SINGLESTEP))
++ regs->flags |= X86_EFLAGS_TF;
++
/* do the secure computing check first */
secure_computing(regs->orig_ax);
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- && (current->ptrace & PT_PTRACED))
-+ if (test_thread_flag(TIF_SYSCALL_TRACE) ||
-+ unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
++ if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
++ ret = -1L;
++
++ if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
syscall_trace(regs);
if (unlikely(current->audit_context)) {
@@ -335,16 +525,7 @@
+#endif
}
+
-+ if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
-+ /*
-+ * Setting an invalid syscall number skips making the call
-+ * and leaves the registers as they are now (-ENOSYS in
-+ * regs->ax, or as just modified by ptrace). This also
-+ * ensures that signal handling won't restart the call.
-+ * TIF_SYSCALL_AUDIT will still cause us to get into
-+ * syscall_trace_leave() after not making the call.
-+ */
-+ regs->orig_ax = -1L;
++ return ret ?: regs->orig_ax;
}
-asmlinkage void syscall_trace_leave(struct pt_regs *regs)
@@ -362,27 +543,82 @@
-#endif /* CONFIG_X86_32 */
+ /*
++ * If TIF_SYSCALL_EMU is set, we only get here because of
++ * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
++ * We already reported this syscall instruction in
++ * syscall_trace_enter(), so don't do any more now.
++ */
++ if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
++ return;
++
++ /*
+ * If we are single-stepping, synthesize a trap to follow the
+ * system call instruction.
+ */
+ if (test_thread_flag(TIF_SINGLESTEP) &&
-+ !test_thread_flag(TIF_SYSCALL_EMU) &&
+ (current->ptrace & PT_PTRACED))
+ send_sigtrap(current, regs, 0);
+}
+diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
+index d923736..295b5f5 100644
+--- a/arch/x86/kernel/signal_32.c
++++ b/arch/x86/kernel/signal_32.c
+@@ -657,12 +657,6 @@ static void do_signal(struct pt_regs *re
+ void
+ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
+ {
+- /* Pending single-step? */
+- if (thread_info_flags & _TIF_SINGLESTEP) {
+- regs->flags |= X86_EFLAGS_TF;
+- clear_thread_flag(TIF_SINGLESTEP);
+- }
+-
+ /* deal with pending signal delivery */
+ if (thread_info_flags & _TIF_SIGPENDING)
+ do_signal(regs);
+diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
+index e53b267..bf87684 100644
+--- a/arch/x86/kernel/signal_64.c
++++ b/arch/x86/kernel/signal_64.c
+@@ -487,12 +487,6 @@ static void do_signal(struct pt_regs *re
+ void do_notify_resume(struct pt_regs *regs, void *unused,
+ __u32 thread_info_flags)
+ {
+- /* Pending single-step? */
+- if (thread_info_flags & _TIF_SINGLESTEP) {
+- regs->flags |= X86_EFLAGS_TF;
+- clear_thread_flag(TIF_SINGLESTEP);
+- }
+-
+ #ifdef CONFIG_X86_MCE
+ /* notify userspace of pending MCEs */
+ if (thread_info_flags & _TIF_MCE_NOTIFY)
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
-index 92c20fe..0d2cb36 100644
+index 92c20fe..e8b9863 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
-@@ -105,6 +105,7 @@ static int is_setting_trap_flag(struct t
+@@ -105,6 +105,20 @@ static int is_setting_trap_flag(struct t
static int enable_single_step(struct task_struct *child)
{
struct pt_regs *regs = task_pt_regs(child);
+ unsigned long oflags;
++
++ /*
++ * If we stepped into a sysenter/syscall insn, it trapped in
++ * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
++ * If user-mode had set TF itself, then it's still clear from
++ * do_debug() and we need to set it again to restore the user
++ * state so we don't wrongly set TIF_FORCED_TF below.
++ * If enable_single_step() was used last and that is what
++ * set TIF_SINGLESTEP, then both TF and TIF_FORCED_TF are
++ * already set and our bookkeeping is fine.
++ */
++ if (unlikely(test_tsk_thread_flag(child, TIF_SINGLESTEP)))
++ regs->flags |= X86_EFLAGS_TF;
/*
* Always set TIF_SINGLESTEP - this guarantees that
-@@ -113,11 +114,7 @@ static int enable_single_step(struct tas
+@@ -113,11 +127,7 @@ static int enable_single_step(struct tas
*/
set_tsk_thread_flag(child, TIF_SINGLESTEP);
@@ -395,7 +631,7 @@
/* Set TF on the kernel stack.. */
regs->flags |= X86_EFLAGS_TF;
-@@ -126,9 +123,22 @@ static int enable_single_step(struct tas
+@@ -126,9 +136,22 @@ static int enable_single_step(struct tas
* ..but if TF is changed by the instruction we will trace,
* don't mark it as being "us" that set it, so that we
* won't clear it by hand later.
@@ -500,6 +736,30 @@
#endif /* __KERNEL__ */
+diff --git a/include/asm-x86/calling.h b/include/asm-x86/calling.h
+index f13e62e..2bc162e 100644
+--- a/include/asm-x86/calling.h
++++ b/include/asm-x86/calling.h
+@@ -104,7 +104,7 @@
+ .endif
+ .endm
+
+- .macro LOAD_ARGS offset
++ .macro LOAD_ARGS offset, skiprax=0
+ movq \offset(%rsp), %r11
+ movq \offset+8(%rsp), %r10
+ movq \offset+16(%rsp), %r9
+@@ -113,7 +113,10 @@
+ movq \offset+48(%rsp), %rdx
+ movq \offset+56(%rsp), %rsi
+ movq \offset+64(%rsp), %rdi
++ .if \skiprax
++ .else
+ movq \offset+72(%rsp), %rax
++ .endif
+ .endm
+
+ #define REST_SKIP 6*8
diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h
index f224eb3..72e7b9d 100644
--- a/include/asm-x86/ptrace-abi.h
@@ -519,8 +779,33 @@
#define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */
#ifndef __ASSEMBLY__
+diff --git a/include/asm-x86/thread_info_32.h b/include/asm-x86/thread_info_32.h
+index b633882..3267d9c 100644
+--- a/include/asm-x86/thread_info_32.h
++++ b/include/asm-x86/thread_info_32.h
+@@ -160,10 +160,19 @@ static inline struct thread_info *curren
+ #define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
+ #define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
+
++/* work to do in syscall_trace_enter() */
++#define _TIF_WORK_SYSCALL_ENTRY \
++ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | \
++ _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | _TIF_SINGLESTEP)
++
++/* work to do in syscall_trace_leave() */
++#define _TIF_WORK_SYSCALL_EXIT \
++ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)
++
+ /* work to do on interrupt/exception return */
+ #define _TIF_WORK_MASK \
+ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+- _TIF_SECCOMP | _TIF_SYSCALL_EMU))
++ _TIF_SINGLESTEP | _TIF_SECCOMP | _TIF_SYSCALL_EMU))
+ /* work to do on any return to u-space */
+ #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
+
diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
-index cb69f70..79cf6ab 100644
+index cb69f70..a531e79 100644
--- a/include/asm-x86/thread_info_64.h
+++ b/include/asm-x86/thread_info_64.h
@@ -107,6 +107,7 @@ static inline struct thread_info *stack_
@@ -539,6 +824,34 @@
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
+@@ -146,15 +148,24 @@ static inline struct thread_info *stack_
+ #define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
+ #define _TIF_NOTSC (1 << TIF_NOTSC)
+
++/* work to do in syscall_trace_enter() */
++#define _TIF_WORK_SYSCALL_ENTRY \
++ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | \
++ _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | _TIF_SINGLESTEP)
++
++/* work to do in syscall_trace_leave() */
++#define _TIF_WORK_SYSCALL_EXIT \
++ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)
++
+ /* work to do on interrupt/exception return */
+ #define _TIF_WORK_MASK \
+- (0x0000FFFF & \
+- ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
++ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
++ _TIF_SINGLESTEP | _TIF_SECCOMP | _TIF_SYSCALL_EMU))
+ /* work to do on any return to user space */
+ #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
+
+ #define _TIF_DO_NOTIFY_MASK \
+- (_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
++ (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
+
+ /* flags to check in __switch_to() */
+ #define _TIF_WORK_CTXSW \
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 9927a88..93c45ac 100644
--- a/include/linux/init_task.h
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.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-tracehook.patch 9 Jul 2008 03:37:06 -0000 1.1
+++ linux-2.6-tracehook.patch 12 Jul 2008 00:14:30 -0000 1.2
@@ -39,7 +39,7 @@
include/asm-x86/ptrace.h | 5 +
include/asm-x86/syscall.h | 213 ++++++++++++++
include/asm-x86/thread_info_32.h | 2 +
- include/asm-x86/thread_info_64.h | 5 +-
+ include/asm-x86/thread_info_64.h | 4 +-
include/linux/ptrace.h | 72 +++++
include/linux/sched.h | 10 +-
include/linux/tracehook.h | 566 +++++++++++++++++++++++++++++++++++++
@@ -53,7 +53,7 @@
lib/syscall.c | 75 +++++
mm/nommu.c | 4 +-
security/selinux/hooks.c | 22 +--
- 55 files changed, 1556 insertions(+), 368 deletions(-)
+ 55 files changed, 1555 insertions(+), 368 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 3ea332b..1955fbd 100644
@@ -631,7 +631,7 @@
}
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
-index 44ee172..96630a5 100644
+index 652f550..8a194ed 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -14,6 +14,7 @@
@@ -673,16 +673,16 @@
#ifdef CONFIG_X86_32
# define IS_IA32 1
-@@ -1415,7 +1392,7 @@ asmregparm void syscall_trace_enter(stru
+@@ -1433,7 +1410,7 @@ asmregparm long syscall_trace_enter(stru
+ ret = -1L;
- if (test_thread_flag(TIF_SYSCALL_TRACE) ||
- unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
+ if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
- syscall_trace(regs);
+ tracehook_report_syscall_entry(regs);
if (unlikely(current->audit_context)) {
if (IS_IA32)
-@@ -1450,7 +1427,7 @@ asmregparm void syscall_trace_leave(stru
+@@ -1459,7 +1436,7 @@ asmregparm void syscall_trace_leave(stru
audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
if (test_thread_flag(TIF_SYSCALL_TRACE))
@@ -690,17 +690,17 @@
+ tracehook_report_syscall_exit(regs, 0);
/*
- * If we are single-stepping, synthesize a trap to follow the
-@@ -1458,6 +1435,6 @@ asmregparm void syscall_trace_leave(stru
+ * If TIF_SYSCALL_EMU is set, we only get here because of
+@@ -1475,6 +1452,6 @@ asmregparm void syscall_trace_leave(stru
+ * system call instruction.
*/
if (test_thread_flag(TIF_SINGLESTEP) &&
- !test_thread_flag(TIF_SYSCALL_EMU) &&
- (current->ptrace & PT_PTRACED))
+ tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
send_sigtrap(current, regs, 0);
}
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
-index d923736..83631f9 100644
+index 295b5f5..c17c0cb 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -17,6 +17,7 @@
@@ -730,7 +730,7 @@
return 0;
}
-@@ -667,6 +669,11 @@ do_notify_resume(struct pt_regs *regs, v
+@@ -661,6 +663,11 @@ do_notify_resume(struct pt_regs *regs, v
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
@@ -743,7 +743,7 @@
hrtick_resched();
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
-index e53b267..249c547 100644
+index bf87684..f65ece6 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -15,6 +15,7 @@
@@ -841,7 +841,7 @@
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
-@@ -503,6 +477,11 @@ void do_notify_resume(struct pt_regs *re
+@@ -497,6 +471,11 @@ void do_notify_resume(struct pt_regs *re
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
@@ -933,7 +933,7 @@
/* error cleanup */
diff --git a/fs/exec.c b/fs/exec.c
-index da94a6f..5fe37f7 100644
+index fd92343..346db53 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -43,7 +43,6 @@
@@ -1732,7 +1732,7 @@
+
+#endif /* _ASM_SYSCALL_H */
diff --git a/include/asm-x86/thread_info_32.h b/include/asm-x86/thread_info_32.h
-index b633882..ecaac87 100644
+index 3267d9c..975e2b1 100644
--- a/include/asm-x86/thread_info_32.h
+++ b/include/asm-x86/thread_info_32.h
@@ -131,6 +131,7 @@ static inline struct thread_info *curren
@@ -1752,7 +1752,7 @@
#define _TIF_DEBUG (1 << TIF_DEBUG)
#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
-index 79cf6ab..0a95812 100644
+index a531e79..f1281a7 100644
--- a/include/asm-x86/thread_info_64.h
+++ b/include/asm-x86/thread_info_64.h
@@ -103,6 +103,7 @@ static inline struct thread_info *stack_
@@ -1771,13 +1771,12 @@
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
-@@ -156,7 +158,8 @@ static inline struct thread_info *stack_
+@@ -165,7 +167,7 @@ static inline struct thread_info *stack_
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
#define _TIF_DO_NOTIFY_MASK \
-- (_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
-+ (_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY| \
-+ _TIF_NOTIFY_RESUME|_TIF_HRTICK_RESCHED)
+- (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
++ (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED|_TIF_NOTIFY_RESUME)
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW \
@@ -2778,7 +2777,7 @@
/* All systems go.. */
return ret;
diff --git a/kernel/sched.c b/kernel/sched.c
-index 94ead43..aceaf2a 100644
+index 4e2f603..102d634 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1765,16 +1765,24 @@ migrate_task(struct task_struct *p, int
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.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- linux-2.6-utrace.patch 9 Jul 2008 03:37:06 -0000 1.79
+++ linux-2.6-utrace.patch 12 Jul 2008 00:14:30 -0000 1.80
@@ -4,14 +4,14 @@
fs/proc/array.c | 3 +
include/linux/ptrace.h | 15 +
include/linux/sched.h | 6 +
- include/linux/tracehook.h | 64 ++
- include/linux/utrace.h | 504 +++++++++
+ include/linux/tracehook.h | 59 +
+ include/linux/utrace.h | 501 +++++++++
init/Kconfig | 28 +
kernel/Makefile | 1 +
- kernel/ptrace.c | 438 ++++++++-
+ kernel/ptrace.c | 472 ++++++++-
kernel/signal.c | 14 +-
- kernel/utrace.c | 2156 +++++++++++++++++++++++++++++++++++++
- 13 files changed, 3827 insertions(+), 4 deletions(-)
+ kernel/utrace.c | 2210 +++++++++++++++++++++++++++++++++++++
+ 13 files changed, 3907 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..a753172 100644
+index 88ce8af..a68801f 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -49,6 +49,7 @@
@@ -840,25 +840,20 @@
}
/**
-@@ -370,8 +405,17 @@ static inline void tracehook_signal_hand
+@@ -370,8 +405,12 @@ static inline void tracehook_signal_hand
const struct k_sigaction *ka,
struct pt_regs *regs, int stepping)
{
-+#if 0 /* XXX */
-+ if (stepping &&
-+ (task_utrace_flags(current) & UTRACE_EVENT_SIGNAL_ALL) &&
-+ (task_utrace_flags(current) & (UTRACE_ACTION_SINGLESTEP |
-+ UTRACE_ACTION_BLOCKSTEP)))
-+ utrace_signal_handler_singlestep(current, regs);
-+#endif
-+#ifndef CONFIG_UTRACE_PTRACE /* XXX */
++ if (task_utrace_flags(current))
++ utrace_signal_handler(current, stepping);
++#ifndef CONFIG_UTRACE_PTRACE
if (stepping)
ptrace_notify(SIGTRAP);
+#endif
}
/**
-@@ -390,6 +434,8 @@ static inline int tracehook_consider_ign
+@@ -390,6 +429,8 @@ static inline int tracehook_consider_ign
int sig,
void __user *handler)
{
@@ -867,7 +862,7 @@
return (task_ptrace(task) & PT_PTRACED);
}
-@@ -411,6 +457,9 @@ static inline int tracehook_consider_fat
+@@ -411,6 +452,9 @@ static inline int tracehook_consider_fat
int sig,
void __user *handler)
{
@@ -877,7 +872,7 @@
return (task_ptrace(task) & PT_PTRACED);
}
-@@ -425,6 +474,8 @@ static inline int tracehook_consider_fat
+@@ -425,6 +469,8 @@ static inline int tracehook_consider_fat
*/
static inline int tracehook_force_sigpending(void)
{
@@ -886,7 +881,7 @@
return 0;
}
-@@ -454,6 +505,8 @@ static inline int tracehook_get_signal(s
+@@ -454,6 +500,8 @@ static inline int tracehook_get_signal(s
siginfo_t *info,
struct k_sigaction *return_ka)
{
@@ -895,7 +890,7 @@
return 0;
}
-@@ -474,6 +527,8 @@ static inline int tracehook_get_signal(s
+@@ -474,6 +522,8 @@ static inline int tracehook_get_signal(s
*/
static inline int tracehook_notify_jctl(int notify, int why)
{
@@ -904,7 +899,7 @@
return notify || (current->ptrace & PT_PTRACED);
}
-@@ -491,6 +546,8 @@ static inline int tracehook_notify_jctl(
+@@ -491,6 +541,8 @@ static inline int tracehook_notify_jctl(
static inline int tracehook_notify_death(struct task_struct *task,
void **death_cookie, int group_dead)
{
@@ -913,7 +908,7 @@
if (task->exit_signal == -1)
return task->ptrace ? SIGCHLD : -1;
-@@ -527,6 +584,10 @@ static inline void tracehook_report_deat
+@@ -527,6 +579,10 @@ static inline void tracehook_report_deat
int signal, void *death_cookie,
int group_dead)
{
@@ -924,7 +919,7 @@
}
#ifdef TIF_NOTIFY_RESUME
-@@ -560,6 +621,9 @@ static inline void set_notify_resume(str
+@@ -560,6 +616,9 @@ static inline void set_notify_resume(str
*/
static inline void tracehook_notify_resume(struct pt_regs *regs)
{
@@ -936,10 +931,10 @@
diff --git a/include/linux/utrace.h b/include/linux/utrace.h
new file mode 100644
-index ...7867898 100644
+index ...4622ed0 100644
--- /dev/null
+++ b/include/linux/utrace.h
-@@ -0,0 +1,504 @@
+@@ -0,0 +1,501 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -1072,7 +1067,7 @@
+ __attribute__((weak));
+int utrace_unsafe_exec(struct task_struct *)
+ __attribute__((weak));
-+void utrace_signal_handler_singlestep(struct task_struct *, struct pt_regs *)
++void utrace_signal_handler(struct task_struct *, int)
+ __attribute__((weak));
+
+#ifndef CONFIG_UTRACE
@@ -1185,6 +1180,7 @@
+ * @UTRACE_SIGNAL_STOP: Deliver as absolute stop.
+ * @UTRACE_SIGNAL_TSTP: Deliver as job control stop.
+ * @UTRACE_SIGNAL_REPORT: Reporting before pending signals.
++ * @UTRACE_SIGNAL_HANDLER: Report after signal handler setup.
+ *
+ * This is encoded in the @action argument and the return value for
+ * a @report_signal callback. It says what will happen to the
@@ -1192,6 +1188,10 @@
+ *
+ * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when
+ * a tracing report is being made before dequeuing any pending signal.
++ * If this is immediately after a signal handler has been set up, then
++ * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback
++ * that uses %UTRACE_SIGNAL_DELIVER | %UTRACE_SINGLESTEP will ensure
++ * it sees a %UTRACE_SIGNAL_HANDLER report.
+ */
+enum utrace_signal_action {
+ UTRACE_SIGNAL_DELIVER = 0x00,
@@ -1200,7 +1200,8 @@
+ UTRACE_SIGNAL_CORE = 0x30,
+ UTRACE_SIGNAL_STOP = 0x40,
+ UTRACE_SIGNAL_TSTP = 0x50,
-+ UTRACE_SIGNAL_REPORT = 0x60
++ UTRACE_SIGNAL_REPORT = 0x60,
++ UTRACE_SIGNAL_HANDLER = 0x70
+};
+#define UTRACE_SIGNAL_MASK 0xf0
+
@@ -1222,15 +1223,6 @@
+#define UTRACE_HIDE_EVENT XXX
+
+/*
-+ * This value is passed to a report_signal() callback after a signal
-+ * handler is entered while %UTRACE_ACTION_SINGLESTEP is in force.
-+ * For this callback, no signal will never actually be delivered regardless
-+ * of the return value, and the other callback parameters are null.
-+ */
-+#define UTRACE_SIGNAL_HANDLER 0x0700
-+
-+
-+/*
+ * Flags for utrace_attach().
+ */
+#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */
@@ -1445,7 +1437,7 @@
+
+#endif /* linux/utrace.h */
diff --git a/init/Kconfig b/init/Kconfig
-index 6199d11..02e80ca 100644
+index 6199d11..66fa8fe 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -911,6 +911,34 @@ config STOP_MACHINE
@@ -1478,7 +1470,7 @@
+ It's recommended to enable this if you are experimenting with
+ new modules that use utrace. But, disabling it makes sure that
+ using traditional ptrace() on tasks not touched by utrace will
-+ not use any experimental new code that might be unreliable.
++ not use any experimental new code that might be unreliable.
+
source "block/Kconfig"
@@ -1496,7 +1488,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..89bea7c 100644
+index ef66127..9003b0e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -16,6 +16,7 @@
@@ -1557,7 +1549,7 @@
/*
* Check that we have indeed attached to the thing..
*/
-@@ -113,6 +137,336 @@ int ptrace_check_attach(struct task_stru
+@@ -113,6 +137,367 @@ int ptrace_check_attach(struct task_stru
return ret;
}
@@ -1761,6 +1753,21 @@
+ return utrace_ptrace_report(0, task, code);
+}
+
++#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
++
++
+static u32 ptrace_resumed(struct task_struct *task, struct pt_regs *regs,
+ siginfo_t *info, struct k_sigaction *return_ka)
+{
@@ -1809,11 +1816,27 @@
+ const struct k_sigaction *orig_ka,
+ struct k_sigaction *return_ka)
+{
-+ if (info->si_signo == 0 ||
-+ utrace_signal_action(action) == UTRACE_SIGNAL_REPORT)
++ switch (utrace_signal_action(action)) {
++ default:
++ break;
++ case UTRACE_SIGNAL_HANDLER:
++ /*
++ * A handler was set up. If we are stepping, pretend
++ * another SIGTRAP arrived.
++ */
++ if (ptrace_resume_action(task) == UTRACE_SINGLESTEP ||
++ ptrace_resume_action(task) == UTRACE_BLOCKSTEP) {
++ memset(info, 0, sizeof *info);
++ info->si_signo = SIGTRAP;
++ info->si_code = SIGTRAP;
++ info->si_pid = task_pid_vnr(task);
++ info->si_uid = task->uid;
++ break;
++ }
++ /* Fall through. */
++ case UTRACE_SIGNAL_REPORT:
+ return ptrace_resumed(task, regs, info, return_ka);
-+
-+ show_regs(regs);
++ }
+
+ task->last_siginfo = info;
+ return utrace_ptrace_report(UTRACE_SIGNAL_IGN, task, info->si_signo);
@@ -1837,7 +1860,7 @@
+ .report_exit = ptrace_report_exit,
+ .report_clone = ptrace_report_clone,
+ .report_syscall_entry = ptrace_report_syscall,
-+ .report_syscall_exit = ptrace_report_syscall,
++ .report_syscall_exit = ptrace_report_syscall_exit,
+};
+
+/*
@@ -1894,7 +1917,7 @@
int __ptrace_may_attach(struct task_struct *task)
{
/* May we inspect the given task?
-@@ -156,6 +510,7 @@ int ptrace_attach(struct task_struct *ta
+@@ -156,6 +541,7 @@ int ptrace_attach(struct task_struct *ta
{
int retval;
unsigned long flags;
@@ -1902,7 +1925,7 @@
audit_ptrace(task);
-@@ -163,6 +518,13 @@ int ptrace_attach(struct task_struct *ta
+@@ -163,6 +549,13 @@ int ptrace_attach(struct task_struct *ta
if (same_thread_group(task, current))
goto out;
@@ -1916,7 +1939,7 @@
repeat:
/*
* Nasty, nasty.
-@@ -202,6 +564,8 @@ repeat:
+@@ -202,6 +595,8 @@ repeat:
bad:
write_unlock_irqrestore(&tasklist_lock, flags);
task_unlock(task);
@@ -1925,7 +1948,7 @@
out:
return retval;
}
-@@ -309,6 +673,8 @@ static int ptrace_setoptions(struct task
+@@ -309,6 +704,8 @@ static int ptrace_setoptions(struct task
if (data & PTRACE_O_TRACEEXIT)
child->ptrace |= PT_TRACE_EXIT;
@@ -1934,7 +1957,7 @@
return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
}
-@@ -367,6 +733,7 @@ static int ptrace_setsiginfo(struct task
+@@ -367,6 +764,7 @@ static int ptrace_setsiginfo(struct task
#define is_sysemu_singlestep(request) 0
#endif
@@ -1942,7 +1965,7 @@
static int ptrace_resume(struct task_struct *child, long request, long data)
{
if (!valid_signal(data))
-@@ -401,6 +768,66 @@ static int ptrace_resume(struct task_str
+@@ -401,6 +799,69 @@ static int ptrace_resume(struct task_str
return 0;
}
@@ -1951,6 +1974,7 @@
+{
+ struct utrace_attached_engine *engine;
+ enum utrace_resume_action action;
++ int sysemu = 0;
+
+ if (!valid_signal(data))
+ return -EIO;
@@ -1960,7 +1984,16 @@
+ if (IS_ERR(engine))
+ return -ESRCH;
+
-+ if (request == PTRACE_SYSCALL) {
++#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);
++#endif
++
++ if (sysemu || request == PTRACE_SYSCALL) {
+ if (!(engine->flags & UTRACE_EVENT_SYSCALL))
+ utrace_set_events(child, engine,
+ engine->flags | UTRACE_EVENT_SYSCALL);
@@ -1969,13 +2002,6 @@
+ engine->flags & ~UTRACE_EVENT_SYSCALL);
+ }
+
-+#ifdef TIF_SYSCALL_EMU
-+ if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)
-+ set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
-+ else
-+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
-+#endif
-+
+ action = UTRACE_RESUME;
+ if (is_singleblock(request)) {
+ if (unlikely(!arch_has_block_step()))
@@ -2009,7 +2035,7 @@
int ptrace_request(struct task_struct *child, long request,
long addr, long data)
-@@ -480,6 +907,11 @@ int ptrace_request(struct task_struct *c
+@@ -480,6 +941,11 @@ int ptrace_request(struct task_struct *c
int ptrace_traceme(void)
{
int ret = -EPERM;
@@ -2021,7 +2047,7 @@
/*
* Are we already being traced?
-@@ -513,6 +945,8 @@ repeat:
+@@ -513,6 +979,8 @@ repeat:
write_unlock_irqrestore(&tasklist_lock, flags);
}
task_unlock(current);
@@ -2085,10 +2111,10 @@
struct pt_regs *regs, void *cookie)
diff --git a/kernel/utrace.c b/kernel/utrace.c
new file mode 100644
-index ...8234e66 100644
+index ...f0fed73 100644
--- /dev/null
+++ b/kernel/utrace.c
-@@ -0,0 +1,2156 @@
+@@ -0,0 +1,2210 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -2160,6 +2186,7 @@
+ unsigned int stopped:1;
+ unsigned int report:1;
+ unsigned int interrupt:1;
++ unsigned int signal_handler:1;
+};
+
+static struct kmem_cache *utrace_cachep;
@@ -2210,6 +2237,7 @@
+ utrace->stopped = 0;
+ utrace->report = 0;
+ utrace->interrupt = 0;
++ utrace->signal_handler = 0;
+ INIT_LIST_HEAD(&utrace->engines);
+ list_add(&engine->entry, &utrace->engines);
+ spin_lock_init(&utrace->lock);
@@ -3704,6 +3732,21 @@
+ struct utrace_attached_engine *engine, *next;
+
+ /*
++ * If this flag is still set it's because there was a signal
++ * handler setup done but no report_signal following it. Clear
++ * the flag before we get to user so it doesn't confuse us later.
++ */
++ if (unlikely(utrace->signal_handler)) {
++ int skip;
++ spin_lock(&utrace->lock);
++ utrace->signal_handler = 0;
++ skip = !utrace->report;
++ spin_unlock(&utrace->lock);
++ if (skip)
++ return;
++ }
++
++ /*
+ * If UTRACE_INTERRUPT was just used, we don't bother with a
+ * report here. We will report and stop in utrace_get_signal().
+ */
@@ -3778,7 +3821,7 @@
+ return 0;
+ }
+
-+ if (utrace->interrupt || utrace->report) {
++ if (utrace->interrupt || utrace->report || utrace->signal_handler) {
+ /*
+ * We've been asked for an explicit report before we
+ * even check for pending signals.
@@ -3802,21 +3845,33 @@
+ return -1;
+ }
+
++ if (unlikely(!utrace->interrupt) && unlikely(!utrace->report))
++ action = UTRACE_SIGNAL_IGN;
++ else if (utrace->signal_handler)
++ action = UTRACE_SIGNAL_HANDLER;
++ else
++ action = UTRACE_SIGNAL_REPORT;
++
+ /*
+ * We are now making the report and it's on the
+ * interrupt path, so clear the flags asking for those.
+ */
-+ utrace->interrupt = utrace->report = 0;
++ utrace->interrupt = utrace->report = utrace->signal_handler = 0;
+
+ spin_unlock(&utrace->lock);
+
++ if (unlikely(action == UTRACE_SIGNAL_IGN))
++ /*
++ * We only got here to clear utrace->signal_handler.
++ */
++ return -1;
++
+ /*
+ * Do a reporting pass for no signal, just for EVENT(QUIESCE).
+ * The engine callbacks can fill in *info and *return_ka.
+ * We'll pass NULL for the @orig_ka argument to indicate
+ * that there was no original signal.
+ */
-+ action = UTRACE_SIGNAL_REPORT;
+ event = 0;
+ ka = NULL;
+ memset(return_ka, 0, sizeof *return_ka);
@@ -3998,6 +4053,7 @@
+ spin_lock(&utrace->lock);
+ utrace->interrupt = 1;
+ spin_unlock(&utrace->lock);
++ set_tsk_thread_flag(task, TIF_SIGPENDING);
+ }
+
+ spin_lock_irq(&task->sighand->siglock);
@@ -4077,6 +4133,30 @@
+
+ return signr;
+}
++
++/*
++ * This gets called after a signal handler has been set up.
++ * We set a flag so the next report knows it happened.
++ * If we're already stepping, make sure we do a report_signal.
++ * If not, make sure we get into utrace_resume() where we can
++ * clear the signal_handler flag before resuming.
++ */
++void utrace_signal_handler(struct task_struct *task, int stepping)
++{
++ struct utrace *utrace = task->utrace;
++
++ spin_lock(&utrace->lock);
++
++ utrace->signal_handler = 1;
++ if (stepping) {
++ utrace->interrupt = 1;
++ set_tsk_thread_flag(task, TIF_SIGPENDING);
++ } else {
++ set_notify_resume(task);
++ }
++
++ spin_unlock(&utrace->lock);
++}
+
+/**
+ * utrace_prepare_examine - prepare to examine thread state
More information about the fedora-extras-commits
mailing list