Unverified Commit 4a403d7a authored by Christian Brauner's avatar Christian Brauner
Browse files

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: 2eea9ce4 ("mounts: keep list of mounts in an rbtree")
Link: https://patch.msgid.link/20260129-geleckt-treuhand-4bb940acacd9@brauner


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent a41dbf5e
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -1531,25 +1531,35 @@ 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;
	}

	/*
	 * 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)
{
	up_read(&namespace_sem);