[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <1335604790.5995.22.camel@marge.simpson.net>
Date:	Sat, 28 Apr 2012 11:19:50 +0200
From:	Mike Galbraith <efault@....de>
To:	LKML <linux-kernel@...r.kernel.org>
Cc:	Oleg Nesterov <oleg@...hat.com>
Subject: [RFC PATCH] namespaces: fix leak on fork() failure
Greetings,
The attached testcase induces quite a bit of pid/mnt namespace leakage.
The below fixes up one of these leaks.  There's still at least one pid
namespace leak left, that being the final put_pid() in softirq context
goes missing.
A trace of the leak that's left shows... 
vsftpd-5055  [003] ....  3921.490806: proc_set_super: get_pid_ns: 0xffff8801c996e988 count:1->2
vsftpd-5055  [003] ....  3921.490823: alloc_pid: get_pid_ns: 0xffff8801c996e988 count:2->3
vsftpd-5102  [003] ....  3921.502565: switch_task_namespaces: exiting: 0xffff8801c996e988 count:3
vsftpd-5102  [003] ....  3921.522296: free_nsproxy: put_pid_ns: 0xffff8801c996e988 count:3->2
vsftpd-5055  [003] ....  3921.574201: proc_kill_sb: put_pid_ns: 0xffff8801c996e988 count:2->1
..but that should be..
vsftpd-5055  [003] ....  3921.497313: proc_set_super: get_pid_ns: 0xffff8801c6e65ff0 count:1->2
vsftpd-5055  [003] ....  3921.497330: alloc_pid: get_pid_ns: 0xffff8801c6e65ff0 count:2->3
vsftpd-5124  [003] ....  3921.502977: switch_task_namespaces: exiting: 0xffff8801c6e65ff0 count:3
vsftpd-5124  [003] ....  3921.522308: free_nsproxy: put_pid_ns: 0xffff8801c6e65ff0 count:3->2
vsftpd-5055  [003] ....  3921.698349: proc_kill_sb: put_pid_ns: 0xffff8801c6e65ff0 count:2->1
ksoftirqd/3-16    [003] ..s.  3921.702182: put_pid: put_pid_ns: 0xffff8801c6e65ff0 count:1->0
Anyway, here's what I did for one of the little buggers.
SIGCHLD delivery during fork() may cause failure, resulting in the aborted
child being cloned with CLONE_NEWPID leaking namespaces due to proc being
mounted during pid namespace creation, but not unmounted on fork() failure.
Call pid_ns_release_proc() to prevent the leaks.
Signed-off-by: Mike Galbraith <efault@....de>
 
 kernel/nsproxy.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index b576f7f..fd751d3 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -216,6 +216,14 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
 	rcu_assign_pointer(p->nsproxy, new);
 
 	if (ns && atomic_dec_and_test(&ns->count)) {
+		/* Handle fork() failure, unmount proc before proceeding */
+		if (unlikely(!new && !((p->flags & PF_EXITING)))) {
+			struct pid_namespace *pid_ns = ns->pid_ns;
+
+			if (pid_ns && pid_ns != &init_pid_ns)
+				pid_ns_release_proc(pid_ns);
+		}
+
 		/*
 		 * wait for others to get what they want from this nsproxy.
 		 *
View attachment "vsftpd.c" of type "text/x-csrc" (2182 bytes)
Powered by blists - more mailing lists
 
