[Devel] [PATCH RH8] ve/sync/mounts: skip cursor mounts when iterating over mnt_ns->list

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Thu Jul 15 17:51:04 MSK 2021


After RHEL ported "roc/mounts: add cursor" we need to iterate over
mounts list in mntns more carefully:

- Export mnt_list_next and move it out from CONFIG_PROC_FS;
- Use mnt_list_next in sync_collect_filesystems to skip cursors.

Else kernel would break at dereferencing something from uninitialized
cursor mount.

https://jira.sw.ru/browse/PSBM-131158
Fixes: e92dd8564eab ("ve/fs/sync: Per containter sync and syncfs and
fs.fsync-enable sysctl")
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/namespace.c     | 6 +++---
 fs/sync.c          | 7 +++++--
 include/linux/fs.h | 4 ++++
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index f38b5d70c4d7..9128029f5a78 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1320,9 +1320,8 @@ struct vfsmount *mnt_clone_internal(const struct path *path)
 	return &p->mnt;
 }
 
-#ifdef CONFIG_PROC_FS
-static struct mount *mnt_list_next(struct mnt_namespace *ns,
-				   struct list_head *p)
+struct mount *mnt_list_next(struct mnt_namespace *ns,
+			    struct list_head *p)
 {
 	struct mount *mnt, *ret = NULL;
 
@@ -1339,6 +1338,7 @@ static struct mount *mnt_list_next(struct mnt_namespace *ns,
 	return ret;
 }
 
+#ifdef CONFIG_PROC_FS
 /* iterator; we want it to have access to namespace_sem, thus here... */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
diff --git a/fs/sync.c b/fs/sync.c
index 5a4fab629931..dc38126dbdd5 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -146,9 +146,10 @@ static int sync_collect_filesystems(struct ve_struct *ve, struct list_head *sync
 	mnt_ns = ve_ns->mnt_ns;
 	rcu_read_unlock();
 
-	list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {
+	mnt = mnt_list_next(mnt_ns, &mnt_ns->list);
+	while (mnt) {
 		if (sync_filesystem_collected(sync_list, mnt->mnt.mnt_sb))
-			continue;
+			goto next;
 
 		ss = kmalloc(sizeof(*ss), GFP_KERNEL);
 		if (ss == NULL) {
@@ -165,6 +166,8 @@ static int sync_collect_filesystems(struct ve_struct *ve, struct list_head *sync
 		ss->sb->s_count++;
 		spin_unlock(&sb_lock);
 		list_add_tail(&ss->list, sync_list);
+next:
+		mnt = mnt_list_next(mnt_ns, &mnt->mnt_list);
 	}
 	up_read(&namespace_sem);
 	return ret;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 11e014939b74..f9ce9d3d8b2b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -67,6 +67,7 @@ struct fscrypt_info;
 struct fscrypt_operations;
 struct fs_context;
 struct fs_parameter_spec;
+struct mnt_namespace;
 
 extern void __init inode_init(void);
 extern void __init inode_init_early(void);
@@ -3392,6 +3393,9 @@ extern void setattr_copy(struct inode *inode, const struct iattr *attr);
 
 extern int file_update_time(struct file *file);
 
+extern struct mount *mnt_list_next(struct mnt_namespace *ns,
+				   struct list_head *p);
+
 static inline bool vma_is_dax(const struct vm_area_struct *vma)
 {
 	return vma->vm_file && IS_DAX(vma->vm_file->f_mapping->host);
-- 
2.31.1



More information about the Devel mailing list