rpms/kernel/devel kernel-2.6.spec, 1.2546, 1.2547 linux-2.6-utrace.patch, 1.16, 1.17

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Fri Aug 11 00:47:56 UTC 2006


Author: roland

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv19641

Modified Files:
	kernel-2.6.spec linux-2.6-utrace.patch 
Log Message:
New utrace patch: fix ptrace synchronization issues.


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.2546
retrieving revision 1.2547
diff -u -r1.2546 -r1.2547
--- kernel-2.6.spec	10 Aug 2006 23:52:23 -0000	1.2546
+++ kernel-2.6.spec	11 Aug 2006 00:47:52 -0000	1.2547
@@ -1697,6 +1697,9 @@
 %endif
 
 %changelog
+* Thu Aug 10 2006 Roland McGrath <roland at redhat.com>
+- New utrace patch: fix ptrace synchronization issues.
+
 * Thu Aug 10 2006 Dave Jones <davej at redhat.com>
 - GFS2/DLM update.
 - Daily GregKH updates

linux-2.6-utrace.patch:
 Documentation/utrace.txt                |  455 +++++++++
 arch/alpha/kernel/asm-offsets.c         |    2 
 arch/alpha/kernel/entry.S               |    4 
 arch/arm/kernel/ptrace.c                |   36 
 arch/arm26/kernel/ptrace.c              |   32 
 arch/frv/kernel/ptrace.c                |   15 
 arch/i386/kernel/entry.S                |    7 
 arch/i386/kernel/i387.c                 |  143 +-
 arch/i386/kernel/process.c              |    3 
 arch/i386/kernel/ptrace.c               |  839 ++++++++--------
 arch/i386/kernel/signal.c               |   39 
 arch/i386/kernel/vm86.c                 |    7 
 arch/ia64/ia32/ia32_entry.S             |    2 
 arch/ia64/ia32/sys_ia32.c               |   23 
 arch/ia64/kernel/asm-offsets.c          |    2 
 arch/ia64/kernel/fsys.S                 |   16 
 arch/ia64/kernel/mca.c                  |    2 
 arch/ia64/kernel/ptrace.c               |   41 
 arch/ia64/kernel/signal.c               |    4 
 arch/mips/kernel/ptrace.c               |   21 
 arch/mips/kernel/sysirix.c              |    2 
 arch/powerpc/kernel/Makefile            |    4 
 arch/powerpc/kernel/asm-offsets.c       |    2 
 arch/powerpc/kernel/process.c           |    5 
 arch/powerpc/kernel/ptrace-common.h     |  161 ---
 arch/powerpc/kernel/ptrace.c            |  785 +++++++--------
 arch/powerpc/kernel/ptrace32.c          |  436 --------
 arch/powerpc/kernel/signal_32.c         |   56 +
 arch/powerpc/kernel/signal_64.c         |    4 
 arch/powerpc/kernel/sys_ppc32.c         |    5 
 arch/powerpc/lib/sstep.c                |    3 
 arch/powerpc/platforms/cell/spufs/run.c |    2 
 arch/ppc/kernel/asm-offsets.c           |    2 
 arch/s390/kernel/compat_linux.c         |    3 
 arch/s390/kernel/compat_signal.c        |    5 
 arch/s390/kernel/process.c              |    3 
 arch/s390/kernel/ptrace.c               |  553 +++++++++--
 arch/s390/kernel/signal.c               |    4 
 arch/s390/kernel/traps.c                |    6 
 arch/sparc64/kernel/entry.S             |    6 
 arch/sparc64/kernel/process.c           |    3 
 arch/sparc64/kernel/ptrace.c            |  653 +++++++++++--
 arch/sparc64/kernel/signal.c            |    2 
 arch/sparc64/kernel/signal32.c          |    2 
 arch/sparc64/kernel/sys_sparc32.c       |    3 
 arch/sparc64/kernel/systbls.S           |    4 
 arch/x86_64/ia32/fpu32.c                |   92 +
 arch/x86_64/ia32/ia32_aout.c            |    6 
 arch/x86_64/ia32/ia32_signal.c          |    8 
 arch/x86_64/ia32/ia32entry.S            |    2 
 arch/x86_64/ia32/ptrace32.c             |  688 ++++++++-----
 arch/x86_64/ia32/sys_ia32.c             |    5 
 arch/x86_64/kernel/process.c            |    5 
 arch/x86_64/kernel/ptrace.c             |  619 +++++++-----
 arch/x86_64/kernel/signal.c             |   30 
 arch/x86_64/kernel/traps.c              |    8 
 arch/x86_64/mm/fault.c                  |    4 
 drivers/connector/cn_proc.c             |    4 
 fs/binfmt_aout.c                        |    6 
 fs/binfmt_elf.c                         |    6 
 fs/binfmt_elf_fdpic.c                   |    7 
 fs/binfmt_flat.c                        |    3 
 fs/binfmt_som.c                         |    2 
 fs/exec.c                               |   11 
 fs/proc/array.c                         |   14 
 fs/proc/base.c                          |   17 
 include/asm-i386/i387.h                 |   13 
 include/asm-i386/signal.h               |    4 
 include/asm-i386/thread_info.h          |    7 
 include/asm-i386/tracehook.h            |   74 +
 include/asm-ia64/tracehook.h            |   67 +
 include/asm-powerpc/tracehook.h         |  303 ++++++
 include/asm-s390/tracehook.h            |  105 ++
 include/asm-sparc64/tracehook.h         |   44 
 include/asm-x86_64/fpu32.h              |    3 
 include/asm-x86_64/thread_info.h        |    2 
 include/asm-x86_64/tracehook.h          |  106 ++
 include/linux/init_task.h               |    3 
 include/linux/ptrace.h                  |   88 -
 include/linux/sched.h                   |   25 
 include/linux/tracehook.h               |  645 ++++++++++++
 include/linux/utrace.h                  |  481 +++++++++
 init/Kconfig                            |   29 
 kernel/Makefile                         |    1 
 kernel/exit.c                           |  253 +----
 kernel/fork.c                           |   62 -
 kernel/ptrace.c                         | 1592 +++++++++++++++++++++++++-------
 kernel/signal.c                         |  211 ----
 kernel/sys.c                            |    2 
 kernel/timer.c                          |    6 
 kernel/utrace.c                         | 1526 ++++++++++++++++++++++++++++++
 security/selinux/hooks.c                |   54 -
 security/selinux/include/objsec.h       |    1 
 93 files changed, 8331 insertions(+), 3320 deletions(-)

Index: linux-2.6-utrace.patch
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/linux-2.6-utrace.patch,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- linux-2.6-utrace.patch	9 Aug 2006 23:58:50 -0000	1.16
+++ linux-2.6-utrace.patch	11 Aug 2006 00:47:52 -0000	1.17
@@ -7,7 +7,7 @@
  arch/i386/kernel/entry.S                |    7 
  arch/i386/kernel/i387.c                 |  143 +--
  arch/i386/kernel/process.c              |    3 
- arch/i386/kernel/ptrace.c               |  839 +++++++++--------
+ arch/i386/kernel/ptrace.c               |  839 +++++++++-------
  arch/i386/kernel/signal.c               |   39 -
  arch/i386/kernel/vm86.c                 |    7 
  arch/ia64/ia32/ia32_entry.S             |    2 
@@ -23,8 +23,8 @@
  arch/powerpc/kernel/asm-offsets.c       |    2 
  arch/powerpc/kernel/process.c           |    5 
  arch/powerpc/kernel/ptrace-common.h     |  161 ---
- arch/powerpc/kernel/ptrace.c            |  785 +++++++---------
- arch/powerpc/kernel/ptrace32.c          |  436 ---------
+ arch/powerpc/kernel/ptrace.c            |  785 +++++++--------
+ arch/powerpc/kernel/ptrace32.c          |  436 --------
  arch/powerpc/kernel/signal_32.c         |   56 +
  arch/powerpc/kernel/signal_64.c         |    4 
  arch/powerpc/kernel/sys_ppc32.c         |    5 
@@ -48,7 +48,7 @@
  arch/x86_64/ia32/ia32_aout.c            |    6 
  arch/x86_64/ia32/ia32_signal.c          |    8 
  arch/x86_64/ia32/ia32entry.S            |    2 
- arch/x86_64/ia32/ptrace32.c             |  690 +++++++++-----
+ arch/x86_64/ia32/ptrace32.c             |  690 +++++++++----
  arch/x86_64/ia32/sys_ia32.c             |    5 
  arch/x86_64/kernel/process.c            |    5 
  arch/x86_64/kernel/ptrace.c             |  619 +++++++-----
@@ -76,22 +76,22 @@
  include/asm-x86_64/thread_info.h        |    2 
  include/asm-x86_64/tracehook.h          |  106 ++
  include/linux/init_task.h               |    3 
- include/linux/ptrace.h                  |   86 +-
+ include/linux/ptrace.h                  |   88 +-
  include/linux/sched.h                   |   25 
  include/linux/tracehook.h               |  645 +++++++++++++
- include/linux/utrace.h                  |  481 ++++++++++
+ include/linux/utrace.h                  |  481 +++++++++
  init/Kconfig                            |   29 +
  kernel/Makefile                         |    1 
- kernel/exit.c                           |  259 +----
+ kernel/exit.c                           |  253 +----
  kernel/fork.c                           |   62 -
- kernel/ptrace.c                         | 1563 ++++++++++++++++++++++++-------
+ kernel/ptrace.c                         | 1592 ++++++++++++++++++++++++-------
  kernel/signal.c                         |  211 +---
  kernel/sys.c                            |    2 
  kernel/timer.c                          |    6 
  kernel/utrace.c                         | 1526 ++++++++++++++++++++++++++++++
  security/selinux/hooks.c                |   54 +
  security/selinux/include/objsec.h       |    1 
- 93 files changed, 8302 insertions(+), 3326 deletions(-)
+ 93 files changed, 8332 insertions(+), 3321 deletions(-)
  create mode 100644 Documentation/utrace.txt
  delete arch/powerpc/kernel/ptrace-common.h
  delete arch/powerpc/kernel/ptrace32.c
@@ -1492,7 +1492,7 @@
 +#endif	/* linux/utrace.h */
 --- linux-2.6/include/linux/ptrace.h.utrace-ptrace-compat
 +++ linux-2.6/include/linux/ptrace.h
-@@ -49,66 +49,42 @@
+@@ -49,66 +49,44 @@
  #include <asm/ptrace.h>
  
  #ifdef __KERNEL__
@@ -1570,6 +1570,8 @@
 + * This reports any ptrace-child that is ready as do_wait would a normal child.
 + * If there are no ptrace children, returns -ECHILD.
 + * If there are some ptrace children but none reporting now, returns 0.
++ * In those cases the tasklist_lock is still held so next_thread(tsk) works.
++ * For any other return value, tasklist_lock is released before return.
 + */
 +int ptrace_do_wait(struct task_struct *tsk,
 +		   pid_t pid, int options, struct siginfo __user *infop,
@@ -5252,23 +5254,7 @@
  static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
  		    int __user *stat_addr, struct rusage __user *ru)
  {
-@@ -1449,13 +1316,14 @@ repeat:
- 	 */
- 	flag = 0;
- 	current->state = TASK_INTERRUPTIBLE;
--	read_lock(&tasklist_lock);
- 	tsk = current;
-+	rcu_read_lock();
- 	do {
- 		struct task_struct *p;
- 		struct list_head *_p;
- 		int ret;
- 
-+		read_lock(&tasklist_lock);
- 		list_for_each(_p,&tsk->children) {
- 			p = list_entry(_p, struct task_struct, sibling);
- 
-@@ -1465,26 +1333,17 @@ repeat:
+@@ -1465,26 +1332,17 @@ repeat:
  
  			switch (p->state) {
  			case TASK_TRACED:
@@ -5299,7 +5285,7 @@
  					continue;
  				retval = wait_task_stopped(p, ret == 2,
  							   (options & WNOWAIT),
-@@ -1509,6 +1368,10 @@ repeat:
+@@ -1509,6 +1367,10 @@ repeat:
  						goto check_continued;
  					if (!likely(options & WEXITED))
  						continue;
@@ -5310,7 +5296,7 @@
  					retval = wait_task_zombie(
  						p, (options & WNOWAIT),
  						infop, stat_addr, ru);
-@@ -1525,6 +1388,8 @@ check_continued:
+@@ -1525,6 +1387,8 @@ check_continued:
  				flag = 1;
  				if (!unlikely(options & WCONTINUED))
  					continue;
@@ -5319,7 +5305,7 @@
  				retval = wait_task_continued(
  					p, (options & WNOWAIT),
  					infop, stat_addr, ru);
-@@ -1533,23 +1398,25 @@ check_continued:
+@@ -1533,16 +1397,15 @@ check_continued:
  				break;
  			}
  		}
@@ -5331,30 +5317,20 @@
 -					continue;
 -				flag = 1;
 -				break;
-+		read_unlock(&tasklist_lock);
+-			}
 +
 +		retval = ptrace_do_wait(tsk, pid, options,
 +					infop, stat_addr, ru);
 +		if (retval != -ECHILD) {
 +			flag = 1;
-+			if (retval) {
-+				rcu_read_unlock();
++			if (retval != 0) /* He released the lock.  */
 +				goto end;
- 			}
  		}
 +
  		if (options & __WNOTHREAD)
  			break;
  		tsk = next_thread(tsk);
- 		BUG_ON(tsk->signal != current->signal);
- 	} while (tsk != current);
-+	rcu_read_unlock();
- 
--	read_unlock(&tasklist_lock);
- 	if (flag) {
- 		retval = 0;
- 		if (options & WNOHANG)
-@@ -1566,7 +1433,7 @@ end:
+@@ -1566,7 +1429,7 @@ end:
  	remove_wait_queue(&current->signal->wait_chldexit,&wait);
  	if (infop) {
  		if (retval > 0)
@@ -5605,7 +5581,7 @@
  /*
   * Access another process' address space.
   * Source/target buffer must be kernel space, 
-@@ -295,249 +125,1304 @@ int access_process_vm(struct task_struct
+@@ -295,249 +125,1341 @@ int access_process_vm(struct task_struct
  	return buf - old_buf;
  }
  
@@ -5918,8 +5894,7 @@
 +		list_for_each_entry_rcu(state, &tsk->ptracees, entry) {
 +			rcu_assign_pointer(state->engine->data, 0UL);
 +			utrace_detach(state->task, state->engine);
- 		}
--		spin_unlock_irq(&child->sighand->siglock);
++		}
 +
 +		/*
 +		 * Now clear out our list and clean up our data structures.
@@ -5929,7 +5904,8 @@
 +		list_for_each_entry_safe(state, next, &tsk->ptracees, entry) {
 +			list_del_rcu(&state->entry);
 +			ptrace_done(state);
-+		}
+ 		}
+-		spin_unlock_irq(&child->sighand->siglock);
 +		task_unlock(tsk);
  	}
 -	read_unlock(&tasklist_lock);
@@ -5991,7 +5967,7 @@
 +
 +		return utrace_inject_signal(target, engine,
 +					    UTRACE_ACTION_RESUME, info, NULL);
- 	}
++	}
 +
 +	return 0;
 +}
@@ -6020,7 +5996,7 @@
 +			return -EINVAL;
 +		pos = (addr - regset->bias) * regset->size;
 +		n = 1;
-+	}
+ 	}
 +	else
 +		n = nregs == 0 ? regset->n : nregs;
 +
@@ -6179,6 +6155,21 @@
 +		utrace_set_flags(child, engine,
 +				 engine->flags | UTRACE_ACTION_QUIESCE);
 +	}
++
++	/*
++	 * We do this for all requests to match traditional ptrace behavior.
++	 * If the machine state synchronization done at context switch time
++	 * includes e.g. writing back to user memory, we want to make sure
++	 * that has finished before a PTRACE_PEEKDATA can fetch the results.
++	 * On most machines, only regset data is affected by context switch
++	 * and calling utrace_regset later on will take care of that, so
++	 * this is superfluous.
++	 *
++	 * To do this purely in utrace terms, we could do:
++	 *  (void) utrace_regset(child, engine, utrace_native_view(child), 0);
++	 */
++	wait_task_inactive(child);
++
 +	if (child->exit_state)
 +		goto out_tsk;
 +
@@ -6545,15 +6536,20 @@
  	return ret;
  }
 +#endif
++
  
 -/**
 - * ptrace_traceme  --  helper for PTRACE_TRACEME
 - *
 - * Performs checks and sets PT_PTRACED.
 - * Should be used by all ptrace implementations for PTRACE_TRACEME.
-- */
++/*
++ * We're called with tasklist_lock held for reading.
++ * If we return -ECHILD or zero, next_thread(tsk) must still be valid to use.
++ * If we return another error code, or a successful PID value, we
++ * release tasklist_lock first.
+  */
 -int ptrace_traceme(void)
-+
 +int
 +ptrace_do_wait(struct task_struct *tsk,
 +	       pid_t pid, int options, struct siginfo __user *infop,
@@ -6630,6 +6626,16 @@
 +		why = CLD_TRAPPED;
 +		status = (p->exit_code << 8) | 0x7f;
 +	}
+ 
+ 	/*
+-	 * Are we already being traced?
++	 * At this point we are committed to a successful return
++	 * or a user error return.  Release the tasklist_lock.
+ 	 */
+-	task_lock(current);
+-	if (!(current->ptrace & PT_PTRACED)) {
+-		ret = security_ptrace(current->parent, current);
++	read_unlock(&tasklist_lock);
 +
 +	if (rusagep)
 +		err = getrusage(p, RUSAGE_BOTH, rusagep);
@@ -6654,13 +6660,7 @@
 +		struct utrace *utrace;
 +
 +		err = p->pid;
- 
--	/*
--	 * Are we already being traced?
--	 */
--	task_lock(current);
--	if (!(current->ptrace & PT_PTRACED)) {
--		ret = security_ptrace(current->parent, current);
++
  		/*
 -		 * Set the ptrace bit in the process ptrace flags.
 +		 * If this was a non-death report, the child might now be
@@ -6746,10 +6746,7 @@
  	 */
 -	if (pid == 1)
 -		return ERR_PTR(-EPERM);
-+	wake_up_interruptible_sync(&parent->signal->wait_chldexit);
-+	spin_unlock_irqrestore(&sighand->siglock, flags);
-+}
- 
+-
 -	read_lock(&tasklist_lock);
 -	child = find_task_by_pid(pid);
 -	if (child)
@@ -6758,10 +6755,18 @@
 -	if (!child)
 -		return ERR_PTR(-ESRCH);
 -	return child;
++	wake_up_interruptible_sync(&parent->signal->wait_chldexit);
++	spin_unlock_irqrestore(&sighand->siglock, flags);
+ }
+ 
+-#ifndef __ARCH_SYS_PTRACE
+-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 +static u32
 +ptrace_report(struct utrace_attached_engine *engine, struct task_struct *tsk,
 +	      int code)
-+{
+ {
+-	struct task_struct *child;
+-	long ret;
 +	struct ptrace_state *state = (struct ptrace_state *) engine->data;
 +
 +#ifdef PTRACE_DEBUG
@@ -6776,6 +6781,21 @@
 +	}
 +#endif
 +
++	BUG_ON(state->u.live.stopped);
+ 
+ 	/*
+-	 * This lock_kernel fixes a subtle race with suid exec
++	 * Set our QUIESCE flag right now, before notifying the tracer.
++	 * We do this before setting state->u.live.stopped rather than
++	 * by using UTRACE_ACTION_NEWSTATE in our return value, to
++	 * ensure that the tracer can't get the notification and then
++	 * try to resume us with PTRACE_CONT before we set the flag.
+ 	 */
+-	lock_kernel();
+-	if (request == PTRACE_TRACEME) {
+-		ret = ptrace_traceme();
++	utrace_set_flags(tsk, engine, engine->flags | UTRACE_ACTION_QUIESCE);
++
 +	state->u.live.stopped = 1;
 +	state->u.live.reported = 0;
 +	tsk->exit_code = code;
@@ -6786,29 +6806,18 @@
 +	       current->pid, current->exit_code);
 +#endif
 +
-+	return (UTRACE_ACTION_NEWSTATE
-+		| UTRACE_ACTION_QUIESCE | UTRACE_ACTION_NOREAP);
- }
- 
--#ifndef __ARCH_SYS_PTRACE
--asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
++	return UTRACE_ACTION_RESUME;
++}
++
 +static inline u32
 +ptrace_event(struct utrace_attached_engine *engine, struct task_struct *tsk,
 +	     int event)
- {
--	struct task_struct *child;
--	long ret;
++{
 +	struct ptrace_state *state = (struct ptrace_state *) engine->data;
 +	state->u.live.syscall = 0;
 +	return ptrace_report(engine, tsk, (event << 8) | SIGTRAP);
 +}
- 
--	/*
--	 * This lock_kernel fixes a subtle race with suid exec
--	 */
--	lock_kernel();
--	if (request == PTRACE_TRACEME) {
--		ret = ptrace_traceme();
++
 +
 +static u32
 +ptrace_report_death(struct utrace_attached_engine *engine,
@@ -6947,7 +6956,8 @@
 +		   struct task_struct *tsk, int type)
 +{
 +	return UTRACE_ACTION_RESUME; /* XXX */
-+}
+ }
+-#endif /* __ARCH_SYS_PTRACE */
 +
 +static u32
 +ptrace_report_exec(struct utrace_attached_engine *engine,
@@ -6990,8 +7000,7 @@
 +			    struct task_struct *tsk, struct pt_regs *regs)
 +{
 +	return ptrace_report_syscall(engine, tsk, regs, 0);
- }
--#endif /* __ARCH_SYS_PTRACE */
++}
 +
 +static u32
 +ptrace_report_exit(struct utrace_attached_engine *engine,




More information about the fedora-cvs-commits mailing list