nsproxy.c 2.9 KB
Newer Older
S
Serge E. Hallyn 已提交
1 2 3 4 5 6 7 8 9
/*
 *  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.
K
Kirill Korotaev 已提交
10 11 12 13
 *
 *  Jun 2006 - namespaces support
 *             OpenVZ, SWsoft Inc.
 *             Pavel Emelianov <xemul@openvz.org>
S
Serge E. Hallyn 已提交
14 15 16 17 18
 */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/nsproxy.h>
19
#include <linux/init_task.h>
20
#include <linux/mnt_namespace.h>
21
#include <linux/utsname.h>
C
Cedric Le Goater 已提交
22
#include <linux/pid_namespace.h>
23 24

struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
S
Serge E. Hallyn 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

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;

48
	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
49
	if (ns)
S
Serge E. Hallyn 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62
		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);

63
	if (ns) {
64 65
		if (ns->mnt_ns)
			get_mnt_ns(ns->mnt_ns);
66 67
		if (ns->uts_ns)
			get_uts_ns(ns->uts_ns);
K
Kirill Korotaev 已提交
68 69
		if (ns->ipc_ns)
			get_ipc_ns(ns->ipc_ns);
C
Cedric Le Goater 已提交
70 71
		if (ns->pid_ns)
			get_pid_ns(ns->pid_ns);
72 73
	}

S
Serge E. Hallyn 已提交
74 75 76 77 78 79 80 81 82 83
	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;
84 85
	struct nsproxy *new_ns;
	int err = 0;
S
Serge E. Hallyn 已提交
86 87 88 89 90 91

	if (!old_ns)
		return 0;

	get_nsproxy(old_ns);

K
Kirill Korotaev 已提交
92
	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
93 94 95 96 97 98 99 100 101 102
		return 0;

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

	tsk->nsproxy = new_ns;

103
	err = copy_mnt_ns(flags, tsk);
K
Kirill Korotaev 已提交
104 105
	if (err)
		goto out_ns;
106

107
	err = copy_utsname(flags, tsk);
K
Kirill Korotaev 已提交
108 109 110 111 112 113
	if (err)
		goto out_uts;

	err = copy_ipcs(flags, tsk);
	if (err)
		goto out_ipc;
114

C
Cedric Le Goater 已提交
115 116 117 118
	err = copy_pid_ns(flags, tsk);
	if (err)
		goto out_pid;

119
out:
120
	put_nsproxy(old_ns);
121
	return err;
K
Kirill Korotaev 已提交
122

C
Cedric Le Goater 已提交
123 124 125
out_pid:
	if (new_ns->ipc_ns)
		put_ipc_ns(new_ns->ipc_ns);
K
Kirill Korotaev 已提交
126 127 128 129
out_ipc:
	if (new_ns->uts_ns)
		put_uts_ns(new_ns->uts_ns);
out_uts:
130 131
	if (new_ns->mnt_ns)
		put_mnt_ns(new_ns->mnt_ns);
K
Kirill Korotaev 已提交
132 133
out_ns:
	tsk->nsproxy = old_ns;
P
Pavel 已提交
134
	kfree(new_ns);
K
Kirill Korotaev 已提交
135
	goto out;
S
Serge E. Hallyn 已提交
136 137 138 139
}

void free_nsproxy(struct nsproxy *ns)
{
C
Cedric Le Goater 已提交
140 141 142 143 144 145 146 147 148
	if (ns->mnt_ns)
		put_mnt_ns(ns->mnt_ns);
	if (ns->uts_ns)
		put_uts_ns(ns->uts_ns);
	if (ns->ipc_ns)
		put_ipc_ns(ns->ipc_ns);
	if (ns->pid_ns)
		put_pid_ns(ns->pid_ns);
	kfree(ns);
S
Serge E. Hallyn 已提交
149
}