diff -NurpP linux-2.6.16-vs2.1.1-rc15.5/include/linux/vserver/context_cmd.h linux-2.6.16-vs2.1.1-rc15.6/include/linux/vserver/context_cmd.h --- linux-2.6.16-vs2.1.1-rc15.5/include/linux/vserver/context_cmd.h 2006-03-20 17:34:50 +0100 +++ linux-2.6.16-vs2.1.1-rc15.6/include/linux/vserver/context_cmd.h 2006-04-12 02:56:58 +0200 @@ -67,8 +67,8 @@ extern int vc_set_cflags(uint32_t, void /* context caps commands */ -#define VCMD_get_ccaps VC_CMD(FLAGS, 3, 0) -#define VCMD_set_ccaps VC_CMD(FLAGS, 4, 0) +#define VCMD_get_ccaps_v0 VC_CMD(FLAGS, 3, 0) +#define VCMD_set_ccaps_v0 VC_CMD(FLAGS, 4, 0) struct vcmd_ctx_caps_v0 { uint64_t bcaps; @@ -76,9 +76,36 @@ struct vcmd_ctx_caps_v0 { uint64_t cmask; }; +#define VCMD_get_ccaps VC_CMD(FLAGS, 3, 1) +#define VCMD_set_ccaps VC_CMD(FLAGS, 4, 1) + +struct vcmd_ctx_caps_v1 { + uint64_t ccaps; + uint64_t cmask; +}; + #ifdef __KERNEL__ +extern int vc_get_ccaps_v0(uint32_t, void __user *); +extern int vc_set_ccaps_v0(uint32_t, void __user *); extern int vc_get_ccaps(uint32_t, void __user *); extern int vc_set_ccaps(uint32_t, void __user *); #endif /* __KERNEL__ */ + + +/* bcaps commands */ + +#define VCMD_get_bcaps VC_CMD(FLAGS, 9, 0) +#define VCMD_set_bcaps VC_CMD(FLAGS,10, 0) + +struct vcmd_bcaps { + uint64_t bcaps; + uint64_t bmask; +}; + +#ifdef __KERNEL__ +extern int vc_get_bcaps(uint32_t, void __user *); +extern int vc_set_bcaps(uint32_t, void __user *); + +#endif /* __KERNEL__ */ #endif /* _VX_CONTEXT_CMD_H */ diff -NurpP linux-2.6.16-vs2.1.1-rc15.5/kernel/vserver/context.c linux-2.6.16-vs2.1.1-rc15.6/kernel/vserver/context.c --- linux-2.6.16-vs2.1.1-rc15.5/kernel/vserver/context.c 2006-03-27 17:31:59 +0200 +++ linux-2.6.16-vs2.1.1-rc15.6/kernel/vserver/context.c 2006-04-12 02:59:41 +0200 @@ -939,49 +930,116 @@ int vc_set_cflags(uint32_t id, void __us return 0; } -int vc_get_ccaps(uint32_t id, void __user *data) +int do_get_caps(xid_t xid, uint64_t *bcaps, uint64_t *ccaps) { struct vx_info *vxi; - struct vcmd_ctx_caps_v0 vc_data; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - vxi = lookup_vx_info(id); + vxi = lookup_vx_info(xid); if (!vxi) return -ESRCH; - vc_data.bcaps = vxi->vx_bcaps; - vc_data.ccaps = vxi->vx_ccaps; - vc_data.cmask = ~0UL; + if (bcaps) + *bcaps = vxi->vx_bcaps; + if (ccaps) + *ccaps = vxi->vx_ccaps; + put_vx_info(vxi); + return 0; +} + +int vc_get_ccaps_v0(uint32_t id, void __user *data) +{ + struct vcmd_ctx_caps_v0 vc_data; + int ret; + + ret = do_get_caps(id, &vc_data.bcaps, &vc_data.ccaps); + if (ret) + return ret; + vc_data.cmask = ~0UL; if (copy_to_user (data, &vc_data, sizeof(vc_data))) return -EFAULT; return 0; } -int vc_set_ccaps(uint32_t id, void __user *data) +int vc_get_ccaps(uint32_t id, void __user *data) { - struct vx_info *vxi; - struct vcmd_ctx_caps_v0 vc_data; + struct vcmd_ctx_caps_v1 vc_data; + int ret; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) + ret = do_get_caps(id, NULL, &vc_data.ccaps); + if (ret) + return ret; + vc_data.cmask = ~0UL; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) return -EFAULT; + return 0; +} - vxi = lookup_vx_info(id); +int do_set_caps(xid_t xid, uint64_t bcaps, uint64_t bmask, + uint64_t ccaps, uint64_t cmask) +{ + struct vx_info *vxi; + + vxi = lookup_vx_info(xid); if (!vxi) return -ESRCH; - vxi->vx_bcaps &= vc_data.bcaps; - vxi->vx_ccaps = vx_mask_flags(vxi->vx_ccaps, - vc_data.ccaps, vc_data.cmask); + vxi->vx_bcaps = vx_mask_flags(vxi->vx_bcaps, bcaps, bmask); + vxi->vx_ccaps = vx_mask_flags(vxi->vx_ccaps, ccaps, cmask); + put_vx_info(vxi); return 0; } +int vc_set_ccaps_v0(uint32_t id, void __user *data) +{ + struct vcmd_ctx_caps_v0 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + /* simulate old &= behaviour for bcaps */ + return do_set_caps(id, 0, ~vc_data.bcaps, + vc_data.ccaps, vc_data.cmask); +} + +int vc_set_ccaps(uint32_t id, void __user *data) +{ + struct vcmd_ctx_caps_v1 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_caps(id, 0, 0, vc_data.ccaps, vc_data.cmask); +} + +int vc_get_bcaps(uint32_t id, void __user *data) +{ + struct vcmd_bcaps vc_data; + int ret; + + ret = do_get_caps(id, &vc_data.bcaps, NULL); + if (ret) + return ret; + vc_data.bmask = ~0UL; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + +int vc_set_bcaps(uint32_t id, void __user *data) +{ + struct vcmd_bcaps vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_caps(id, vc_data.bcaps, vc_data.bmask, 0, 0); +} + #include EXPORT_SYMBOL_GPL(free_vx_info); diff -NurpP linux-2.6.16-vs2.1.1-rc15.5/kernel/vserver/switch.c linux-2.6.16-vs2.1.1-rc15.6/kernel/vserver/switch.c --- linux-2.6.16-vs2.1.1-rc15.5/kernel/vserver/switch.c 2006-04-03 01:11:42 +0200 +++ linux-2.6.16-vs2.1.1-rc15.6/kernel/vserver/switch.c 2006-04-12 02:47:34 +0200 @@ -118,6 +121,7 @@ long do_vserver(uint32_t cmd, uint32_t i case VCMD_set_namespace_v0: return vc_set_namespace(-1, data); + /* this is version 1 */ case VCMD_set_namespace: return vc_set_namespace(id, data); case VCMD_cleanup_namespace: @@ -128,11 +132,11 @@ long do_vserver(uint32_t cmd, uint32_t i if (!vx_check(0, VX_ADMIN|VX_WATCH) && !vx_flags(VXF_STATE_SETUP,0)) return -EPERM; - + #ifdef CONFIG_VSERVER_LEGACY switch (cmd) { case VCMD_set_cflags: - case VCMD_set_ccaps: + case VCMD_set_ccaps_v0: if (vx_check(0, VX_WATCH)) return 0; } @@ -163,10 +167,20 @@ long do_vserver(uint32_t cmd, uint32_t i case VCMD_get_cflags: return vc_get_cflags(id, data); + case VCMD_set_ccaps_v0: + return vc_set_ccaps_v0(id, data); + /* this is version 1 */ case VCMD_set_ccaps: return vc_set_ccaps(id, data); + case VCMD_get_ccaps_v0: + return vc_get_ccaps_v0(id, data); + /* this is version 1 */ case VCMD_get_ccaps: return vc_get_ccaps(id, data); + case VCMD_set_bcaps: + return vc_set_bcaps(id, data); + case VCMD_get_bcaps: + return vc_get_bcaps(id, data); case VCMD_set_nflags: return vc_set_nflags(id, data);