nsproxy.c 2.1 KB
Newer Older
S
Serge E. Hallyn 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 *  Copyright (C) 2006 IBM Corporation
 *
 *  Author: Serge Hallyn <serue@us.ibm.com>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation, version 2 of the
 *  License.
 */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/nsproxy.h>
15
#include <linux/init_task.h>
16
#include <linux/namespace.h>
17 18

struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
S
Serge E. Hallyn 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

static inline void get_nsproxy(struct nsproxy *ns)
{
	atomic_inc(&ns->count);
}

void get_task_namespaces(struct task_struct *tsk)
{
	struct nsproxy *ns = tsk->nsproxy;
	if (ns) {
		get_nsproxy(ns);
	}
}

/*
 * creates a copy of "orig" with refcount 1.
 * This does not grab references to the contained namespaces,
 * so that needs to be done by dup_namespaces.
 */
static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
{
	struct nsproxy *ns;

	ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL);
	if (ns) {
		memcpy(ns, orig, sizeof(struct nsproxy));
		atomic_set(&ns->count, 1);
	}
	return ns;
}

/*
 * copies the nsproxy, setting refcount to 1, and grabbing a
 * reference to all contained namespaces.  Called from
 * sys_unshare()
 */
struct nsproxy *dup_namespaces(struct nsproxy *orig)
{
	struct nsproxy *ns = clone_namespaces(orig);

59 60 61 62 63
	if (ns) {
		if (ns->namespace)
			get_namespace(ns->namespace);
	}

S
Serge E. Hallyn 已提交
64 65 66 67 68 69 70 71 72 73
	return ns;
}

/*
 * called from clone.  This now handles copy for nsproxy and all
 * namespaces therein.
 */
int copy_namespaces(int flags, struct task_struct *tsk)
{
	struct nsproxy *old_ns = tsk->nsproxy;
74 75
	struct nsproxy *new_ns;
	int err = 0;
S
Serge E. Hallyn 已提交
76 77 78 79 80 81

	if (!old_ns)
		return 0;

	get_nsproxy(old_ns);

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
	if (!(flags & CLONE_NEWNS))
		return 0;

	new_ns = clone_namespaces(old_ns);
	if (!new_ns) {
		err = -ENOMEM;
		goto out;
	}

	tsk->nsproxy = new_ns;

	err = copy_namespace(flags, tsk);
	if (err) {
		tsk->nsproxy = old_ns;
		put_nsproxy(new_ns);
		goto out;
	}

out:
	put_nsproxy(old_ns);
	return err;
S
Serge E. Hallyn 已提交
103 104 105 106
}

void free_nsproxy(struct nsproxy *ns)
{
107 108
		if (ns->namespace)
			put_namespace(ns->namespace);
S
Serge E. Hallyn 已提交
109 110
		kfree(ns);
}