[Devel] [PATCH RH9 03/13] ve/kernfs: hide forbidden entries in container

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Tue Sep 21 19:04:21 MSK 2021


From: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>

Hide kernfs entries if kernfs superblock instance owner has no permissions for
them.

Signed-off-by: Konstantin Khlebnikov <khlebnikov at openvz.org>
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>

(cherry-picked from vz8 commit 7becc92d98d2e17a10a80b1781d1301be7beeb0f)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/kernfs/dir.c       | 11 +++++++++++
 fs/kernfs/kernfs-ve.h |  7 +++++++
 fs/kernfs/ve.c        | 28 ++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index f77ca8e1a301..f576c5ba364b 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -1064,6 +1064,9 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
 	    kernfs_info(dentry->d_sb)->ns != kn->ns)
 		goto out_bad;
 
+	if (!kernfs_d_visible(kn, kernfs_info(dentry->d_sb)))
+		goto out_bad;
+
 	mutex_unlock(&kernfs_mutex);
 	return 1;
 out_bad:
@@ -1099,6 +1102,11 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
 		goto out_unlock;
 	}
 
+	if(!kernfs_d_visible(kn, kernfs_info(dentry->d_sb))) {
+		ret = NULL;
+		goto out_unlock;
+	}
+
 	/* attach dentry and inode */
 	inode = kernfs_get_inode(dir->i_sb, kn);
 	if (!inode) {
@@ -1691,6 +1699,9 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
 		file->private_data = pos;
 		kernfs_get(pos);
 
+		if (!kernfs_d_visible(pos, kernfs_info(dentry->d_sb)))
+			continue;
+
 		mutex_unlock(&kernfs_mutex);
 		if (!dir_emit(ctx, name, len, ino, type))
 			return 0;
diff --git a/fs/kernfs/kernfs-ve.h b/fs/kernfs/kernfs-ve.h
index 2420af5d5091..116898829e07 100644
--- a/fs/kernfs/kernfs-ve.h
+++ b/fs/kernfs/kernfs-ve.h
@@ -23,6 +23,8 @@ int kernfs_ve_permission(struct kernfs_node *kn,
 
 int kernfs_ve_allowed(struct kernfs_node *kn);
 
+bool kernfs_d_visible(struct kernfs_node *kn, struct kernfs_super_info *info);
+
 #else // CONFIG_VE
 
 void kernfs_get_ve_perms(struct kernfs_node *kn) { }
@@ -39,6 +41,11 @@ static inline int kernfs_ve_allowed(void)
 	return 1;
 }
 
+bool kernfs_d_visible(struct kernfs_node *kn, struct kernfs_super_info *info)
+{
+	return true;
+}
+
 #endif
 
 #endif
diff --git a/fs/kernfs/ve.c b/fs/kernfs/ve.c
index 94cd5913ca3a..383724fb2dae 100644
--- a/fs/kernfs/ve.c
+++ b/fs/kernfs/ve.c
@@ -98,3 +98,31 @@ void kernfs_put_ve_perms(struct kernfs_node *kn)
 	if (kn->ve_perms_map)
 		kmapset_put(kn->ve_perms_map);
 }
+
+bool kernfs_d_visible(struct kernfs_node *kn, struct kernfs_super_info *info)
+{
+	struct ve_struct *ve = info->ve;
+	struct kernfs_node *tmp_kn = kn;
+
+	/* Non-containerized fs */
+	if (!ve)
+		return true;
+
+	/* Host sees anything */
+	if (ve_is_super(ve))
+		return true;
+
+	/* Entries with namespace tag and their sub-entries always visible */
+	while (tmp_kn) {
+		if (tmp_kn->ns)
+			return true;
+		tmp_kn = tmp_kn->parent;
+	}
+
+	/* Symlinks are visible if target kn is visible */
+	if (kernfs_type(kn) == KERNFS_LINK)
+		kn = kn->symlink.target_kn;
+
+	return !!kmapset_get_value(kn->ve_perms_map,
+				   kernfs_info_perms_key(info));
+}
-- 
2.31.1



More information about the Devel mailing list