summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-01-29 16:52:22 +0300
committerChristian Brauner <brauner@kernel.org>2026-02-18 16:04:42 +0300
commit4a403d7aa9074f527f064ef0806aaab38d14b07c (patch)
tree289a65ccde308209771018468a3bd111a6c135bd
parenta41dbf5e004edbe1260883c43a8bd134d9cb0c1c (diff)
downloadlinux-4a403d7aa9074f527f064ef0806aaab38d14b07c.tar.xz
namespace: fix proc mount iteration
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>
-rw-r--r--fs/namespace.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 022e59afcb5e..31483c66ace8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -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)