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

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 21 21:05:30 MSK 2021


The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.47
------>
commit aee8f9c25de5bf6b62bca3b64178badfc185cb75
Author: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
Date:   Mon Jun 21 21:05:30 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>
---
 fs/overlayfs/inode.c       |  2 +-
 include/linux/capability.h |  1 +
 kernel/capability.c        | 23 +++++++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 109096867ef9..583427c08be6 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -401,7 +401,7 @@ static bool ovl_can_list(const char *s)
 
 	/* Never list trusted.overlay, list other trusted for superuser only */
 	return !ovl_is_private_xattr(s) &&
-	       ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
+	       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 2cd6cc8ead53..814d2ac1bb1e 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);
 #else
 static inline bool has_capability(struct task_struct *t, int cap)
 {
diff --git a/kernel/capability.c b/kernel/capability.c
index 5f1c6cb2af07..6e646cd4187f 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -418,6 +418,23 @@ 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;
+}
+
 bool feature_capable(int feature, int cap)
 {
 	if (get_exec_env()->features & feature)
@@ -431,12 +448,18 @@ bool ve_capable(int cap)
 	return capable(cap);
 }
 
+bool ve_capable_noaudit(int cap)
+{
+	return ns_capable_noaudit(&init_user_ns, cap);
+}
+
 bool feature_capable(int feature, int cap)
 {
 	return capable(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