[Devel] [PATCH RHEL COMMIT] overlayfs: relax capable check for trusted prefix xattrs

Konstantin Khorenko khorenko at virtuozzo.com
Mon Oct 4 20:39:07 MSK 2021


The commit is pushed to "branch-rh9-5.14.vz9.1.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after ark-5.14
------>
commit 3feeee0e227b88a44db1f2998c269194942df161
Author: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
Date:   Mon Oct 4 20:39:07 2021 +0300

    overlayfs: relax capable check for trusted prefix xattrs
    
    ovl_listxattr() additionally check if attributes can be shown to user by
    calling capable(). Change it to ve_capable() to avoid problems in containers.
    
    https://jira.sw.ru/browse/PSBM-124532
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
    
    (cherry-picked from vz commit 2a2b9806906460afcddda2cd273a9933504ee8b9)
    
    conflicts:
    In the original patch capable() has been changed to ve_capable(), but in
    VZ8 capable() is not used anymore and is substituted by
    ns_capable_noaudit(), in 5c2e9f346b815841f9bed6029ebcb06415caf640.
    I have examined this patch.
    
    What it does is removes unneeded audit log in ovl_listxattr: during
    listxattr, some trusted xattrs can be met by the listing algorithm, they
    will be filtered out from the output and not shown to the user.
    
    In the filtering function, that decides which xattrs should be hidden,
    both capable() and ns_capable_noaudit() served the same function to say
    yes or no to the filtering function, but capable() did that with
    additionally doing an audit log (a kind of a warning in the logs), which
    is not needed in reality as this was an internal kernel checking
    function, not the actual userspace request to access a trusted object,
    userspace will never see this item.
    
    So ns_capability_noaudit() - has the same functionality as capable()
    except for it also passes the flag to selinux_capable() to NOT perform
    an audit log, still it will decide should the attribute be visible to
    the user or not in the same way.
    
    To call ns_capable_noaudit() in the same way ve_capable() calls
    ns_capable(), ve_capable_noaudit() has been added in the same
    cherry-pick patch.
    
    https://jira.sw.ru/browse/PSBM-127858
    Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
    
    (cherry picked from vz8 commit 834a4045afeb6e9308c319e59bab2584d21433db)
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 fs/overlayfs/inode.c       |  2 +-
 include/linux/capability.h |  1 +
 kernel/capability.c        | 24 ++++++++++++++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 5e828a1c98a8..9f8a04021581 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -411,7 +411,7 @@ static bool ovl_can_list(struct super_block *sb, const char *s)
 		return true;
 
 	/* list other trusted for superuser only */
-	return ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
+	return ve_capable_noaudit(CAP_SYS_ADMIN);
 }
 
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index c7ac860db4f1..7761f5c00f56 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -210,6 +210,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 ns_capable_noaudit(struct user_namespace *ns, int cap);
+extern bool ve_capable_noaudit(int cap);
 extern bool ns_capable_setid(struct user_namespace *ns, int cap);
 #else
 static inline bool has_capability(struct task_struct *t, int cap)
diff --git a/kernel/capability.c b/kernel/capability.c
index f17becfa97ee..318ffb811db6 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -415,13 +415,37 @@ bool ve_capable(int cap)
 
 	return ret;
 }
+
+bool ve_capable_noaudit(int cap)
+{
+	struct cred *cred;
+	bool ret;
+
+	rcu_read_lock();
+	cred = get_exec_env()->init_cred;
+
+	if (cred == NULL) /* ve isn't running */
+		cred = ve0.init_cred;
+
+	ret = ns_capable_noaudit(cred->user_ns, cap);
+	rcu_read_unlock();
+
+	return ret;
+}
+
 #else
 bool ve_capable(int cap)
 {
 	return capable(cap);
 }
+
+bool ve_capable_noaudit(int cap)
+{
+	return ns_capable_noaudit(&init_user_ns, cap);
+}
 #endif
 EXPORT_SYMBOL_GPL(ve_capable);
+EXPORT_SYMBOL_GPL(ve_capable_noaudit);
 
 /**
  * ns_capable_noaudit - Determine if the current task has a superior capability


More information about the Devel mailing list