diff options
| author | Kirill Tkhai <ktkhai@virtuozzo.com> | 2017-05-08 15:56:41 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 17:15:12 -0700 | 
| commit | eaa0d190bfe1ed891b814a52712dcd852554cb08 (patch) | |
| tree | fafc1eb0753750511bac47f2368d8d6ead2f66a9 /kernel | |
| parent | 25b14e92af1a563c7331466ca59188f88050bbf0 (diff) | |
pidns: expose task pid_ns_for_children to userspace
pid_ns_for_children set by a task is known only to the task itself, and
it's impossible to identify it from outside.
It's a big problem for checkpoint/restore software like CRIU, because it
can't correctly handle tasks, that do setns(CLONE_NEWPID) in proccess of
their work.
This patch solves the problem, and it exposes pid_ns_for_children to ns
directory in standard way with the name "pid_for_children":
  ~# ls /proc/5531/ns -l | grep pid
  lrwxrwxrwx 1 root root 0 Jan 14 16:38 pid -> pid:[4026531836]
  lrwxrwxrwx 1 root root 0 Jan 14 16:38 pid_for_children -> pid:[4026532286]
Link: http://lkml.kernel.org/r/149201123914.6007.2187327078064239572.stgit@localhost.localdomain
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Andrei Vagin <avagin@virtuozzo.com>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Michael Kerrisk <mtk.manpages@googlemail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/pid_namespace.c | 34 | 
1 files changed, 34 insertions, 0 deletions
| diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index de461aa0bf9a..d1f3e9f558b8 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -374,6 +374,29 @@ static struct ns_common *pidns_get(struct task_struct *task)  	return ns ? &ns->ns : NULL;  } +static struct ns_common *pidns_for_children_get(struct task_struct *task) +{ +	struct pid_namespace *ns = NULL; + +	task_lock(task); +	if (task->nsproxy) { +		ns = task->nsproxy->pid_ns_for_children; +		get_pid_ns(ns); +	} +	task_unlock(task); + +	if (ns) { +		read_lock(&tasklist_lock); +		if (!ns->child_reaper) { +			put_pid_ns(ns); +			ns = NULL; +		} +		read_unlock(&tasklist_lock); +	} + +	return ns ? &ns->ns : NULL; +} +  static void pidns_put(struct ns_common *ns)  {  	put_pid_ns(to_pid_ns(ns)); @@ -443,6 +466,17 @@ const struct proc_ns_operations pidns_operations = {  	.get_parent	= pidns_get_parent,  }; +const struct proc_ns_operations pidns_for_children_operations = { +	.name		= "pid_for_children", +	.real_ns_name	= "pid", +	.type		= CLONE_NEWPID, +	.get		= pidns_for_children_get, +	.put		= pidns_put, +	.install	= pidns_install, +	.owner		= pidns_owner, +	.get_parent	= pidns_get_parent, +}; +  static __init int pid_namespaces_init(void)  {  	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); | 
