rpms/kernel/devel kernel.spec, 1.535, 1.536 linux-2.6-utrace.patch, 1.72, 1.73
Roland McGrath (roland)
fedora-extras-commits at redhat.com
Tue Mar 25 03:20:50 UTC 2008
Author: roland
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv9493
Modified Files:
kernel.spec 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.535
retrieving revision 1.536
diff -u -r1.535 -r1.536
--- kernel.spec 25 Mar 2008 02:47:31 -0000 1.535
+++ kernel.spec 25 Mar 2008 03:19:46 -0000 1.536
@@ -1751,6 +1751,9 @@
%kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL} -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.conf %{with_xen} xen
%changelog
+* Mon Mar 24 2008 Roland McGrath <roland at redhat.com>
+- utrace update
+
* Mon Mar 24 2008 Tom "spot" Callaway <tcallawa at redhat.com>
- Add linux-2.6-sparc64-big-kernel.patch, to support bigger sparc64 kernels (DaveM)
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.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- linux-2.6-utrace.patch 23 Mar 2008 21:11:47 -0000 1.72
+++ linux-2.6-utrace.patch 25 Mar 2008 03:19:46 -0000 1.73
@@ -10,9 +10,7 @@
arch/powerpc/kernel/signal_32.c | 19 +-
arch/powerpc/kernel/sys_ppc32.c | 5 -
arch/sparc64/kernel/binfmt_aout32.c | 2 -
- arch/sparc64/kernel/process.c | 23 +-
arch/sparc64/kernel/ptrace.c | 28 +-
- arch/sparc64/kernel/sys_sparc32.c | 41 +-
arch/x86/ia32/ia32_aout.c | 6 -
arch/x86/ia32/ia32_signal.c | 10 -
arch/x86/ia32/ia32entry.S | 14 +-
@@ -42,15 +40,15 @@
include/asm-x86/ptrace.h | 2 +
include/linux/init_task.h | 3 -
include/linux/ptrace.h | 71 +-
- include/linux/sched.h | 22 +-
+ include/linux/sched.h | 46 +-
include/linux/thread_info.h | 10 +-
include/linux/tracehook.h | 493 ++++++++
include/linux/utrace.h | 544 ++++++++
init/Kconfig | 29 +
kernel/Makefile | 1 +
kernel/compat.c | 3 +-
- kernel/exit.c | 189 +--
- kernel/fork.c | 70 +-
+ kernel/exit.c | 371 +++---
+ kernel/fork.c | 72 +-
kernel/ptrace.c | 2112 +++++++++++++++++++++++++-------
kernel/signal.c | 288 +----
kernel/sys_ni.c | 4 +
@@ -58,7 +56,7 @@
mm/nommu.c | 4 +-
security/selinux/hooks.c | 59 +-
security/selinux/include/objsec.h | 1 -
- 60 files changed, 6209 insertions(+), 1240 deletions(-)
+ 58 files changed, 6306 insertions(+), 1287 deletions(-)
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 300e170..7cf3afc 100644
@@ -75,7 +73,7 @@
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl
new file mode 100644
-index ...00213c2 100644
+index ...f185043 100644
--- /dev/null
+++ b/Documentation/DocBook/utrace.tmpl
@@ -0,0 +1,23 @@
@@ -96,9 +94,9 @@
+ </chapter>
+
+<chapter><title>Machine state access via utrace</title>
-+!Finclude/linux/tracehook.h struct utrace_regset
-+!Finclude/linux/tracehook.h struct utrace_regset_view
-+!Finclude/linux/tracehook.h utrace_native_view
++!Finclude/linux/regset.h struct user_regset
++!Finclude/linux/regset.h struct user_regset_view
++!Finclude/linux/regset.h task_user_regset_view
+ </chapter>
+
+</book>
@@ -921,20 +919,6 @@
return 0;
}
-diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
-index e116e38..c80d850 100644
---- a/arch/sparc64/kernel/process.c
-+++ b/arch/sparc64/kernel/process.c
-@@ -731,9 +731,6 @@ asmlinkage int sparc_execve(struct pt_re
- current_thread_info()->xfsr[0] = 0;
- current_thread_info()->fpsaved[0] = 0;
- regs->tstate &= ~TSTATE_PEF;
-- task_lock(current);
-- current->ptrace &= ~PT_DTRACE;
-- task_unlock(current);
- }
- out:
- return error;
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 9a1ba1f..453023b 100644
--- a/arch/sparc64/kernel/ptrace.c
@@ -997,20 +981,6 @@
if (unlikely(current->audit_context) && !syscall_exit_p)
audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
AUDIT_ARCH_SPARC :
-diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
-index deaba2b..41cbc6b 100644
---- a/arch/sparc64/kernel/sys_sparc32.c
-+++ b/arch/sparc64/kernel/sys_sparc32.c
-@@ -678,9 +678,6 @@ asmlinkage long sparc32_execve(struct pt
- current_thread_info()->xfsr[0] = 0;
- current_thread_info()->fpsaved[0] = 0;
- regs->tstate &= ~TSTATE_PEF;
-- task_lock(current);
-- current->ptrace &= ~PT_DTRACE;
-- task_unlock(current);
- }
- out:
- return error;
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 58cccb6..a0e1dbe 100644
--- a/arch/x86/ia32/ia32_aout.c
@@ -2075,7 +2045,7 @@
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
-index fed07d0..8681933 100644
+index fed07d0..8b552ea 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -996,7 +996,6 @@ struct task_struct {
@@ -2099,15 +2069,39 @@
struct mm_struct *mm, *active_mm;
-@@ -1073,7 +1066,6 @@ struct task_struct {
- * p->parent->pid)
+@@ -1070,18 +1063,26 @@ struct task_struct {
+ /*
+ * pointers to (original) parent process, youngest child, younger sibling,
+ * older sibling, respectively. (p->father can be replaced with
+- * p->parent->pid)
++ * p->real_parent->pid)
*/
- struct task_struct *real_parent; /* real parent process (when being debugged) */
+- struct task_struct *real_parent; /* real parent process (when being debugged) */
- struct task_struct *parent; /* parent process */
++ struct task_struct *real_parent; /* real parent process */
/*
- * children/sibling forms the list of my children plus the
- * tasks I'm ptracing.
-@@ -1162,6 +1154,11 @@ struct task_struct {
+- * children/sibling forms the list of my children plus the
+- * tasks I'm ptracing.
++ * children/sibling forms the list of my natural children
+ */
+ struct list_head children; /* list of my children */
+ struct list_head sibling; /* linkage in my parent's children list */
+ struct task_struct *group_leader; /* threadgroup leader */
+
++
++ /*
++ * ptrace_attached is the list of tasks I have PTRACE_ATTACH'd to,
++ * excluding my own natural children.
++ * ptrace_list is my own link on my PTRACE_ATTACHer's list,
++ * which is p->parent->ptrace_attached.
++ */
++ struct list_head ptrace_attached;
++ struct list_head ptrace_list;
++
+ /* PID/PID hash table linkage. */
+ struct pid_link pids[PIDTYPE_MAX];
+ struct list_head thread_group;
+@@ -1162,6 +1163,11 @@ struct task_struct {
#endif
seccomp_t seccomp;
@@ -2119,7 +2113,7 @@
/* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;
-@@ -1218,8 +1215,6 @@ struct task_struct {
+@@ -1218,8 +1224,6 @@ struct task_struct {
struct io_context *io_context;
@@ -2128,7 +2122,7 @@
#ifdef CONFIG_TASK_XACCT
/* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw;
-@@ -1256,6 +1251,10 @@ struct task_struct {
+@@ -1256,6 +1260,10 @@ struct task_struct {
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
@@ -2139,7 +2133,7 @@
/*
* cache last used pipe for splice
*/
-@@ -1700,6 +1699,7 @@ extern int kill_pgrp(struct pid *pid, in
+@@ -1700,6 +1708,7 @@ extern int kill_pgrp(struct pid *pid, in
extern int kill_pid(struct pid *pid, int sig, int priv);
extern int kill_proc_info(int, struct siginfo *, pid_t);
extern void do_notify_parent(struct task_struct *, int);
@@ -2147,15 +2141,16 @@
extern void force_sig(int, struct task_struct *);
extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
-@@ -1789,7 +1789,7 @@ extern void wait_task_inactive(struct ta
+@@ -1788,9 +1797,6 @@ extern void wait_task_inactive(struct ta
+ #define wait_task_inactive(p) do { } while (0)
#endif
- #define remove_parent(p) list_del_init(&(p)->sibling)
+-#define remove_parent(p) list_del_init(&(p)->sibling)
-#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children)
-+#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->real_parent->children)
-
+-
#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
+ #define for_each_process(p) \
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 421323e..6ce2c42 100644
--- a/include/linux/thread_info.h
@@ -3291,7 +3286,7 @@
}
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/exit.c b/kernel/exit.c
-index 53872bf..fb3b1c0 100644
+index 53872bf..bb79240 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -44,6 +44,7 @@
@@ -3302,6 +3297,15 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
+@@ -64,7 +65,7 @@ static void __unhash_process(struct task
+ __get_cpu_var(process_counts)--;
+ }
+ list_del_rcu(&p->thread_group);
+- remove_parent(p);
++ list_del_init(&p->sibling);
+ }
+
+ /*
@@ -144,12 +145,13 @@ void release_task(struct task_struct * p
{
struct task_struct *leader;
@@ -3348,19 +3352,21 @@
}
/*
-@@ -301,10 +314,9 @@ static void reparent_to_kthreadd(void)
+@@ -301,11 +314,9 @@ static void reparent_to_kthreadd(void)
{
write_lock_irq(&tasklist_lock);
- ptrace_unlink(current);
/* Reparent to init */
- remove_parent(current);
+- remove_parent(current);
- current->real_parent = current->parent = kthreadd_task;
+- add_parent(current);
+ current->real_parent = kthreadd_task;
- add_parent(current);
++ list_move_tail(¤t->sibling, ¤t->real_parent->children);
/* Set the exit signal to SIGCHLD so we signal init on exit */
-@@ -616,37 +628,14 @@ static void exit_mm(struct task_struct *
+ current->exit_signal = SIGCHLD;
+@@ -616,37 +627,13 @@ static void exit_mm(struct task_struct *
mmput(mm);
}
@@ -3372,7 +3378,7 @@
/* We already hold the tasklist_lock here. */
group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
- /* Move the child from its dying parent to the new one. */
+- /* Move the child from its dying parent to the new one. */
- if (unlikely(traced)) {
- /* Preserve ptrace links if someone else is tracing this child. */
- list_del_init(&p->ptrace_list);
@@ -3400,7 +3406,7 @@
/* If this is a threaded reparent there is no need to
* notify anyone anything has happened.
-@@ -661,7 +650,8 @@ reparent_thread(struct task_struct *p, s
+@@ -661,7 +648,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.
*/
@@ -3410,7 +3416,7 @@
p->exit_signal != -1 && thread_group_empty(p))
do_notify_parent(p, p->exit_signal);
-@@ -678,9 +668,6 @@ reparent_thread(struct task_struct *p, s
+@@ -678,9 +666,6 @@ reparent_thread(struct task_struct *p, s
static void forget_original_parent(struct task_struct *father)
{
struct task_struct *p, *n, *reaper = father;
@@ -3420,8 +3426,17 @@
write_lock_irq(&tasklist_lock);
-@@ -701,49 +688,12 @@ static void forget_original_parent(struc
- * Search them and reparent children.
+@@ -693,57 +678,15 @@ static void forget_original_parent(struc
+ } while (reaper->flags & PF_EXITING);
+
+ /*
+- * There are only two places where our children can be:
+- *
+- * - in our child list
+- * - in our ptraced child list
+- *
+- * Search them and reparent children.
++ * Reparent our natural children.
*/
list_for_each_entry_safe(p, n, &father->children, sibling) {
- int ptrace;
@@ -3471,7 +3486,7 @@
}
/*
-@@ -753,6 +703,8 @@ static void forget_original_parent(struc
+@@ -753,6 +696,8 @@ static void forget_original_parent(struc
static void exit_notify(struct task_struct *tsk, int group_dead)
{
int state;
@@ -3480,7 +3495,7 @@
/*
* This does two things:
-@@ -789,20 +741,12 @@ static void exit_notify(struct task_stru
+@@ -789,20 +734,12 @@ static void exit_notify(struct task_stru
&& !capable(CAP_KILL))
tsk->exit_signal = SIGCHLD;
@@ -3505,7 +3520,7 @@
state = EXIT_DEAD;
tsk->exit_state = state;
-@@ -813,6 +757,8 @@ static void exit_notify(struct task_stru
+@@ -813,6 +750,8 @@ static void exit_notify(struct task_stru
write_unlock_irq(&tasklist_lock);
@@ -3514,7 +3529,7 @@
/* If the process is dead, release it - nobody will wait for it */
if (state == EXIT_DEAD)
release_task(tsk);
-@@ -893,10 +839,7 @@ NORET_TYPE void do_exit(long code)
+@@ -893,10 +832,7 @@ NORET_TYPE void do_exit(long code)
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
@@ -3526,7 +3541,7 @@
/*
* We're taking recursive faults here in do_exit. Safest is to just
-@@ -929,6 +872,8 @@ NORET_TYPE void do_exit(long code)
+@@ -929,6 +865,8 @@ NORET_TYPE void do_exit(long code)
smp_mb();
spin_unlock_wait(&tsk->pi_lock);
@@ -3535,7 +3550,7 @@
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
current->comm, task_pid_nr(current),
-@@ -1103,10 +1048,9 @@ static int eligible_child(enum pid_type
+@@ -1103,10 +1041,9 @@ static int eligible_child(enum pid_type
}
/*
@@ -3548,7 +3563,7 @@
return 0;
/* Wait for all children (clone and not) if __WALL is set;
-@@ -1196,8 +1140,7 @@ static int wait_task_zombie(struct task_
+@@ -1196,8 +1133,7 @@ static int wait_task_zombie(struct task_
return 0;
}
@@ -3558,7 +3573,7 @@
if (likely(!traced)) {
struct signal_struct *psig;
-@@ -1218,8 +1161,8 @@ static int wait_task_zombie(struct task_
+@@ -1218,8 +1154,8 @@ static int wait_task_zombie(struct task_
* as other threads in the parent group can be right
* here reaping other children at the same time.
*/
@@ -3569,7 +3584,7 @@
sig = p->signal;
psig->cutime =
cputime_add(psig->cutime,
-@@ -1250,7 +1193,7 @@ static int wait_task_zombie(struct task_
+@@ -1250,7 +1186,7 @@ static int wait_task_zombie(struct task_
psig->coublock +=
task_io_get_oublock(p) +
sig->oublock + sig->coublock;
@@ -3578,7 +3593,7 @@
}
/*
-@@ -1289,24 +1232,6 @@ static int wait_task_zombie(struct task_
+@@ -1289,24 +1225,6 @@ static int wait_task_zombie(struct task_
if (!retval)
retval = pid;
@@ -3603,7 +3618,7 @@
if (p != NULL)
release_task(p);
-@@ -1333,7 +1258,7 @@ static int wait_task_stopped(struct task
+@@ -1333,7 +1251,7 @@ static int wait_task_stopped(struct task
if (unlikely(!task_is_stopped_or_traced(p)))
goto unlock_sig;
@@ -3612,7 +3627,7 @@
/*
* A group stop is in progress and this is the group leader.
* We won't report until all threads have stopped.
-@@ -1362,7 +1287,7 @@ unlock_sig:
+@@ -1362,7 +1280,7 @@ unlock_sig:
*/
get_task_struct(p);
pid = task_pid_vnr(p);
@@ -3621,45 +3636,201 @@
read_unlock(&tasklist_lock);
if (unlikely(noreap))
-@@ -1481,8 +1406,8 @@ repeat:
- * continue, exit, or stop again.
- */
- flag = 1;
+@@ -1442,89 +1360,144 @@ static int wait_task_continued(struct ta
+ return retval;
+ }
+
++/*
++ * Consider @p for a wait by @parent.
++ * Returns -ECHILD if @p is not a child that counts for this wait.
++ * For an -ECHILD return due to security_task_wait refusal, *@enone is
++ * set to the error code if it is not already zero.
++ * Returns 0 if @p is eligible but we have nothing to report about it now.
++ * Returns pid or a different error if we tried to handle @p; in that
++ * case we unlock tasklist_lock before return.
++ */
++static int wait_consider_task(struct task_struct *parent,
++ struct task_struct *p,
++ int *enone,
++ enum pid_type type, struct pid *pid, int options,
++ struct siginfo __user *infop,
++ int __user *stat_addr, struct rusage __user *ru)
++{
++ int ret = eligible_child(type, pid, options, p);
++ if (!ret)
++ return -ECHILD;
++
++ if (unlikely(ret < 0)) {
++ if (*enone)
++ *enone = ret;
++ return -ECHILD;
++ }
++
++ if (task_is_stopped_or_traced(p)) {
++ /*
++ * It's stopped now, so it might later
++ * continue, exit, or stop again.
++ */
++ if (tracehook_inhibit_wait_stopped(p, !(options & WUNTRACED)))
++ return 0;
++
++ return wait_task_stopped(p, (options & WNOWAIT),
++ infop, stat_addr, ru);
++ }
++
++ if (p->exit_state == EXIT_ZOMBIE && !delay_group_leader(p)) {
++ /*
++ * We don't reap group leaders with subthreads.
++ */
++ if (!likely(options & WEXITED))
++ return 0;
++
++ if (tracehook_inhibit_wait_zombie(p))
++ /*
++ * We're prevented from seeing it,
++ * but we will see it eventually.
++ */
++ return 0;
++
++ return wait_task_zombie(p, (options & WNOWAIT),
++ infop, stat_addr, ru);
++ }
++
++ if (p->exit_state != EXIT_DEAD) {
++ /*
++ * It's running now, so it might later
++ * exit, stop, or stop and then continue.
++ */
++ if (!unlikely(options & WCONTINUED))
++ return 0;
++
++ if (tracehook_inhibit_wait_continued(p))
++ return 0;
++
++ return wait_task_continued(p, (options & WNOWAIT),
++ infop, stat_addr, ru);
++ }
++
++ return -ECHILD;
++}
++
++/*
++ * Do the work of do_wait() for one thread in the group, @tsk.
++ * -ECHILD should be in *@retval before the first call.
++ * Returns nonzero if we have unlocked tasklist_lock and have
++ * the final return value ready in *@retval.
++ * Returns zero if the search for a child should continue; then
++ * *@retval is 0 if there are any eligible children, or another
++ * code that security_task_wait returned, or still -ECHILD.
++ */
++static int do_wait_thread(struct task_struct *tsk, int *retval,
++ enum pid_type type, struct pid *pid, int options,
++ struct siginfo __user *infop, int __user *stat_addr,
++ struct rusage __user *ru)
++{
++ struct task_struct *p;
++ int ret;
++
++ list_for_each_entry(p, &tsk->children, sibling) {
++ ret = wait_consider_task(tsk, p, retval, type, pid, options,
++ infop, stat_addr, ru);
++ if (ret != -ECHILD) {
++ *retval = ret;
++ if (ret)
++ return ret;
++ }
++ }
++
++ ret = ptrace_do_wait(tsk, type, pid, options, infop, stat_addr, ru);
++ if (ret != -ECHILD) {
++ *retval = ret;
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
+ static long do_wait(enum pid_type type, struct pid *pid, int options,
+ struct siginfo __user *infop, int __user *stat_addr,
+ struct rusage __user *ru)
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ struct task_struct *tsk;
+- int flag, retval;
++ int retval;
+
+ add_wait_queue(¤t->signal->wait_chldexit,&wait);
+ repeat:
+- /* If there is nothing that can match our critier just get out */
++ /*
++ * If there is nothing that can match our critiera just get out.
++ * We will clear @retval to zero if we see any child that might later
++ * match our criteria, even if we are not able to reap it yet.
++ */
+ retval = -ECHILD;
+ if ((type < PIDTYPE_MAX) && (!pid || hlist_empty(&pid->tasks[type])))
+ goto end;
+
+- /*
+- * We will set this flag if we see any child that might later
+- * match our criteria, even if we are not able to reap it yet.
+- */
+- flag = retval = 0;
+ current->state = TASK_INTERRUPTIBLE;
+ read_lock(&tasklist_lock);
+ tsk = current;
+ do {
+- struct task_struct *p;
++ if (do_wait_thread(tsk, &retval, type, pid, options,
++ infop, stat_addr, ru))
++ goto end;
+
+- list_for_each_entry(p, &tsk->children, sibling) {
+- int ret = eligible_child(type, pid, options, p);
+- if (!ret)
+- continue;
+-
+- if (unlikely(ret < 0)) {
+- retval = ret;
+- } else if (task_is_stopped_or_traced(p)) {
+- /*
+- * It's stopped now, so it might later
+- * continue, exit, or stop again.
+- */
+- flag = 1;
- if (!(p->ptrace & PT_PTRACED) &&
- !(options & WUNTRACED))
-+ if (tracehook_inhibit_wait_stopped(
-+ p, !(options & WUNTRACED)))
- continue;
-
- retval = wait_task_stopped(p,
-@@ -1495,6 +1420,14 @@ repeat:
- */
- if (!likely(options & WEXITED))
- continue;
-+ if (tracehook_inhibit_wait_zombie(p)) {
-+ /*
-+ * We're prevented from seeing it,
-+ * but we will see it eventually.
-+ */
-+ flag = 1;
-+ continue;
-+ }
- retval = wait_task_zombie(p,
- (options & WNOWAIT), infop,
- stat_addr, ru);
-@@ -1506,6 +1439,8 @@ repeat:
- flag = 1;
- if (!unlikely(options & WCONTINUED))
- continue;
-+ if (tracehook_inhibit_wait_continued(p))
-+ continue;
- retval = wait_task_continued(p,
- (options & WNOWAIT), infop,
- stat_addr, ru);
-@@ -1513,18 +1448,15 @@ repeat:
- if (retval != 0) /* tasklist_lock released */
- goto end;
- }
+- continue;
+-
+- retval = wait_task_stopped(p,
+- (options & WNOWAIT), infop,
+- stat_addr, ru);
+- } else if (p->exit_state == EXIT_ZOMBIE &&
+- !delay_group_leader(p)) {
+- /*
+- * We don't reap group leaders with subthreads.
+- */
+- if (!likely(options & WEXITED))
+- continue;
+- retval = wait_task_zombie(p,
+- (options & WNOWAIT), infop,
+- stat_addr, ru);
+- } else if (p->exit_state != EXIT_DEAD) {
+- /*
+- * It's running now, so it might later
+- * exit, stop, or stop and then continue.
+- */
+- flag = 1;
+- if (!unlikely(options & WCONTINUED))
+- continue;
+- retval = wait_task_continued(p,
+- (options & WNOWAIT), infop,
+- stat_addr, ru);
+- }
+- if (retval != 0) /* tasklist_lock released */
+- goto end;
+- }
- if (!flag) {
- list_for_each_entry(p, &tsk->ptrace_children,
- ptrace_list) {
@@ -3669,29 +3840,37 @@
- if (likely(flag > 0))
- break;
- retval = flag;
-+
-+ retval = ptrace_do_wait(tsk, type, pid, options,
-+ infop, stat_addr, ru);
-+ if (retval != -ECHILD) {
-+ flag = 1;
-+ if (retval != 0) /* He released the lock. */
- goto end;
+- goto end;
- }
- }
-+
+- }
if (options & __WNOTHREAD)
break;
tsk = next_thread(tsk);
-@@ -1533,6 +1465,7 @@ repeat:
+@@ -1532,16 +1505,14 @@ repeat:
+ } while (tsk != current);
read_unlock(&tasklist_lock);
- if (flag) {
-+ retval = 0;
- if (options & WNOHANG)
- goto end;
+- if (flag) {
+- if (options & WNOHANG)
+- goto end;
++ if (!retval && !(options & WNOHANG)) {
retval = -ERESTARTSYS;
+- if (signal_pending(current))
+- goto end;
+- schedule();
+- goto repeat;
++ if (!signal_pending(current)) {
++ schedule();
++ goto repeat;
++ }
+ }
+- retval = -ECHILD;
++
+ end:
+ current->state = TASK_RUNNING;
+ remove_wait_queue(¤t->signal->wait_chldexit,&wait);
diff --git a/kernel/fork.c b/kernel/fork.c
-index dd249c3..15fc4f5 100644
+index dd249c3..d090075 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -50,9 +50,11 @@
@@ -3751,12 +3930,14 @@
spin_lock(¤t->sighand->siglock);
-@@ -1330,8 +1330,7 @@ static struct task_struct *copy_process(
+@@ -1329,9 +1329,8 @@ static struct task_struct *copy_process(
+ }
if (likely(p->pid)) {
- add_parent(p);
+- add_parent(p);
- if (unlikely(p->ptrace & PT_PTRACED))
- __ptrace_link(p, current->parent);
++ list_add_tail(&p->sibling, &p->real_parent->children);
+ tracehook_clone_attach(p, trace);
if (thread_group_leader(p)) {
More information about the fedora-extras-commits
mailing list