]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
namespace: fix proc mount iteration
authorChristian Brauner <brauner@kernel.org>
Thu, 29 Jan 2026 13:52:22 +0000 (14:52 +0100)
committerChristian Brauner <brauner@kernel.org>
Wed, 18 Feb 2026 13:04:42 +0000 (14:04 +0100)
The m->index isn't updated when m->show() overflows and retains its
value before the current mount causing a restart to start at the same
value. If that happens in short order to due a quickly expanding mount
table this would cause the same mount to be shown again and again.

Ensure that *pos always equals the mount id of the mount that was
returned by start/next. On restart after overflow mnt_find_id_at(*pos)
finds the exact mount. This should avoid duplicates, avoid skips and
should handle concurrent modification just fine.

Cc: <stable@vger.kernel.org>
Fixed: 2eea9ce4310d8 ("mounts: keep list of mounts in an rbtree")
Link: https://patch.msgid.link/20260129-geleckt-treuhand-4bb940acacd9@brauner
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/namespace.c

index 022e59afcb5ee70743de9ad7923750dcad66aeab..31483c66ace87d85fc413d4a88b67b2204f3f1a3 100644 (file)
@@ -1531,23 +1531,33 @@ static struct mount *mnt_find_id_at_reverse(struct mnt_namespace *ns, u64 mnt_id
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
        struct proc_mounts *p = m->private;
+       struct mount *mnt;
 
        down_read(&namespace_sem);
 
-       return mnt_find_id_at(p->ns, *pos);
+       mnt = mnt_find_id_at(p->ns, *pos);
+       if (mnt)
+               *pos = mnt->mnt_id_unique;
+       return mnt;
 }
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct mount *next = NULL, *mnt = v;
+       struct mount *mnt = v;
        struct rb_node *node = rb_next(&mnt->mnt_node);
 
-       ++*pos;
        if (node) {
-               next = node_to_mount(node);
+               struct mount *next = node_to_mount(node);
                *pos = next->mnt_id_unique;
+               return next;
        }
-       return next;
+
+       /*
+        * No more mounts. Set pos past current mount's ID so that if
+        * iteration restarts, mnt_find_id_at() returns NULL.
+        */
+       *pos = mnt->mnt_id_unique + 1;
+       return NULL;
 }
 
 static void m_stop(struct seq_file *m, void *v)