--- linux-2.6.16-vs2.1.1-rc14.7/include/linux/vserver/limit_cmd.h 2006-03-20 17:34:50 +0100 +++ linux-2.6.16-vs2.1.1-rc14.9/include/linux/vserver/limit_cmd.h 2006-04-02 07:19:29 +0200 @@ -27,11 +27,29 @@ struct vcmd_ctx_rlimit_mask_v0 { #ifdef __KERNEL__ +#ifdef CONFIG_COMPAT + +struct vcmd_ctx_rlimit_v0_x32 { + uint32_t id; + uint64_t minimum; + uint64_t softlimit; + uint64_t maximum; +} __attribute__ ((packed)); + +#endif /* CONFIG_COMPAT */ + #include extern int vc_get_rlimit(uint32_t, void __user *); extern int vc_set_rlimit(uint32_t, void __user *); extern int vc_get_rlimit_mask(uint32_t, void __user *); +#ifdef CONFIG_COMPAT + +extern int vc_get_rlimit_x32(uint32_t, void __user *); +extern int vc_set_rlimit_x32(uint32_t, void __user *); + +#endif /* CONFIG_COMPAT */ + #endif /* __KERNEL__ */ #endif /* _VX_LIMIT_CMD_H */ --- linux-2.6.16-vs2.1.1-rc14.7/kernel/vserver/limit.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.1-rc14.9/kernel/vserver/limit.c 2006-04-02 07:20:04 +0200 @@ -75,64 +75,120 @@ static inline uint64_t vc_get_hard(struc return VX_VLIM(limit); } -int vc_get_rlimit(uint32_t id, void __user *data) +int do_get_rlimit(xid_t xid, uint32_t id, + uint64_t *minimum, uint64_t *softlimit, uint64_t *maximum) { struct vx_info *vxi; - struct vcmd_ctx_rlimit_v0 vc_data; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) - return -EFAULT; - if (!is_valid_rlimit(vc_data.id)) + if (!is_valid_rlimit(id)) return -EINVAL; - vxi = lookup_vx_info(id); + vxi = lookup_vx_info(xid); if (!vxi) return -ESRCH; - vc_data.minimum = CRLIM_UNSET; - vc_data.softlimit = vc_get_soft(vxi, vc_data.id); - vc_data.maximum = vc_get_hard(vxi, vc_data.id); + if (minimum) + *minimum = CRLIM_UNSET; + if (softlimit) + *softlimit = vc_get_soft(vxi, id); + if (maximum) + *maximum = vc_get_hard(vxi, id); put_vx_info(vxi); + return 0; +} +int vc_get_rlimit(uint32_t id, void __user *data) +{ + struct vcmd_ctx_rlimit_v0 vc_data; + int ret; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = do_get_rlimit(id, vc_data.id, + &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum); + if (ret) + return ret; + if (copy_to_user (data, &vc_data, sizeof(vc_data))) return -EFAULT; return 0; } -int vc_set_rlimit(uint32_t id, void __user *data) +int do_set_rlimit(xid_t xid, uint32_t id, + uint64_t minimum, uint64_t softlimit, uint64_t maximum) { struct vx_info *vxi; - struct vcmd_ctx_rlimit_v0 vc_data; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE)) - return -EPERM; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) - return -EFAULT; - if (!is_valid_rlimit(vc_data.id)) + if (!is_valid_rlimit(id)) return -EINVAL; - vxi = lookup_vx_info(id); + vxi = lookup_vx_info(xid); if (!vxi) return -ESRCH; - if (vc_data.maximum != CRLIM_KEEP) - __rlim_hard(&vxi->limit, vc_data.id) = - VX_RLIM(vc_data.maximum); - if (vc_data.softlimit != CRLIM_KEEP) - __rlim_soft(&vxi->limit, vc_data.id) = - VX_RLIM(vc_data.softlimit); + if (maximum != CRLIM_KEEP) + __rlim_hard(&vxi->limit, id) = VX_RLIM(maximum); + if (softlimit != CRLIM_KEEP) + __rlim_soft(&vxi->limit, id) = VX_RLIM(softlimit); /* clamp soft limit */ - if (__rlim_soft(&vxi->limit, vc_data.id) > - __rlim_hard(&vxi->limit, vc_data.id)) - __rlim_soft(&vxi->limit, vc_data.id) = - __rlim_hard(&vxi->limit, vc_data.id); + if (__rlim_soft(&vxi->limit, id) > __rlim_hard(&vxi->limit, id)) + __rlim_soft(&vxi->limit, id) = __rlim_hard(&vxi->limit, id); put_vx_info(vxi); + return 0; +} + +int vc_set_rlimit(uint32_t id, void __user *data) +{ + struct vcmd_ctx_rlimit_v0 vc_data; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_rlimit(id, vc_data.id, + vc_data.minimum, vc_data.softlimit, vc_data.maximum); +} + +#ifdef CONFIG_COMPAT + +int vc_set_rlimit_x32(uint32_t id, void __user *data) +{ + struct vcmd_ctx_rlimit_v0_x32 vc_data; + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_rlimit(id, vc_data.id, + vc_data.minimum, vc_data.softlimit, vc_data.maximum); +} + +int vc_get_rlimit_x32(uint32_t id, void __user *data) +{ + struct vcmd_ctx_rlimit_v0_x32 vc_data; + int ret; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = do_get_rlimit(id, vc_data.id, + &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum); + if (ret) + return ret; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; return 0; } +#endif + + int vc_get_rlimit_mask(uint32_t id, void __user *data) { static struct vcmd_ctx_rlimit_mask_v0 mask = { --- linux-2.6.16-vs2.1.1-rc14.7/kernel/vserver/switch.c 2006-03-27 03:57:58 +0200 +++ linux-2.6.16-vs2.1.1-rc14.9/kernel/vserver/switch.c 2006-04-02 04:32:54 +0200 @@ -140,9 +140,9 @@ long do_vserver(uint32_t cmd, uint32_t i switch (cmd) { case VCMD_get_rlimit: - return vc_get_rlimit(id, data); + return __COMPAT(vc_get_rlimit, id, data, compat); case VCMD_set_rlimit: - return vc_set_rlimit(id, data); + return __COMPAT(vc_set_rlimit, id, data, compat); case VCMD_get_rlimit_mask: return vc_get_rlimit_mask(id, data);