Skip to content

Commit

Permalink
[PATCH] namespaces: incorporate fs namespace into nsproxy
Browse files Browse the repository at this point in the history
This moves the mount namespace into the nsproxy.  The mount namespace count
now refers to the number of nsproxies point to it, rather than the number of
tasks.  As a result, the unshare_namespace() function in kernel/fork.c no
longer checks whether it is being shared.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
Cc: Kirill Korotaev <dev@openvz.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: Andrey Savochkin <saw@sw.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Serge E. Hallyn authored and Linus Torvalds committed Oct 2, 2006
1 parent 0437eb5 commit 1651e14
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 39 deletions.
22 changes: 8 additions & 14 deletions fs/namespace.c
Expand Up @@ -133,7 +133,7 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)

static inline int check_mnt(struct vfsmount *mnt)
{
return mnt->mnt_namespace == current->namespace;
return mnt->mnt_namespace == current->nsproxy->namespace;
}

static void touch_namespace(struct namespace *ns)
Expand Down Expand Up @@ -830,7 +830,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
if (parent_nd) {
detach_mnt(source_mnt, parent_nd);
attach_mnt(source_mnt, nd);
touch_namespace(current->namespace);
touch_namespace(current->nsproxy->namespace);
} else {
mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
commit_tree(source_mnt);
Expand Down Expand Up @@ -1441,7 +1441,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
*/
struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
{
struct namespace *namespace = tsk->namespace;
struct namespace *namespace = tsk->nsproxy->namespace;
struct namespace *new_ns;
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
struct vfsmount *p, *q;
Expand Down Expand Up @@ -1508,7 +1508,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)

int copy_namespace(int flags, struct task_struct *tsk)
{
struct namespace *namespace = tsk->namespace;
struct namespace *namespace = tsk->nsproxy->namespace;
struct namespace *new_ns;
int err = 0;

Expand All @@ -1531,7 +1531,7 @@ int copy_namespace(int flags, struct task_struct *tsk)
goto out;
}

tsk->namespace = new_ns;
tsk->nsproxy->namespace = new_ns;

out:
put_namespace(namespace);
Expand Down Expand Up @@ -1754,7 +1754,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
detach_mnt(user_nd.mnt, &root_parent);
attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */
attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */
touch_namespace(current->namespace);
touch_namespace(current->nsproxy->namespace);
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&user_nd, &new_nd);
security_sb_post_pivotroot(&user_nd, &new_nd);
Expand All @@ -1780,7 +1780,6 @@ static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
struct namespace *namespace;
struct task_struct *g, *p;

mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
Expand All @@ -1796,13 +1795,8 @@ static void __init init_mount_tree(void)
namespace->root = mnt;
mnt->mnt_namespace = namespace;

init_task.namespace = namespace;
read_lock(&tasklist_lock);
do_each_thread(g, p) {
get_namespace(namespace);
p->namespace = namespace;
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
init_task.nsproxy->namespace = namespace;
get_namespace(namespace);

set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
Expand Down
5 changes: 3 additions & 2 deletions fs/proc/base.c
Expand Up @@ -71,6 +71,7 @@
#include <linux/cpuset.h>
#include <linux/audit.h>
#include <linux/poll.h>
#include <linux/nsproxy.h>
#include "internal.h"

/* NOTE:
Expand Down Expand Up @@ -473,7 +474,7 @@ static int mounts_open(struct inode *inode, struct file *file)

if (task) {
task_lock(task);
namespace = task->namespace;
namespace = task->nsproxy->namespace;
if (namespace)
get_namespace(namespace);
task_unlock(task);
Expand Down Expand Up @@ -544,7 +545,7 @@ static int mountstats_open(struct inode *inode, struct file *file)

if (task) {
task_lock(task);
namespace = task->namespace;
namespace = task->nsproxy->namespace;
if (namespace)
get_namespace(namespace);
task_unlock(task);
Expand Down
1 change: 1 addition & 0 deletions include/linux/init_task.h
Expand Up @@ -72,6 +72,7 @@ extern struct nsproxy init_nsproxy;
#define INIT_NSPROXY(nsproxy) { \
.count = ATOMIC_INIT(1), \
.nslock = SPIN_LOCK_UNLOCKED, \
.namespace = NULL, \
}

#define INIT_SIGHAND(sighand) { \
Expand Down
6 changes: 2 additions & 4 deletions include/linux/namespace.h
Expand Up @@ -4,6 +4,7 @@

#include <linux/mount.h>
#include <linux/sched.h>
#include <linux/nsproxy.h>

struct namespace {
atomic_t count;
Expand All @@ -26,11 +27,8 @@ static inline void put_namespace(struct namespace *namespace)

static inline void exit_namespace(struct task_struct *p)
{
struct namespace *namespace = p->namespace;
struct namespace *namespace = p->nsproxy->namespace;
if (namespace) {
task_lock(p);
p->namespace = NULL;
task_unlock(p);
put_namespace(namespace);
}
}
Expand Down
3 changes: 3 additions & 0 deletions include/linux/nsproxy.h
Expand Up @@ -4,6 +4,8 @@
#include <linux/spinlock.h>
#include <linux/sched.h>

struct namespace;

/*
* A structure to contain pointers to all per-process
* namespaces - fs (mount), uts, network, sysvipc, etc.
Expand All @@ -19,6 +21,7 @@
struct nsproxy {
atomic_t count;
spinlock_t nslock;
struct namespace *namespace;
};
extern struct nsproxy init_nsproxy;

Expand Down
4 changes: 1 addition & 3 deletions include/linux/sched.h
Expand Up @@ -238,7 +238,6 @@ extern signed long schedule_timeout_interruptible(signed long timeout);
extern signed long schedule_timeout_uninterruptible(signed long timeout);
asmlinkage void schedule(void);

struct namespace;
struct nsproxy;

/* Maximum number of active map areas.. This is a random (large) number */
Expand Down Expand Up @@ -897,8 +896,7 @@ struct task_struct {
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
/* namespace */
struct namespace *namespace;
/* namespaces */
struct nsproxy *nsproxy;
/* signal handlers */
struct signal_struct *signal;
Expand Down
4 changes: 0 additions & 4 deletions kernel/exit.c
Expand Up @@ -399,11 +399,8 @@ void daemonize(const char *name, ...)
current->fs = fs;
atomic_inc(&fs->count);

exit_namespace(current);
exit_task_namespaces(current);
current->namespace = init_task.namespace;
current->nsproxy = init_task.nsproxy;
get_namespace(current->namespace);
get_task_namespaces(current);

exit_files(current);
Expand Down Expand Up @@ -923,7 +920,6 @@ fastcall NORET_TYPE void do_exit(long code)
exit_sem(tsk);
__exit_files(tsk);
__exit_fs(tsk);
exit_namespace(tsk);
exit_task_namespaces(tsk);
exit_thread();
cpuset_exit(tsk);
Expand Down
17 changes: 6 additions & 11 deletions kernel/fork.c
Expand Up @@ -1119,11 +1119,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto bad_fork_cleanup_mm;
if ((retval = copy_namespaces(clone_flags, p)))
goto bad_fork_cleanup_keys;
if ((retval = copy_namespace(clone_flags, p)))
goto bad_fork_cleanup_namespaces;
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
if (retval)
goto bad_fork_cleanup_namespace;
goto bad_fork_cleanup_namespaces;

p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
/*
Expand Down Expand Up @@ -1215,7 +1213,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
retval = -ERESTARTNOINTR;
goto bad_fork_cleanup_namespace;
goto bad_fork_cleanup_namespaces;
}

if (clone_flags & CLONE_THREAD) {
Expand Down Expand Up @@ -1263,8 +1261,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
proc_fork_connector(p);
return p;

bad_fork_cleanup_namespace:
exit_namespace(p);
bad_fork_cleanup_namespaces:
exit_task_namespaces(p);
bad_fork_cleanup_keys:
Expand Down Expand Up @@ -1519,10 +1515,9 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
*/
static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
{
struct namespace *ns = current->namespace;
struct namespace *ns = current->nsproxy->namespace;

if ((unshare_flags & CLONE_NEWNS) &&
(ns && atomic_read(&ns->count) > 1)) {
if ((unshare_flags & CLONE_NEWNS) && ns) {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;

Expand Down Expand Up @@ -1655,8 +1650,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
}

if (new_ns) {
ns = current->namespace;
current->namespace = new_ns;
ns = current->nsproxy->namespace;
current->nsproxy->namespace = new_ns;
new_ns = ns;
}

Expand Down
32 changes: 31 additions & 1 deletion kernel/nsproxy.c
Expand Up @@ -13,6 +13,7 @@
#include <linux/version.h>
#include <linux/nsproxy.h>
#include <linux/init_task.h>
#include <linux/namespace.h>

struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);

Expand Down Expand Up @@ -55,6 +56,11 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
{
struct nsproxy *ns = clone_namespaces(orig);

if (ns) {
if (ns->namespace)
get_namespace(ns->namespace);
}

return ns;
}

Expand All @@ -65,16 +71,40 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
int copy_namespaces(int flags, struct task_struct *tsk)
{
struct nsproxy *old_ns = tsk->nsproxy;
struct nsproxy *new_ns;
int err = 0;

if (!old_ns)
return 0;

get_nsproxy(old_ns);

return 0;
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;
}

void free_nsproxy(struct nsproxy *ns)
{
if (ns->namespace)
put_namespace(ns->namespace);
kfree(ns);
}

0 comments on commit 1651e14

Please sign in to comment.