copy_process && utrace_init_task (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes)

Oleg Nesterov oleg at redhat.com
Tue Nov 17 19:53:51 UTC 2009


On 11/16, Oleg Nesterov wrote:
>
> On 11/16, Oleg Nesterov wrote:
> >
> > And I didn't check "make xcheck", I guess it still crashes the kernel.
>
> Yes it does. I am almost sure the bug should be trivial, but
> somehow can't find find it.

Found the trivial but nasty problem.

tracehook_finish_clone()->utrace_init_task() sets ->utrace = NULL, but
this is too late. If copy_process() fails before, tracehook_free_task()
will free parent's ->utrace copied by dup_task_struct().

This is nasty because we need some changes outside of utrace/tracehook
files. Perhaps we should send something like the patch below to Andrew
right now?


And! While this bug could perfectly explain the crash, it doesn't.
I appiled this patch

	--- UTRACE-PTRACE/kernel/fork.c~XXX_CRASH	2009-11-16 20:26:23.000000000 +0100
	+++ UTRACE-PTRACE/kernel/fork.c	2009-11-17 20:33:50.000000000 +0100
	@@ -1019,6 +1019,7 @@ static struct task_struct *copy_process(
		if (!p)
			goto fork_out;
	 
	+p->utrace = NULL;
		ftrace_graph_init_task(p);
	 
		rt_mutex_init_task(p);

but "make xcheck" still crashes. Still investigating.

Oleg.

--- TH/include/linux/ptrace.h~TH_INIT_TASK	2009-11-10 21:31:25.000000000 +0100
+++ TH/include/linux/ptrace.h	2009-11-17 20:43:42.000000000 +0100
@@ -148,6 +148,14 @@ static inline int ptrace_event(int mask,
 	return 1;
 }
 
+static inline void ptrace_init_task(struct task_struct *child)
+{
+	INIT_LIST_HEAD(&child->ptrace_entry);
+	INIT_LIST_HEAD(&child->ptraced);
+	child->parent = child->real_parent;
+	child->ptrace = 0;
+}
+
 /**
  * ptrace_init_task - initialize ptrace state for a new child
  * @child:		new child task
@@ -158,12 +166,8 @@ static inline int ptrace_event(int mask,
  *
  * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
  */
-static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
+static inline void ptrace_finish_clone(struct task_struct *child, bool ptrace)
 {
-	INIT_LIST_HEAD(&child->ptrace_entry);
-	INIT_LIST_HEAD(&child->ptraced);
-	child->parent = child->real_parent;
-	child->ptrace = 0;
 	if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) {
 		child->ptrace = current->ptrace;
 		__ptrace_link(child, current->parent);
--- TH/include/linux/tracehook.h~TH_INIT_TASK	2009-11-11 21:49:42.000000000 +0100
+++ TH/include/linux/tracehook.h	2009-11-17 20:42:43.000000000 +0100
@@ -247,6 +247,11 @@ static inline int tracehook_prepare_clon
 	return 0;
 }
 
+static inline void tracehook_init_task(struct task_struct *child)
+{
+	ptrace_init_task(child);
+}
+
 /**
  * tracehook_finish_clone - new child created and being attached
  * @child:		new child task
@@ -261,7 +266,7 @@ static inline int tracehook_prepare_clon
 static inline void tracehook_finish_clone(struct task_struct *child,
 					  unsigned long clone_flags, int trace)
 {
-	ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
+	ptrace_finish_clone(child, (clone_flags & CLONE_PTRACE) || trace);
 }
 
 /**
--- TH/kernel/fork.c~TH_INIT_TASK	2009-11-07 22:15:15.000000000 +0100
+++ TH/kernel/fork.c	2009-11-17 20:40:52.000000000 +0100
@@ -1018,8 +1018,8 @@ static struct task_struct *copy_process(
 	if (!p)
 		goto fork_out;
 
+	tracehook_init_task(p);
 	ftrace_graph_init_task(p);
-
 	rt_mutex_init_task(p);
 
 #ifdef CONFIG_PROVE_LOCKING




More information about the utrace-devel mailing list