lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 25 May 2009 02:00:16 +0200
From:	Oleg Nesterov <oleg@...hat.com>
To:	Roland McGrath <roland@...hat.com>
Cc:	Christoph Hellwig <hch@...radead.org>, Ingo Molnar <mingo@...e.hu>,
	linux-kernel@...r.kernel.org
Subject: [RFC PATCH 7/X] ptrace: mv task->parent ptrace_task->pt_tracer

Move task_struct->parent into ptrace_task->pt_tracer and change the users
accordingly.

The next patches will add the helper to simplify/cleanup the usage of
->pt_tracer, and unify do_notify_parent/do_notify_parent_cldstop.

 include/linux/sched.h     |    8 +-------
 include/linux/init_task.h |    1 -
 include/linux/ptrace.h    |   18 ++++++++++--------
 include/linux/tracehook.h |    4 ++--
 kernel/ptrace.c           |    8 ++++----
 kernel/exit.c             |   18 +++++++-----------
 kernel/signal.c           |   24 +++++++++++++++---------
 7 files changed, 39 insertions(+), 42 deletions(-)

--- PTRACE/include/linux/sched.h~7_MV_PARENT	2009-05-24 23:10:47.000000000 +0200
+++ PTRACE/include/linux/sched.h	2009-05-25 00:17:28.000000000 +0200
@@ -1186,13 +1186,7 @@ struct task_struct {
 	/* Canary value for the -fstack-protector gcc feature */
 	unsigned long stack_canary;
 
-	/* 
-	 * pointers to (original) parent process, youngest child, younger sibling,
-	 * older sibling, respectively.  (p->father can be replaced with 
-	 * p->real_parent->pid)
-	 */
-	struct task_struct *real_parent; /* real parent process */
-	struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports */
+	struct task_struct *real_parent; /* parent process */
 	/*
 	 * children/sibling forms the list of my natural children
 	 */
--- PTRACE/include/linux/init_task.h~7_MV_PARENT	2009-04-15 12:53:58.000000000 +0200
+++ PTRACE/include/linux/init_task.h	2009-05-25 01:30:35.000000000 +0200
@@ -139,7 +139,6 @@ extern struct cred init_cred;
 	.ptraced	= LIST_HEAD_INIT(tsk.ptraced),			\
 	.ptrace_entry	= LIST_HEAD_INIT(tsk.ptrace_entry),		\
 	.real_parent	= &tsk,						\
-	.parent		= &tsk,						\
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
--- PTRACE/include/linux/ptrace.h~7_MV_PARENT	2009-05-24 23:38:10.000000000 +0200
+++ PTRACE/include/linux/ptrace.h	2009-05-25 00:27:38.000000000 +0200
@@ -76,7 +76,8 @@
 #include <linux/sched.h>		/* For struct task_struct.  */
 
 struct ptrace_task {
-	unsigned long	pt_flags;
+	unsigned long		pt_flags;
+	struct task_struct	*pt_tracer;
 };
 
 extern int alloc_ptrace_task(struct task_struct *child);
@@ -103,11 +104,6 @@ extern int __ptrace_may_access(struct ta
 /* Returns true on success, false on denial. */
 extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
-static inline int ptrace_reparented(struct task_struct *child)
-{
-	return child->real_parent != child->parent;
-}
-
 /**
  * task_ptrace - return %PT_* flags that apply to a task
  * @task:	pointer to &task_struct in question
@@ -120,6 +116,12 @@ static inline int task_ptrace(struct tas
 		task->ptrace_task->pt_flags : 0;
 }
 
+static inline int ptrace_reparented(struct task_struct *child)
+{
+	return unlikely(task_ptrace(child)) &&
+		child->ptrace_task->pt_tracer != child->real_parent;
+}
+
 static inline void ptrace_unlink(struct task_struct *child)
 {
 	if (unlikely(task_ptrace(child)))
@@ -164,10 +166,10 @@ static inline void ptrace_init_task(stru
 {
 	INIT_LIST_HEAD(&child->ptrace_entry);
 	INIT_LIST_HEAD(&child->ptraced);
-	child->parent = child->real_parent;
 
 	if (unlikely(child->ptrace_task) && task_ptrace(current))
-		ptrace_link(child, task_ptrace(current), current->parent);
+		ptrace_link(child, task_ptrace(current),
+				current->ptrace_task->pt_tracer);
 }
 
 /**
--- PTRACE/include/linux/tracehook.h~7_MV_PARENT	2009-05-24 22:15:08.000000000 +0200
+++ PTRACE/include/linux/tracehook.h	2009-05-25 01:51:11.000000000 +0200
@@ -171,8 +171,8 @@ static inline int tracehook_unsafe_exec(
  */
 static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
 {
-	if (task_ptrace(tsk) & PT_PTRACED)
-		return rcu_dereference(tsk->parent);
+	if (tsk->ptrace_task)
+		return rcu_dereference(tsk->ptrace_task->pt_tracer);
 	return NULL;
 }
 
--- PTRACE/kernel/ptrace.c~7_MV_PARENT	2009-05-25 00:03:45.000000000 +0200
+++ PTRACE/kernel/ptrace.c	2009-05-25 00:41:10.000000000 +0200
@@ -47,7 +47,7 @@ void ptrace_link(struct task_struct *chi
 
 	BUG_ON(!list_empty(&child->ptrace_entry));
 	list_add(&child->ptrace_entry, &tracer->ptraced);
-	child->parent = tracer;
+	child->ptrace_task->pt_tracer = tracer;
 }
 
 /*
@@ -85,7 +85,7 @@ void __ptrace_unlink(struct task_struct 
 	BUG_ON(!task_ptrace(child));
 
 	child->ptrace_task->pt_flags = 0;
-	child->parent = child->real_parent;
+	child->ptrace_task->pt_tracer = NULL;
 	list_del_init(&child->ptrace_entry);
 
 	arch_ptrace_untrace(child);
@@ -108,7 +108,7 @@ int ptrace_check_attach(struct task_stru
 	 * be changed by us so it's not changing right after this.
 	 */
 	read_lock(&tasklist_lock);
-	if (task_ptrace(child) && child->parent == current) {
+	if (task_ptrace(child) && child->ptrace_task->pt_tracer == current) {
 		ret = 0;
 		/*
 		 * child->sighand can't be NULL, release_task()
@@ -259,7 +259,7 @@ int ptrace_traceme(void)
 	write_lock_irq(&tasklist_lock);
 	/* Are we already being traced? */
 	if (!task_ptrace(current)) {
-		ret = security_ptrace_traceme(current->parent);
+		ret = security_ptrace_traceme(current->real_parent);
 		/*
 		 * Check PF_EXITING to ensure ->real_parent has not passed
 		 * exit_ptrace(). Otherwise we don't report the error but
--- PTRACE/kernel/exit.c~7_MV_PARENT	2009-05-20 16:00:52.000000000 +0200
+++ PTRACE/kernel/exit.c	2009-05-25 00:49:27.000000000 +0200
@@ -336,7 +336,7 @@ static void reparent_to_kthreadd(void)
 
 	ptrace_unlink(current);
 	/* Reparent to init */
-	current->real_parent = current->parent = kthreadd_task;
+	current->real_parent = kthreadd_task;
 	list_move_tail(&current->sibling, &current->real_parent->children);
 
 	/* Set the exit signal to SIGCHLD so we signal init on exit */
@@ -780,10 +780,6 @@ static void forget_original_parent(struc
 
 	list_for_each_entry_safe(p, n, &father->children, sibling) {
 		p->real_parent = reaper;
-		if (p->parent == father) {
-			BUG_ON(task_ptrace(p));
-			p->parent = p->real_parent;
-		}
 		reparent_thread(father, p, &dead_children);
 	}
 	write_unlock_irq(&tasklist_lock);
@@ -1210,17 +1206,17 @@ static int wait_task_zombie(struct wait_
 		 * p->signal fields, because they are only touched by
 		 * __exit_signal, which runs with tasklist_lock
 		 * write-locked anyway, and so is excluded here.  We do
-		 * need to protect the access to p->parent->signal fields,
-		 * as other threads in the parent group can be right
-		 * here reaping other children at the same time.
+		 * need to protect the access to p->real_parent->signal
+		 * fields, as other threads in the parent group can be
+		 * right here reaping other children at the same time.
 		 *
 		 * We use thread_group_cputime() to get times for the thread
 		 * group, which consolidates times for all threads in the
 		 * group including the group leader.
 		 */
 		thread_group_cputime(p, &cputime);
-		spin_lock_irq(&p->parent->sighand->siglock);
-		psig = p->parent->signal;
+		spin_lock_irq(&p->real_parent->sighand->siglock);
+		psig = p->real_parent->signal;
 		sig = p->signal;
 		psig->cutime =
 			cputime_add(psig->cutime,
@@ -1251,7 +1247,7 @@ static int wait_task_zombie(struct wait_
 			sig->oublock + sig->coublock;
 		task_io_accounting_add(&psig->ioac, &p->ioac);
 		task_io_accounting_add(&psig->ioac, &sig->ioac);
-		spin_unlock_irq(&p->parent->sighand->siglock);
+		spin_unlock_irq(&p->real_parent->sighand->siglock);
 	}
 
 	/*
--- PTRACE/kernel/signal.c~7_MV_PARENT	2009-04-29 15:45:28.000000000 +0200
+++ PTRACE/kernel/signal.c	2009-05-25 01:22:58.000000000 +0200
@@ -1399,6 +1399,7 @@ int do_notify_parent(struct task_struct 
 {
 	struct siginfo info;
 	unsigned long flags;
+	struct task_struct *parent;
 	struct sighand_struct *psig;
 	int ret = sig;
 
@@ -1410,6 +1411,11 @@ int do_notify_parent(struct task_struct 
 	BUG_ON(!task_ptrace(tsk) &&
 	       (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
+	if (task_ptrace(tsk))
+		parent = tsk->ptrace_task->pt_tracer;
+	else
+		parent = tsk->real_parent;
+
 	info.si_signo = sig;
 	info.si_errno = 0;
 	/*
@@ -1425,7 +1431,7 @@ int do_notify_parent(struct task_struct 
 	 * correct to rely on this
 	 */
 	rcu_read_lock();
-	info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+	info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns);
 	info.si_uid = __task_cred(tsk)->uid;
 	rcu_read_unlock();
 
@@ -1444,7 +1450,7 @@ int do_notify_parent(struct task_struct 
 		info.si_status = tsk->exit_code >> 8;
 	}
 
-	psig = tsk->parent->sighand;
+	psig = parent->sighand;
 	spin_lock_irqsave(&psig->siglock, flags);
 	if (!task_ptrace(tsk) && sig == SIGCHLD &&
 	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
@@ -1469,8 +1475,8 @@ int do_notify_parent(struct task_struct 
 			sig = -1;
 	}
 	if (valid_signal(sig) && sig > 0)
-		__group_send_sig_info(sig, &info, tsk->parent);
-	__wake_up_parent(tsk, tsk->parent);
+		__group_send_sig_info(sig, &info, parent);
+	__wake_up_parent(tsk, parent);
 	spin_unlock_irqrestore(&psig->siglock, flags);
 
 	return ret;
@@ -1484,7 +1490,7 @@ static void do_notify_parent_cldstop(str
 	struct sighand_struct *sighand;
 
 	if (task_ptrace(tsk))
-		parent = tsk->parent;
+		parent = tsk->ptrace_task->pt_tracer;
 	else {
 		tsk = tsk->group_leader;
 		parent = tsk->real_parent;
@@ -1496,7 +1502,7 @@ static void do_notify_parent_cldstop(str
 	 * see comment in do_notify_parent() abot the following 3 lines
 	 */
 	rcu_read_lock();
-	info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+	info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns);
 	info.si_uid = __task_cred(tsk)->uid;
 	rcu_read_unlock();
 
@@ -1544,7 +1550,7 @@ static inline int may_ptrace_stop(void)
 	 * is safe to enter schedule().
 	 */
 	if (unlikely(current->mm->core_state) &&
-	    unlikely(current->mm == current->parent->mm))
+	    unlikely(current->mm == current->ptrace_task->pt_tracer->mm))
 		return 0;
 
 	return 1;
@@ -1773,8 +1779,8 @@ static int ptrace_signal(int signr, sigi
 		info->si_signo = signr;
 		info->si_errno = 0;
 		info->si_code = SI_USER;
-		info->si_pid = task_pid_vnr(current->parent);
-		info->si_uid = task_uid(current->parent);
+		info->si_pid = task_pid_vnr(current->ptrace_task->pt_tracer);
+		info->si_uid = task_uid(current->ptrace_task->pt_tracer);
 	}
 
 	/* If the (new) signal is now blocked, requeue it.  */

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ