diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/context.h linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/context.h --- linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/context.h 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/context.h 2008-10-31 03:55:05.000000000 +0100 @@ -86,6 +86,8 @@ #include "cacct_def.h" #include "device_def.h" +#define VX_SPACES 2 + struct _vx_info_pc { struct _vx_sched_pc sched_pc; struct _vx_cvirt_pc cvirt_pc; @@ -100,8 +102,8 @@ struct vx_info { int vx_state; /* context state */ unsigned long vx_nsmask; /* assignment mask */ - struct nsproxy *vx_nsproxy; /* private namespace */ - struct fs_struct *vx_fs; /* private namespace fs */ + struct nsproxy *vx_nsproxy[VX_SPACES]; /* private namespaces */ + struct fs_struct *vx_fs[VX_SPACES]; /* private namespace fs */ uint64_t vx_flags; /* context flags */ uint64_t vx_ccaps; /* context caps (vserver) */ diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/space_cmd.h linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/space_cmd.h --- linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/space_cmd.h 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/space_cmd.h 2008-10-31 03:49:36.000000000 +0100 @@ -3,10 +3,12 @@ #define VCMD_enter_space_v0 VC_CMD(PROCALT, 1, 0) -#define VCMD_enter_space VC_CMD(PROCALT, 1, 1) +#define VCMD_enter_space_v1 VC_CMD(PROCALT, 1, 1) +#define VCMD_enter_space VC_CMD(PROCALT, 1, 2) #define VCMD_set_space_v0 VC_CMD(PROCALT, 3, 0) -#define VCMD_set_space VC_CMD(PROCALT, 3, 1) +#define VCMD_set_space_v1 VC_CMD(PROCALT, 3, 1) +#define VCMD_set_space VC_CMD(PROCALT, 3, 2) #define VCMD_get_space_mask_v0 VC_CMD(PROCALT, 4, 0) @@ -14,13 +16,20 @@ #define VCMD_get_space_default VC_CMD(VSPACE, 1, 0) -struct vcmd_space_mask { +struct vcmd_space_mask_v1 { uint64_t mask; }; +struct vcmd_space_mask_v2 { + uint64_t mask; + uint32_t index; +}; + #ifdef __KERNEL__ +extern int vc_enter_space_v1(struct vx_info *, void __user *); +extern int vc_set_space_v1(struct vx_info *, void __user *); extern int vc_enter_space(struct vx_info *, void __user *); extern int vc_set_space(struct vx_info *, void __user *); extern int vc_get_space_mask(void __user *, int); diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/space.h linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/space.h --- linux-2.6.27.4-vs2.3.0.35.7/include/linux/vserver/space.h 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/include/linux/vserver/space.h 2008-10-31 04:02:02.000000000 +0100 @@ -1,12 +1,11 @@ #ifndef _VX_SPACE_H #define _VX_SPACE_H - #include struct vx_info; -int vx_set_space(struct vx_info *vxi, unsigned long mask); +int vx_set_space(struct vx_info *vxi, unsigned long mask, unsigned index); #else /* _VX_SPACE_H */ #warning duplicate inclusion diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/context.c linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/context.c --- linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/context.c 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/context.c 2008-10-31 03:56:55.000000000 +0100 @@ -172,19 +172,22 @@ static void __shutdown_vx_info(struct vx { struct nsproxy *nsproxy; struct fs_struct *fs; + int index; might_sleep(); vxi->vx_state |= VXS_SHUTDOWN; vs_state_change(vxi, VSC_SHUTDOWN); - nsproxy = xchg(&vxi->vx_nsproxy, NULL); - fs = xchg(&vxi->vx_fs, NULL); + for (index = 0; index < VX_SPACES; index++) { + nsproxy = xchg(&vxi->vx_nsproxy[index], NULL); + if (nsproxy) + put_nsproxy(nsproxy); - if (nsproxy) - put_nsproxy(nsproxy); - if (fs) - put_fs_struct(fs); + fs = xchg(&vxi->vx_fs[index], NULL); + if (fs) + put_fs_struct(fs); + } } /* exported stuff */ @@ -192,6 +195,7 @@ static void __shutdown_vx_info(struct vx void free_vx_info(struct vx_info *vxi) { unsigned long flags; + unsigned index; /* check for reference counts first */ BUG_ON(atomic_read(&vxi->vx_usecnt)); @@ -203,8 +207,11 @@ void free_vx_info(struct vx_info *vxi) /* context shutdown is mandatory */ BUG_ON(!vx_info_state(vxi, VXS_SHUTDOWN)); - BUG_ON(vxi->vx_nsproxy); - BUG_ON(vxi->vx_fs); + /* nsproxy and fs check */ + for (index = 0; index < VX_SPACES; index++) { + BUG_ON(vxi->vx_nsproxy[index]); + BUG_ON(vxi->vx_fs[index]); + } spin_lock_irqsave(&vx_info_inactive_lock, flags); hlist_del(&vxi->vx_hlist); @@ -611,7 +618,8 @@ int vx_migrate_task(struct task_struct * goto out; old_nsp = xchg(&p->nsproxy, new_nsp); - vx_set_space(vxi, CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER); + vx_set_space(vxi, + CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER, 0); put_nsproxy(old_nsp); } } diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/cvirt.c linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/cvirt.c --- linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/cvirt.c 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/cvirt.c 2008-10-31 03:49:36.000000000 +0100 @@ -166,11 +166,10 @@ static char *vx_vhi_name(struct vx_info struct nsproxy *nsproxy; struct uts_namespace *uts; - if (id == VHIN_CONTEXT) return vxi->vx_name; - nsproxy = vxi->vx_nsproxy; + nsproxy = vxi->vx_nsproxy[0]; if (!nsproxy) return NULL; diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/proc.c linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/proc.c --- linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/proc.c 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/proc.c 2008-10-31 03:49:36.000000000 +0100 @@ -150,9 +150,14 @@ int proc_vxi_sched(struct vx_info *vxi, return length; } -int proc_vxi_nsproxy(struct vx_info *vxi, char *buffer) +int proc_vxi_nsproxy0(struct vx_info *vxi, char *buffer) { - return vx_info_proc_nsproxy(vxi->vx_nsproxy, buffer); + return vx_info_proc_nsproxy(vxi->vx_nsproxy[0], buffer); +} + +int proc_vxi_nsproxy1(struct vx_info *vxi, char *buffer) +{ + return vx_info_proc_nsproxy(vxi->vx_nsproxy[1], buffer); } int proc_vxi_cvirt(struct vx_info *vxi, char *buffer) @@ -544,7 +549,8 @@ static struct vs_entry vx_base_stuff[] = VINF("status", S_IRUGO, vxi_status), VINF("limit", S_IRUGO, vxi_limit), VINF("sched", S_IRUGO, vxi_sched), - VINF("nsproxy", S_IRUGO, vxi_nsproxy), + VINF("nsproxy", S_IRUGO, vxi_nsproxy0), + VINF("nsproxy1",S_IRUGO, vxi_nsproxy1), VINF("cvirt", S_IRUGO, vxi_cvirt), VINF("cacct", S_IRUGO, vxi_cacct), {} diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/space.c linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/space.c --- linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/space.c 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/space.c 2008-10-31 04:00:28.000000000 +0100 @@ -39,7 +39,7 @@ atomic_t vs_global_pid_ns = ATOMIC_INIT( #include -static const struct vcmd_space_mask space_mask_v0 = { +static const struct vcmd_space_mask_v1 space_mask_v0 = { .mask = CLONE_FS | CLONE_NEWNS | CLONE_NEWUTS | @@ -48,7 +48,7 @@ static const struct vcmd_space_mask spac 0 }; -static const struct vcmd_space_mask space_mask = { +static const struct vcmd_space_mask_v1 space_mask = { .mask = CLONE_FS | CLONE_NEWNS | CLONE_NEWUTS | @@ -63,7 +63,7 @@ static const struct vcmd_space_mask spac 0 }; -static const struct vcmd_space_mask default_space_mask = { +static const struct vcmd_space_mask_v1 default_space_mask = { .mask = CLONE_FS | CLONE_NEWNS | CLONE_NEWUTS | @@ -217,14 +217,14 @@ struct fs_struct *__vs_merge_fs(struct f } -int vx_enter_space(struct vx_info *vxi, unsigned long mask) +int vx_enter_space(struct vx_info *vxi, unsigned long mask, unsigned index) { struct nsproxy *proxy, *proxy_cur, *proxy_new; struct fs_struct *fs, *fs_cur, *fs_new; int ret; - vxdprintk(VXD_CBIT(space, 8), "vx_enter_space(%p[#%u],0x%08lx)", - vxi, vxi->vx_id, mask); + vxdprintk(VXD_CBIT(space, 8), "vx_enter_space(%p[#%u],0x%08lx,%d)", + vxi, vxi->vx_id, mask, index); if (vx_info_flags(vxi, VXF_INFO_PRIVATE, 0)) return -EACCES; @@ -235,8 +235,8 @@ int vx_enter_space(struct vx_info *vxi, if ((mask & vxi->vx_nsmask) != mask) return -EINVAL; - proxy = vxi->vx_nsproxy; - fs = vxi->vx_fs; + proxy = vxi->vx_nsproxy[index]; + fs = vxi->vx_fs[index]; task_lock(current); fs_cur = current->fs; @@ -275,14 +275,14 @@ out_put: } -int vx_set_space(struct vx_info *vxi, unsigned long mask) +int vx_set_space(struct vx_info *vxi, unsigned long mask, unsigned index) { struct nsproxy *proxy_vxi, *proxy_cur, *proxy_new; struct fs_struct *fs_vxi, *fs_cur, *fs_new; int ret; - vxdprintk(VXD_CBIT(space, 8), "vx_set_space(%p[#%u],0x%08lx)", - vxi, vxi->vx_id, mask); + vxdprintk(VXD_CBIT(space, 8), "vx_set_space(%p[#%u],0x%08lx,%d)", + vxi, vxi->vx_id, mask, index); #if 0 if (!mask) mask = default_space_mask.mask; @@ -290,8 +290,8 @@ int vx_set_space(struct vx_info *vxi, un if ((mask & space_mask.mask) != mask) return -EINVAL; - proxy_vxi = vxi->vx_nsproxy; - fs_vxi = vxi->vx_fs; + proxy_vxi = vxi->vx_nsproxy[index]; + fs_vxi = vxi->vx_fs[index]; task_lock(current); fs_cur = current->fs; @@ -312,8 +312,8 @@ int vx_set_space(struct vx_info *vxi, un goto out_put_fs; } - fs_new = xchg(&vxi->vx_fs, fs_new); - proxy_new = xchg(&vxi->vx_nsproxy, proxy_new); + fs_new = xchg(&vxi->vx_fs[index], fs_new); + proxy_new = xchg(&vxi->vx_nsproxy[index], proxy_new); vxi->vx_nsmask |= mask; ret = 0; @@ -331,29 +331,55 @@ out_put: } +int vc_enter_space_v1(struct vx_info *vxi, void __user *data) +{ + struct vcmd_space_mask_v1 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, 0); +} + int vc_enter_space(struct vx_info *vxi, void __user *data) { - struct vcmd_space_mask vc_data = { .mask = 0 }; + struct vcmd_space_mask_v2 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); + if (vc_data.index >= VX_SPACES) + return -EINVAL; + + return vx_enter_space(vxi, vc_data.mask, vc_data.index); +} + +int vc_set_space_v1(struct vx_info *vxi, void __user *data) +{ + struct vcmd_space_mask_v1 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, 0); } int vc_set_space(struct vx_info *vxi, void __user *data) { - struct vcmd_space_mask vc_data = { .mask = 0 }; + struct vcmd_space_mask_v2 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); + if (vc_data.index >= VX_SPACES) + return -EINVAL; + + return vx_set_space(vxi, vc_data.mask, vc_data.index); } int vc_get_space_mask(void __user *data, int type) { - const struct vcmd_space_mask *mask; + const struct vcmd_space_mask_v1 *mask; if (type == 0) mask = &space_mask_v0; @@ -365,7 +391,7 @@ int vc_get_space_mask(void __user *data, vxdprintk(VXD_CBIT(space, 10), "vc_get_space_mask(%d) = %08llx", type, mask->mask); - if (copy_to_user(data, mask, sizeof(struct vcmd_space_mask))) + if (copy_to_user(data, mask, sizeof(*mask))) return -EFAULT; return 0; } diff -NurpP --minimal linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/switch.c linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/switch.c --- linux-2.6.27.4-vs2.3.0.35.7/kernel/vserver/switch.c 2008-10-13 14:54:20.000000000 +0200 +++ linux-2.6.27.4-vs2.3.0.35.7.2/kernel/vserver/switch.c 2008-10-31 03:49:36.000000000 +0100 @@ -94,7 +94,9 @@ long do_vcmd(uint32_t cmd, uint32_t id, case VCMD_task_tag: return vc_task_tag(id); - /* this is version 1 */ + case VCMD_set_space_v1: + return vc_set_space_v1(vxi, data); + /* this is version 2 */ case VCMD_set_space: return vc_set_space(vxi, data); @@ -204,8 +206,10 @@ long do_vcmd(uint32_t cmd, uint32_t id, return vc_fset_iattr(id, data); case VCMD_enter_space_v0: - return vc_enter_space(vxi, NULL); - /* this is version 1 */ + return vc_enter_space_v1(vxi, NULL); + case VCMD_enter_space_v1: + return vc_enter_space_v1(vxi, data); + /* this is version 2 */ case VCMD_enter_space: return vc_enter_space(vxi, data);