Skip to content

Commit 4a403d7

Browse files
committed
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: 2eea9ce ("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>
1 parent a41dbf5 commit 4a403d7

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

fs/namespace.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,23 +1531,33 @@ static struct mount *mnt_find_id_at_reverse(struct mnt_namespace *ns, u64 mnt_id
15311531
static void *m_start(struct seq_file *m, loff_t *pos)
15321532
{
15331533
struct proc_mounts *p = m->private;
1534+
struct mount *mnt;
15341535

15351536
down_read(&namespace_sem);
15361537

1537-
return mnt_find_id_at(p->ns, *pos);
1538+
mnt = mnt_find_id_at(p->ns, *pos);
1539+
if (mnt)
1540+
*pos = mnt->mnt_id_unique;
1541+
return mnt;
15381542
}
15391543

15401544
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
15411545
{
1542-
struct mount *next = NULL, *mnt = v;
1546+
struct mount *mnt = v;
15431547
struct rb_node *node = rb_next(&mnt->mnt_node);
15441548

1545-
++*pos;
15461549
if (node) {
1547-
next = node_to_mount(node);
1550+
struct mount *next = node_to_mount(node);
15481551
*pos = next->mnt_id_unique;
1552+
return next;
15491553
}
1550-
return next;
1554+
1555+
/*
1556+
* No more mounts. Set pos past current mount's ID so that if
1557+
* iteration restarts, mnt_find_id_at() returns NULL.
1558+
*/
1559+
*pos = mnt->mnt_id_unique + 1;
1560+
return NULL;
15511561
}
15521562

15531563
static void m_stop(struct seq_file *m, void *v)

0 commit comments

Comments
 (0)