From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
Miklos Szeredi <mszeredi@redhat.com>,
Jeff Layton <jlayton@kernel.org>, shaos <shawnq1@163.com>,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
"Christian Brauner (Amutable)" <brauner@kernel.org>
Subject: [PATCH 3/6] listmount: don't wrap around with a U64_MAX cursor
Date: Wed, 21 Oct 2026 13:46:56 +0200 [thread overview]
Message-ID: <20261021-work-mount-statmount_listns_fixes-v1-3-8917a4c1bd14@kernel.org> (raw)
In-Reply-To: <20261021-work-mount-statmount_listns_fixes-v1-0-8917a4c1bd14@kernel.org>
do_listmount() takes the last mount id the caller saw and looks up the
first mount after it by searching for last_mnt_id + 1. With U64_MAX
that wraps around to zero and the search finds the first mount in the
namespace. So a cursor at the largest possible id restarts the listing
from the beginning instead of ending it. A cursor of U64_MAX - 1
correctly returns nothing.
No mount will ever have that id. Mount ids come from a counter that
starts at MNT_UNIQUE_ID_OFFSET + 1 and a caller that only feeds back
ids it got from us can't hit this. It's still wrong. Nothing can come
after the largest possible id so return no entries for it, just like
for any other cursor past the last mount.
The reverse direction isn't affected. A cursor of zero is special-cased
and anything else is larger than MNT_UNIQUE_ID_OFFSET so last_mnt_id - 1
can't underflow.
Reproducer, unprivileged:
#define _GNU_SOURCE
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#define LSMT_ROOT 0xffffffffffffffffULL
struct mnt_id_req {
uint32_t size, mnt_ns_fd;
uint64_t mnt_id, param, mnt_ns_id;
};
static void list(uint64_t cursor)
{
struct mnt_id_req req = {
.size = sizeof(req), .mnt_id = LSMT_ROOT, .param = cursor,
};
uint64_t ids[8];
long ret;
errno = 0;
ret = syscall(__NR_listmount, &req, ids, 8, 0);
printf("cursor %llu: ret %ld errno %d", (unsigned long long)cursor,
ret, errno);
for (long i = 0; i < ret && i < 1; i++)
printf("%s%llu", i ? "," : " ids ", (unsigned long long)ids[i]);
printf("%s\n", ret > 1 ? ",..." : "");
}
int main(void)
{
list(0);
list(UINT64_MAX - 1);
list(UINT64_MAX);
return 0;
}
Before, on 7.3.0-rc7-00252-g4e3259b08c54 (vfs.fixes) in a VM:
cursor 0: ret 5 errno 0 ids 2147483651,...
cursor 18446744073709551614: ret 0 errno 0
cursor 18446744073709551615: ret 5 errno 0 ids 2147483651,...
After:
cursor 0: ret 5 errno 0 ids 2147483651,...
cursor 18446744073709551614: ret 0 errno 0
cursor 18446744073709551615: ret 0 errno 0
Reported-by: shaos <shawnq1@163.com>
Link: https://lore.kernel.org/r/20261020110732.959552-1-shawnq1@163.com
Fixes: b4c2bea8ceaa ("add listmount(2) syscall")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/namespace.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/namespace.c b/fs/namespace.c
index 6c9c0cdbe890..dd60123a0cb0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -6253,6 +6253,8 @@ static ssize_t do_listmount(struct klistmount *kls, bool reverse)
} else {
if (reverse)
first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);
+ else if (last_mnt_id == U64_MAX)
+ first = NULL; /* nothing comes after the largest id */
else
first = mnt_find_id_at(ns, last_mnt_id + 1);
}
--
2.53.0
next prev parent reply other threads:[~2026-10-21 11:47 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 11:46 [PATCH 0/6] fs: fixes for statmount() short buffers and listmount()/listns() cursors Christian Brauner
2026-10-21 11:46 ` [PATCH 1/6] statmount: don't copy the reserved empty string past the buffer Christian Brauner
2026-10-21 11:52 ` Jeff Layton
2026-10-21 15:18 ` Jan Kara
2026-10-21 11:46 ` [PATCH 2/6] selftests/filesystems: check short buffers for statmount() strings Christian Brauner
2026-10-21 11:46 ` Christian Brauner [this message]
2026-10-21 11:52 ` [PATCH 3/6] listmount: don't wrap around with a U64_MAX cursor Jeff Layton
2026-10-21 15:25 ` Jan Kara
2026-10-21 11:46 ` [PATCH 4/6] selftests/filesystems: check listmount() " Christian Brauner
2026-10-21 11:46 ` [PATCH 5/6] listns: don't wrap around " Christian Brauner
2026-10-21 11:55 ` Jeff Layton
2026-10-21 15:29 ` Jan Kara
2026-10-21 11:46 ` [PATCH 6/6] selftests/namespaces: check listns() " Christian Brauner
2026-10-21 13:18 ` [PATCH 0/6] fs: fixes for statmount() short buffers and listmount()/listns() cursors Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261021-work-mount-statmount_listns_fixes-v1-3-8917a4c1bd14@kernel.org \
--to=brauner@kernel.org \
--cc=jack@suse.cz \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mszeredi@redhat.com \
--cc=shawnq1@163.com \
--cc=stable@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®