The commit is pushed to "branch-rh7-3.10.0-229.7.2.vz7.8.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-229.7.2.vz7.6.8 ------> commit 9c0a32ed2a39800f298cf96308530c805a9188fd Author: Andrew Vagin <ava...@openvz.org> Date: Tue Sep 8 12:45:07 2015 +0400
cred: add ve_capable to check capabilities relative to the current VE (v2) We want to allow a few operations in VE. Currently we use nsown_capable, but it's wrong, because in this case we allow these operations in any user namespace. v2: take ve0->cred if the currect ve isn't running https://jira.sw.ru/browse/PSBM-39077 Signed-off-by: Andrew Vagin <ava...@virtuozzo.com> Reviewed-by: Vladimir Davydov <vdavy...@virtuozzo.com> --- fs/autofs4/root.c | 6 ++---- fs/ioprio.c | 2 +- fs/namei.c | 2 +- include/linux/capability.h | 1 + kernel/capability.c | 20 ++++++++++++++++++++ kernel/printk.c | 5 ++--- net/ipv6/sit.c | 2 +- net/netfilter/nf_sockopt.c | 2 +- security/commoncap.c | 4 ++-- security/device_cgroup.c | 4 ++-- 10 files changed, 33 insertions(+), 15 deletions(-) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 68e3edb..1462d8b 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -588,8 +588,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) struct autofs_info *p_ino; /* This allows root to remove symlinks */ - if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) && - !capable(CAP_VE_SYS_ADMIN)) + if (!autofs4_oz_mode(sbi) && !ve_capable(CAP_SYS_ADMIN)) return -EPERM; if (atomic_dec_and_test(&ino->count)) { @@ -837,8 +836,7 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) return -ENOTTY; - if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) && - !capable(CAP_VE_SYS_ADMIN)) + if (!autofs4_oz_mode(sbi) && !ve_capable(CAP_SYS_ADMIN)) return -EPERM; switch(cmd) { diff --git a/fs/ioprio.c b/fs/ioprio.c index c876fad..f9d9187 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -75,7 +75,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) switch (class) { case IOPRIO_CLASS_RT: - if (!capable(CAP_VE_ADMIN)) + if (!ve_capable(CAP_SYS_ADMIN)) return -EPERM; class = IOPRIO_CLASS_BE; data = 0; diff --git a/fs/namei.c b/fs/namei.c index 8e29a44..e7d9f54 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3397,7 +3397,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) if (error) return error; - if ((S_ISCHR(mode) || S_ISBLK(mode)) && !nsown_capable(CAP_MKNOD)) + if ((S_ISCHR(mode) || S_ISBLK(mode)) && !ve_capable(CAP_MKNOD)) return -EPERM; if (!dir->i_op->mknod) diff --git a/include/linux/capability.h b/include/linux/capability.h index 2b77384..b1131e3 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -217,6 +217,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, extern bool capable(int cap); extern bool ns_capable(struct user_namespace *ns, int cap); extern bool nsown_capable(int cap); +extern bool ve_capable(int cap); extern bool inode_capable(const struct inode *inode, int cap); extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); diff --git a/kernel/capability.c b/kernel/capability.c index 0a843d5..4a73381 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -16,6 +16,7 @@ #include <linux/pid_namespace.h> #include <linux/user_namespace.h> #include <asm/uaccess.h> +#include <linux/ve.h> /* * Leveraged for setting/resetting capabilities @@ -396,6 +397,25 @@ bool ns_capable(struct user_namespace *ns, int cap) } EXPORT_SYMBOL(ns_capable); +#if CONFIG_VE +bool ve_capable(int cap) +{ + struct cred *cred = get_exec_env()->init_cred; + + if (cred == NULL) /* ve isn't running */ + cred = ve0.init_cred; + + return ns_capable(cred->user_ns, cap); +} +#else +bool ve_capable(int cap) +{ + return capable(cap); +} +#endif + +EXPORT_SYMBOL_GPL(ve_capable); + /** * file_ns_capable - Determine if the file's opener had a capability in effect * @file: The file we want to check diff --git a/kernel/printk.c b/kernel/printk.c index 44b3783..91766fc 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -468,14 +468,13 @@ static int check_syslog_permissions(int type, bool from_file) return 0; if (syslog_action_restricted(type)) { - if (nsown_capable(CAP_SYSLOG)) + if (ve_capable(CAP_SYSLOG)) return 0; /* * For historical reasons, accept CAP_SYS_ADMIN too, with * a warning. */ - if (nsown_capable(CAP_SYS_ADMIN) || - nsown_capable(CAP_VE_ADMIN)) { + if (ve_capable(CAP_SYS_ADMIN)) { pr_warn_once("%s (%d): Attempt to access syslog with " "CAP_SYS_ADMIN but no CAP_SYSLOG " "(deprecated).\n", diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8f4c52d..0cbb2b2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -309,7 +309,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, /* For simple GET or for root users, * we try harder to allocate. */ - kp = (cmax <= 1 || capable(CAP_NET_ADMIN) || capable(CAP_VE_NET_ADMIN)) ? + kp = (cmax <= 1 || ve_capable(CAP_NET_ADMIN)) ? kcalloc(cmax, sizeof(*kp), GFP_KERNEL) : NULL; diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 84dfd09..951a11b 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -115,7 +115,7 @@ static int ve0_load_sockopt_module(struct net *net, u8 pf, int val, int get) const char *name; int ret = -EPERM; - if (!capable(CAP_VE_NET_ADMIN)) + if (!ve_capable(CAP_NET_ADMIN)) goto out; if (sockopt_module_fits(pf, val, get, PF_INET, diff --git a/security/commoncap.c b/security/commoncap.c index 59ff538..9d0a2b6 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -654,7 +654,7 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name, if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof(XATTR_SECURITY_PREFIX) - 1) && - !capable(CAP_SYS_ADMIN) && !capable(CAP_VE_ADMIN)) + !ve_capable(CAP_SYS_ADMIN)) return -EPERM; return 0; } @@ -680,7 +680,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof(XATTR_SECURITY_PREFIX) - 1) && - !capable(CAP_SYS_ADMIN) && !capable(CAP_VE_ADMIN)) + !ve_capable(CAP_SYS_ADMIN)) return -EPERM; return 0; } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 375711e..531e40c 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -83,7 +83,7 @@ static int devcgroup_can_attach(struct cgroup *new_cgrp, { struct task_struct *task = cgroup_taskset_first(set); - if (current != task && !capable(CAP_SYS_ADMIN) && !capable(CAP_VE_SYS_ADMIN)) + if (current != task && !ve_capable(CAP_SYS_ADMIN)) return -EPERM; return 0; } @@ -673,7 +673,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, struct cgroup *p = devcgroup->css.cgroup; struct dev_cgroup *parent = NULL; - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_VE_SYS_ADMIN)) + if (!ve_capable(CAP_SYS_ADMIN)) return -EPERM; if (p->parent) _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel