--- olpc-2.6-master.00/include/linux/vserver/space.h 1969-12-31 19:00:00.000000000 -0500 +++ olpc-2.6-master-vs22x.02/include/linux/vserver/space.h 2007-03-01 11:52:20.000000000 -0500 @@ -0,0 +1,13 @@ +#ifndef _VX_SPACE_H +#define _VX_SPACE_H + + +#include + +struct vx_info; + +int vx_set_space(struct vx_info *vxi, unsigned long mask); + +#else /* _VX_SPACE_H */ +#warning duplicate inclusion +#endif /* _VX_SPACE_H */ --- olpc-2.6-master.00/kernel/vserver/space.c 1969-12-31 19:00:00.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/vserver/space.c 2007-03-01 11:52:20.000000000 -0500 @@ -0,0 +1,279 @@ +/* + * linux/kernel/vserver/space.c + * + * Virtual Server: Context Space Support + * + * Copyright (C) 2003-2006 Herbert Pötzl + * + * V0.01 broken out from context.c 0.07 + * V0.02 added task locking for namespace + * V0.03 broken out vx_enter_namespace + * V0.04 added *space support and commands + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +atomic_t vs_global_nsproxy = ATOMIC_INIT(0); +atomic_t vs_global_fs = ATOMIC_INIT(0); +atomic_t vs_global_mnt_ns = ATOMIC_INIT(0); +atomic_t vs_global_uts_ns = ATOMIC_INIT(0); +atomic_t vs_global_ipc_ns = ATOMIC_INIT(0); + + +/* namespace functions */ + +#include + +const struct vcmd_space_mask space_mask = { + .mask = CLONE_NEWNS | + CLONE_NEWUTS | + CLONE_NEWIPC | + CLONE_FS +}; + + +/* + * build a new nsproxy mix + * assumes that both proxies are 'const' + * does not touch nsproxy refcounts + * will hold a reference on the result. + */ + +struct nsproxy *vs_mix_nsproxy(struct nsproxy *old_nsproxy, + struct nsproxy *new_nsproxy, unsigned long mask) +{ + struct mnt_namespace *old_ns; + struct uts_namespace *old_uts; + struct ipc_namespace *old_ipc; + struct nsproxy *nsproxy; + + nsproxy = dup_namespaces(old_nsproxy); + if (!nsproxy) + goto out; + + if (mask & CLONE_NEWNS) { + old_ns = nsproxy->mnt_ns; + nsproxy->mnt_ns = new_nsproxy->mnt_ns; + if (nsproxy->mnt_ns) + get_mnt_ns(nsproxy->mnt_ns); + } else + old_ns = NULL; + + if (mask & CLONE_NEWUTS) { + old_uts = nsproxy->uts_ns; + nsproxy->uts_ns = new_nsproxy->uts_ns; + if (nsproxy->uts_ns) + get_uts_ns(nsproxy->uts_ns); + } else + old_uts = NULL; + + if (mask & CLONE_NEWIPC) { + old_ipc = nsproxy->ipc_ns; + nsproxy->ipc_ns = new_nsproxy->ipc_ns; + if (nsproxy->ipc_ns) + get_ipc_ns(nsproxy->ipc_ns); + } else + old_ipc = NULL; + + if (old_ns) + put_mnt_ns(old_ns); + if (old_uts) + put_uts_ns(old_uts); + if (old_ipc) + put_ipc_ns(old_ipc); +out: + return nsproxy; +} + + +/* + * merge two nsproxy structs into a new one. + * will hold a reference on the result. + */ + +static inline +struct nsproxy * __vs_merge_nsproxy(struct nsproxy *old, + struct nsproxy *proxy, unsigned long mask) +{ + struct nsproxy null_proxy = { .mnt_ns = NULL }; + + if (!proxy) + return NULL; + + if (mask) + return vs_mix_nsproxy(old ? old : &null_proxy, + proxy, mask); + get_nsproxy(proxy); + return proxy; +} + +/* + * merge two fs structs into a new one. + * will take a reference on the result. + */ + +static inline +struct fs_struct * __vs_merge_fs(struct fs_struct *old, + struct fs_struct *fs, unsigned long mask) +{ + if (!(mask & CLONE_FS)) { + if (old) + atomic_inc(&old->count); + return old; + } + + if (!fs) + return NULL; + + return copy_fs_struct(fs); +} + + +int vx_enter_space(struct vx_info *vxi, unsigned long mask) +{ + struct nsproxy *proxy, *proxy_cur, *proxy_new; + struct fs_struct *fs, *fs_cur, *fs_new; + int ret; + + if (vx_info_flags(vxi, VXF_INFO_PRIVATE, 0)) + return -EACCES; + + if (!mask) + mask = vxi->vx_nsmask; + + if ((mask & vxi->vx_nsmask) != mask) + return -EINVAL; + + proxy = vxi->vx_nsproxy; + fs = vxi->vx_fs; + + task_lock(current); + fs_cur = current->fs; + atomic_inc(&fs_cur->count); + proxy_cur = current->nsproxy; + get_nsproxy(proxy_cur); + task_unlock(current); + + fs_new = __vs_merge_fs(fs_cur, fs, mask); + if (IS_ERR(fs_new)) { + ret = PTR_ERR(fs_new); + goto out_put; + } + + proxy_new = __vs_merge_nsproxy(proxy_cur, proxy, mask); + if (IS_ERR(proxy_new)) { + ret = PTR_ERR(proxy_new); + goto out_put_fs; + } + + fs_new = xchg(¤t->fs, fs_new); + proxy_new = xchg(¤t->nsproxy, proxy_new); + ret = 0; + + if (proxy_new) + put_nsproxy(proxy_new); +out_put_fs: + if (fs_new) + put_fs_struct(fs_new); +out_put: + if (proxy_cur) + put_nsproxy(proxy_cur); + if (fs_cur) + put_fs_struct(fs_cur); + return ret; +} + + +int vx_set_space(struct vx_info *vxi, unsigned long mask) +{ + struct nsproxy *proxy_vxi, *proxy_cur, *proxy_new; + struct fs_struct *fs_vxi, *fs_cur, *fs_new; + int ret; + + if (!mask) + mask = space_mask.mask; + + if ((mask & space_mask.mask) != mask) + return -EINVAL; + + proxy_vxi = vxi->vx_nsproxy; + fs_vxi = vxi->vx_fs; + + task_lock(current); + fs_cur = current->fs; + atomic_inc(&fs_cur->count); + proxy_cur = current->nsproxy; + get_nsproxy(proxy_cur); + task_unlock(current); + + fs_new = __vs_merge_fs(fs_vxi, fs_cur, mask); + if (IS_ERR(fs_new)) { + ret = PTR_ERR(fs_new); + goto out_put; + } + + proxy_new = __vs_merge_nsproxy(proxy_vxi, proxy_cur, mask); + if (IS_ERR(proxy_new)) { + ret = PTR_ERR(proxy_new); + goto out_put_fs; + } + + fs_new = xchg(&vxi->vx_fs, fs_new); + proxy_new = xchg(&vxi->vx_nsproxy, proxy_new); + vxi->vx_nsmask |= mask; + ret = 0; + + if (proxy_new) + put_nsproxy(proxy_new); +out_put_fs: + if (fs_new) + put_fs_struct(fs_new); +out_put: + if (proxy_cur) + put_nsproxy(proxy_cur); + if (fs_cur) + put_fs_struct(fs_cur); + return ret; +} + + +int vc_enter_space(struct vx_info *vxi, void __user *data) +{ + struct vcmd_space_mask vc_data = { .mask = 0 }; + + if (data && copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return vx_enter_space(vxi, vc_data.mask); +} + +int vc_set_space(struct vx_info *vxi, void __user *data) +{ + struct vcmd_space_mask vc_data = { .mask = 0 }; + + if (data && copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return vx_set_space(vxi, vc_data.mask); +} + +int vc_get_space_mask(struct vx_info *vxi, void __user *data) +{ + if (copy_to_user(data, &space_mask, sizeof(space_mask))) + return -EFAULT; + return 0; +} + --- olpc-2.6-master.00/kernel/nsproxy.c 2007-02-28 20:05:29.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/nsproxy.c 2007-03-01 11:52:20.000000000 -0500 @@ -23,11 +24,6 @@ ***** struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); -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;