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