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