[Devel] [PATCH RHEL7 COMMIT] cred: add ve_capable to check capabilities relative to the current VE (v2)

Konstantin Khorenko khorenko at virtuozzo.com
Tue Sep 8 01:45:07 PDT 2015


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 <avagin at 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 <avagin at virtuozzo.com>
    Reviewed-by: Vladimir Davydov <vdavydov at 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)



More information about the Devel mailing list