Commit e3222c4e authored by Badari Pulavarty's avatar Badari Pulavarty Committed by Linus Torvalds
Browse files

Merge sys_clone()/sys_unshare() nsproxy and namespace handling



sys_clone() and sys_unshare() both makes copies of nsproxy and its associated
namespaces.  But they have different code paths.

This patch merges all the nsproxy and its associated namespace copy/clone
handling (as much as possible).  Posted on container list earlier for
feedback.

- Create a new nsproxy and its associated namespaces and pass it back to
  caller to attach it to right process.

- Changed all copy_*_ns() routines to return a new copy of namespace
  instead of attaching it to task->nsproxy.

- Moved the CAP_SYS_ADMIN checks out of copy_*_ns() routines.

- Removed unnessary !ns checks from copy_*_ns() and added BUG_ON()
  just incase.

- Get rid of all individual unshare_*_ns() routines and make use of
  copy_*_ns() instead.

[akpm@osdl.org: cleanups, warning fix]
[clg@fr.ibm.com: remove dup_namespaces() declaration]
[serue@us.ibm.com: fix CONFIG_IPC_NS=n, clone(CLONE_NEWIPC) retval]
[akpm@linux-foundation.org: fix build with CONFIG_SYSVIPC=n]
Signed-off-by: default avatarBadari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: default avatarSerge Hallyn <serue@us.ibm.com>
Cc: Cedric Le Goater <clg@fr.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: <containers@lists.osdl.org>
Signed-off-by: default avatarCedric Le Goater <clg@fr.ibm.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4fc75ff4
Loading
Loading
Loading
Loading
+7 −23
Original line number Diff line number Diff line
@@ -1441,10 +1441,9 @@ dput_out:
 * Allocate a new namespace structure and populate it with contents
 * copied from the namespace of the passed in task structure.
 */
struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
		struct fs_struct *fs)
{
	struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns;
	struct mnt_namespace *new_ns;
	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
	struct vfsmount *p, *q;
@@ -1509,36 +1508,21 @@ struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
	return new_ns;
}

int copy_mnt_ns(int flags, struct task_struct *tsk)
struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
		struct fs_struct *new_fs)
{
	struct mnt_namespace *ns = tsk->nsproxy->mnt_ns;
	struct mnt_namespace *new_ns;
	int err = 0;

	if (!ns)
		return 0;

	BUG_ON(!ns);
	get_mnt_ns(ns);

	if (!(flags & CLONE_NEWNS))
		return 0;
		return ns;

	if (!capable(CAP_SYS_ADMIN)) {
		err = -EPERM;
		goto out;
	}
	new_ns = dup_mnt_ns(ns, new_fs);

	new_ns = dup_mnt_ns(tsk, tsk->fs);
	if (!new_ns) {
		err = -ENOMEM;
		goto out;
	}

	tsk->nsproxy->mnt_ns = new_ns;

out:
	put_mnt_ns(ns);
	return err;
	return new_ns;
}

asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
+7 −4
Original line number Diff line number Diff line
@@ -92,16 +92,19 @@ extern struct ipc_namespace init_ipc_ns;

#ifdef CONFIG_SYSVIPC
#define INIT_IPC_NS(ns)		.ns		= &init_ipc_ns,
extern int copy_ipcs(unsigned long flags, struct task_struct *tsk);
extern struct ipc_namespace *copy_ipcs(unsigned long flags,
						struct ipc_namespace *ns);
#else
#define INIT_IPC_NS(ns)
static inline int copy_ipcs(unsigned long flags, struct task_struct *tsk)
{ return 0; }
static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
						struct ipc_namespace *ns)
{
	return ns;
}
#endif

#ifdef CONFIG_IPC_NS
extern void free_ipc_ns(struct kref *kref);
extern int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns);
#endif

static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
+2 −3
Original line number Diff line number Diff line
@@ -14,10 +14,9 @@ struct mnt_namespace {
	int event;
};

extern int copy_mnt_ns(int, struct task_struct *);
extern void __put_mnt_ns(struct mnt_namespace *ns);
extern struct mnt_namespace *dup_mnt_ns(struct task_struct *,
extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
		struct fs_struct *);
extern void __put_mnt_ns(struct mnt_namespace *ns);

static inline void put_mnt_ns(struct mnt_namespace *ns)
{
+2 −1
Original line number Diff line number Diff line
@@ -31,10 +31,11 @@ struct nsproxy {
};
extern struct nsproxy init_nsproxy;

struct nsproxy *dup_namespaces(struct nsproxy *orig);
int copy_namespaces(int flags, struct task_struct *tsk);
void get_task_namespaces(struct task_struct *tsk);
void free_nsproxy(struct nsproxy *ns);
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
	struct fs_struct *);

static inline void put_nsproxy(struct nsproxy *ns)
{
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ static inline void get_pid_ns(struct pid_namespace *ns)
	kref_get(&ns->kref);
}

extern int copy_pid_ns(int flags, struct task_struct *tsk);
extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
extern void free_pid_ns(struct kref *kref);

static inline void put_pid_ns(struct pid_namespace *ns)
Loading