* [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id
@ 2026-07-31 9:02 Zizhi Wo
2026-08-06 6:11 ` Zizhi Wo
0 siblings, 1 reply; 4+ messages in thread
From: Zizhi Wo @ 2026-07-31 9:02 UTC (permalink / raw)
To: zlang, brauner, fstests; +Cc: yangerkun, chengzhihao1, wozizhi
From: Zizhi Wo <wozizhi@huawei.com>
Kernel commit 539dce114465 ("fs: refuse O_TMPFILE creation with an
unmapped fsuid or fsgid") made vfs_tmpfile() return -EOVERFLOW when the
caller's fsuid/fsgid has no mapping in the filesystem's user namespace
after applying the mount's idmapping. This is a no-op on non-idmapped
mounts and only takes effect on an idmapped mount that does not map the
caller.
The idmapped-mount testcases behind generic/696 and generic/697 build an
idmapping (e.g. "0 10000 10000") that covers host uid 10000-19999 but
not uid 0, then call openat_tmpfile_supported() from the parent process
that is still real root (fsuid 0). The probe now gets -EOVERFLOW, falls
into the log_errno() branch, and prints
utils.c: 928: openat_tmpfile_supported - Value too large for defined \
data type - failure: create
to stderr. Both testcases expect "Silence is golden", so this spurious
output fails them, even though the kernel behavior is correct and the
testcases' own assertions all pass.
Move each openat_tmpfile_supported() call into the child, after
switch_ids()/switch_userns(), so it probes with the mapped identity the
tmpfile section uses. Silencing EOVERFLOW in openat_tmpfile_supported()
would make it indistinguishable whether the idmapping genuinely has no
mapping for any caller, or the probe just ran in the unmapped parent before
the switch.
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
---
src/vfs/idmapped-mounts.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/vfs/idmapped-mounts.c b/src/vfs/idmapped-mounts.c
index ed9992f9..bfbe9042 100644
--- a/src/vfs/idmapped-mounts.c
+++ b/src/vfs/idmapped-mounts.c
@@ -3838,8 +3838,6 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -3849,6 +3847,8 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
if (!switch_ids(10000, 11000))
die("failure: switch fsids");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
@@ -4014,8 +4014,6 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -4025,6 +4023,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
@@ -4133,6 +4133,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
if (!caps_down_fsetid())
die("failure: caps_down_fsetid");
@@ -4257,6 +4259,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
if (!switch_userns(attr.userns_fd, 0, 1000, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
if (!caps_down_fsetid())
die("failure: caps_down_fsetid");
@@ -7733,8 +7737,6 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -7752,6 +7754,8 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
if (!switch_ids(10000, 11000))
die("failure: switch fsids");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
@@ -7947,8 +7951,6 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
/*
* Below we verify that setgid inheritance for a newly created file or
* directory works correctly. As part of this we need to verify that
@@ -7984,6 +7986,8 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
if (!caps_down_fsetid())
die("failure: caps_down_fsetid");
@@ -8181,8 +8185,6 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -8207,6 +8209,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
if (!switch_ids(10000, 11000))
die("failure: switch fsids");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
@@ -8342,6 +8346,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
if (!switch_ids(10000, 11000))
die("failure: switch fsids");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
@@ -8536,8 +8542,6 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
goto out;
}
- supported = openat_tmpfile_supported(open_tree_fd);
-
/*
* Below we verify that setgid inheritance for a newly created file or
* directory works correctly. As part of this we need to verify that
@@ -8580,6 +8584,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
if (!caps_down_fsetid())
die("failure: caps_down_fsetid");
@@ -8723,6 +8729,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ supported = openat_tmpfile_supported(open_tree_fd);
+
if (!caps_down_fsetid())
die("failure: caps_down_fsetid");
--
2.52.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id
2026-07-31 9:02 [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id Zizhi Wo
@ 2026-08-06 6:11 ` Zizhi Wo
2026-08-10 20:40 ` Zorro Lang
0 siblings, 1 reply; 4+ messages in thread
From: Zizhi Wo @ 2026-08-06 6:11 UTC (permalink / raw)
To: Zizhi Wo, zlang, brauner, fstests; +Cc: yangerkun, chengzhihao1
friendly ping...
在 2026/7/31 17:02, Zizhi Wo 写道:
> From: Zizhi Wo <wozizhi@huawei.com>
>
> Kernel commit 539dce114465 ("fs: refuse O_TMPFILE creation with an
> unmapped fsuid or fsgid") made vfs_tmpfile() return -EOVERFLOW when the
> caller's fsuid/fsgid has no mapping in the filesystem's user namespace
> after applying the mount's idmapping. This is a no-op on non-idmapped
> mounts and only takes effect on an idmapped mount that does not map the
> caller.
>
> The idmapped-mount testcases behind generic/696 and generic/697 build an
> idmapping (e.g. "0 10000 10000") that covers host uid 10000-19999 but
> not uid 0, then call openat_tmpfile_supported() from the parent process
> that is still real root (fsuid 0). The probe now gets -EOVERFLOW, falls
> into the log_errno() branch, and prints
>
> utils.c: 928: openat_tmpfile_supported - Value too large for defined \
> data type - failure: create
>
> to stderr. Both testcases expect "Silence is golden", so this spurious
> output fails them, even though the kernel behavior is correct and the
> testcases' own assertions all pass.
>
> Move each openat_tmpfile_supported() call into the child, after
> switch_ids()/switch_userns(), so it probes with the mapped identity the
> tmpfile section uses. Silencing EOVERFLOW in openat_tmpfile_supported()
> would make it indistinguishable whether the idmapping genuinely has no
> mapping for any caller, or the probe just ran in the unmapped parent before
> the switch.
>
> Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
> ---
> src/vfs/idmapped-mounts.c | 32 ++++++++++++++++++++------------
> 1 file changed, 20 insertions(+), 12 deletions(-)
>
> diff --git a/src/vfs/idmapped-mounts.c b/src/vfs/idmapped-mounts.c
> index ed9992f9..bfbe9042 100644
> --- a/src/vfs/idmapped-mounts.c
> +++ b/src/vfs/idmapped-mounts.c
> @@ -3838,8 +3838,6 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> pid = fork();
> if (pid < 0) {
> log_stderr("failure: fork");
> @@ -3849,6 +3847,8 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
> if (!switch_ids(10000, 11000))
> die("failure: switch fsids");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> /* create regular file via open() */
> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> if (file1_fd < 0)
> @@ -4014,8 +4014,6 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> pid = fork();
> if (pid < 0) {
> log_stderr("failure: fork");
> @@ -4025,6 +4023,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> if (!switch_userns(attr.userns_fd, 0, 0, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> /* create regular file via open() */
> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> if (file1_fd < 0)
> @@ -4133,6 +4133,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> if (!switch_userns(attr.userns_fd, 0, 0, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> if (!caps_down_fsetid())
> die("failure: caps_down_fsetid");
>
> @@ -4257,6 +4259,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> if (!switch_userns(attr.userns_fd, 0, 1000, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> if (!caps_down_fsetid())
> die("failure: caps_down_fsetid");
>
> @@ -7733,8 +7737,6 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> pid = fork();
> if (pid < 0) {
> log_stderr("failure: fork");
> @@ -7752,6 +7754,8 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
> if (!switch_ids(10000, 11000))
> die("failure: switch fsids");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> /* create regular file via open() */
> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> if (file1_fd < 0)
> @@ -7947,8 +7951,6 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> /*
> * Below we verify that setgid inheritance for a newly created file or
> * directory works correctly. As part of this we need to verify that
> @@ -7984,6 +7986,8 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
> if (!switch_userns(attr.userns_fd, 0, 0, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> if (!caps_down_fsetid())
> die("failure: caps_down_fsetid");
>
> @@ -8181,8 +8185,6 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> pid = fork();
> if (pid < 0) {
> log_stderr("failure: fork");
> @@ -8207,6 +8209,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> if (!switch_ids(10000, 11000))
> die("failure: switch fsids");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> /* create regular file via open() */
> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> if (file1_fd < 0)
> @@ -8342,6 +8346,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> if (!switch_ids(10000, 11000))
> die("failure: switch fsids");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> /* create regular file via open() */
> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> if (file1_fd < 0)
> @@ -8536,8 +8542,6 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> goto out;
> }
>
> - supported = openat_tmpfile_supported(open_tree_fd);
> -
> /*
> * Below we verify that setgid inheritance for a newly created file or
> * directory works correctly. As part of this we need to verify that
> @@ -8580,6 +8584,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> if (!switch_userns(attr.userns_fd, 0, 0, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> if (!caps_down_fsetid())
> die("failure: caps_down_fsetid");
>
> @@ -8723,6 +8729,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> if (!switch_userns(attr.userns_fd, 0, 0, false))
> die("failure: switch_userns");
>
> + supported = openat_tmpfile_supported(open_tree_fd);
> +
> if (!caps_down_fsetid())
> die("failure: caps_down_fsetid");
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id
2026-08-06 6:11 ` Zizhi Wo
@ 2026-08-10 20:40 ` Zorro Lang
2026-08-11 1:35 ` Zizhi Wo
0 siblings, 1 reply; 4+ messages in thread
From: Zorro Lang @ 2026-08-10 20:40 UTC (permalink / raw)
To: Zizhi Wo, Christian Brauner; +Cc: fstests, yangerkun, chengzhihao1
On Thu, Aug 06, 2026 at 02:11:55PM +0800, Zizhi Wo wrote:
> friendly ping...
Hi Zizhi, actually I'm waiting for the fix from vfs list.
Hi Christian,
Could you please take a look at this issue? Quite a few people have submitted
patches trying to fix this test issue. Given that you are the authority on
this topic and previously sent a patchset [1] to fix this kind of issue, I think
accepting your patch would be the best approach to stay aligned with upstream
VFS. Christoph also metioned that [2] last time. I don't want to make this issue
fixing any more complicated. Could you please provide your review point or
rebase your fix on the latest fstests for-next branch, we'll review it ASAP.
[1]
https://lore.kernel.org/fstests/20260615-overlay-idmapped-vfstest-v1-1-c6b3b2228092@kernel.org/
[2]
https://lore.kernel.org/fstests/amCGrQi2sCcgSgHL@infradead.org/
Thanks,
Zorro
>
> 在 2026/7/31 17:02, Zizhi Wo 写道:
> > From: Zizhi Wo <wozizhi@huawei.com>
> >
> > Kernel commit 539dce114465 ("fs: refuse O_TMPFILE creation with an
> > unmapped fsuid or fsgid") made vfs_tmpfile() return -EOVERFLOW when the
> > caller's fsuid/fsgid has no mapping in the filesystem's user namespace
> > after applying the mount's idmapping. This is a no-op on non-idmapped
> > mounts and only takes effect on an idmapped mount that does not map the
> > caller.
> >
> > The idmapped-mount testcases behind generic/696 and generic/697 build an
> > idmapping (e.g. "0 10000 10000") that covers host uid 10000-19999 but
> > not uid 0, then call openat_tmpfile_supported() from the parent process
> > that is still real root (fsuid 0). The probe now gets -EOVERFLOW, falls
> > into the log_errno() branch, and prints
> >
> > utils.c: 928: openat_tmpfile_supported - Value too large for defined \
> > data type - failure: create
> >
> > to stderr. Both testcases expect "Silence is golden", so this spurious
> > output fails them, even though the kernel behavior is correct and the
> > testcases' own assertions all pass.
> >
> > Move each openat_tmpfile_supported() call into the child, after
> > switch_ids()/switch_userns(), so it probes with the mapped identity the
> > tmpfile section uses. Silencing EOVERFLOW in openat_tmpfile_supported()
> > would make it indistinguishable whether the idmapping genuinely has no
> > mapping for any caller, or the probe just ran in the unmapped parent before
> > the switch.
> >
> > Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
> > ---
> > src/vfs/idmapped-mounts.c | 32 ++++++++++++++++++++------------
> > 1 file changed, 20 insertions(+), 12 deletions(-)
> >
> > diff --git a/src/vfs/idmapped-mounts.c b/src/vfs/idmapped-mounts.c
> > index ed9992f9..bfbe9042 100644
> > --- a/src/vfs/idmapped-mounts.c
> > +++ b/src/vfs/idmapped-mounts.c
> > @@ -3838,8 +3838,6 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > pid = fork();
> > if (pid < 0) {
> > log_stderr("failure: fork");
> > @@ -3849,6 +3847,8 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
> > if (!switch_ids(10000, 11000))
> > die("failure: switch fsids");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > /* create regular file via open() */
> > file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> > if (file1_fd < 0)
> > @@ -4014,8 +4014,6 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > pid = fork();
> > if (pid < 0) {
> > log_stderr("failure: fork");
> > @@ -4025,6 +4023,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> > if (!switch_userns(attr.userns_fd, 0, 0, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > /* create regular file via open() */
> > file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> > if (file1_fd < 0)
> > @@ -4133,6 +4133,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> > if (!switch_userns(attr.userns_fd, 0, 0, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > if (!caps_down_fsetid())
> > die("failure: caps_down_fsetid");
> > @@ -4257,6 +4259,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
> > if (!switch_userns(attr.userns_fd, 0, 1000, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > if (!caps_down_fsetid())
> > die("failure: caps_down_fsetid");
> > @@ -7733,8 +7737,6 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > pid = fork();
> > if (pid < 0) {
> > log_stderr("failure: fork");
> > @@ -7752,6 +7754,8 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
> > if (!switch_ids(10000, 11000))
> > die("failure: switch fsids");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > /* create regular file via open() */
> > file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> > if (file1_fd < 0)
> > @@ -7947,8 +7951,6 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > /*
> > * Below we verify that setgid inheritance for a newly created file or
> > * directory works correctly. As part of this we need to verify that
> > @@ -7984,6 +7986,8 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
> > if (!switch_userns(attr.userns_fd, 0, 0, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > if (!caps_down_fsetid())
> > die("failure: caps_down_fsetid");
> > @@ -8181,8 +8185,6 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > pid = fork();
> > if (pid < 0) {
> > log_stderr("failure: fork");
> > @@ -8207,6 +8209,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> > if (!switch_ids(10000, 11000))
> > die("failure: switch fsids");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > /* create regular file via open() */
> > file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> > if (file1_fd < 0)
> > @@ -8342,6 +8346,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
> > if (!switch_ids(10000, 11000))
> > die("failure: switch fsids");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > /* create regular file via open() */
> > file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> > if (file1_fd < 0)
> > @@ -8536,8 +8542,6 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> > goto out;
> > }
> > - supported = openat_tmpfile_supported(open_tree_fd);
> > -
> > /*
> > * Below we verify that setgid inheritance for a newly created file or
> > * directory works correctly. As part of this we need to verify that
> > @@ -8580,6 +8584,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> > if (!switch_userns(attr.userns_fd, 0, 0, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > if (!caps_down_fsetid())
> > die("failure: caps_down_fsetid");
> > @@ -8723,6 +8729,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
> > if (!switch_userns(attr.userns_fd, 0, 0, false))
> > die("failure: switch_userns");
> > + supported = openat_tmpfile_supported(open_tree_fd);
> > +
> > if (!caps_down_fsetid())
> > die("failure: caps_down_fsetid");
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id
2026-08-10 20:40 ` Zorro Lang
@ 2026-08-11 1:35 ` Zizhi Wo
0 siblings, 0 replies; 4+ messages in thread
From: Zizhi Wo @ 2026-08-11 1:35 UTC (permalink / raw)
To: Zizhi Wo, Christian Brauner, fstests, yangerkun, chengzhihao1
在 2026/8/11 4:40, Zorro Lang 写道:
> On Thu, Aug 06, 2026 at 02:11:55PM +0800, Zizhi Wo wrote:
>> friendly ping...
>
> Hi Zizhi, actually I'm waiting for the fix from vfs list.
Sorry, I hadn't noticed that this issue had already been discussed and
fixed by the community. Thanks for pointing it out.
Thanks,
Zizhi Wo
>
> Hi Christian,
>
> Could you please take a look at this issue? Quite a few people have submitted
> patches trying to fix this test issue. Given that you are the authority on
> this topic and previously sent a patchset [1] to fix this kind of issue, I think
> accepting your patch would be the best approach to stay aligned with upstream
> VFS. Christoph also metioned that [2] last time. I don't want to make this issue
> fixing any more complicated. Could you please provide your review point or
> rebase your fix on the latest fstests for-next branch, we'll review it ASAP.
>
> [1]
> https://lore.kernel.org/fstests/20260615-overlay-idmapped-vfstest-v1-1-c6b3b2228092@kernel.org/
>
> [2]
> https://lore.kernel.org/fstests/amCGrQi2sCcgSgHL@infradead.org/
>
> Thanks,
> Zorro
>
>>
>> 在 2026/7/31 17:02, Zizhi Wo 写道:
>>> From: Zizhi Wo <wozizhi@huawei.com>
>>>
>>> Kernel commit 539dce114465 ("fs: refuse O_TMPFILE creation with an
>>> unmapped fsuid or fsgid") made vfs_tmpfile() return -EOVERFLOW when the
>>> caller's fsuid/fsgid has no mapping in the filesystem's user namespace
>>> after applying the mount's idmapping. This is a no-op on non-idmapped
>>> mounts and only takes effect on an idmapped mount that does not map the
>>> caller.
>>>
>>> The idmapped-mount testcases behind generic/696 and generic/697 build an
>>> idmapping (e.g. "0 10000 10000") that covers host uid 10000-19999 but
>>> not uid 0, then call openat_tmpfile_supported() from the parent process
>>> that is still real root (fsuid 0). The probe now gets -EOVERFLOW, falls
>>> into the log_errno() branch, and prints
>>>
>>> utils.c: 928: openat_tmpfile_supported - Value too large for defined \
>>> data type - failure: create
>>>
>>> to stderr. Both testcases expect "Silence is golden", so this spurious
>>> output fails them, even though the kernel behavior is correct and the
>>> testcases' own assertions all pass.
>>>
>>> Move each openat_tmpfile_supported() call into the child, after
>>> switch_ids()/switch_userns(), so it probes with the mapped identity the
>>> tmpfile section uses. Silencing EOVERFLOW in openat_tmpfile_supported()
>>> would make it indistinguishable whether the idmapping genuinely has no
>>> mapping for any caller, or the probe just ran in the unmapped parent before
>>> the switch.
>>>
>>> Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
>>> ---
>>> src/vfs/idmapped-mounts.c | 32 ++++++++++++++++++++------------
>>> 1 file changed, 20 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/src/vfs/idmapped-mounts.c b/src/vfs/idmapped-mounts.c
>>> index ed9992f9..bfbe9042 100644
>>> --- a/src/vfs/idmapped-mounts.c
>>> +++ b/src/vfs/idmapped-mounts.c
>>> @@ -3838,8 +3838,6 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> pid = fork();
>>> if (pid < 0) {
>>> log_stderr("failure: fork");
>>> @@ -3849,6 +3847,8 @@ int tcore_setgid_create_idmapped(const struct vfstest_info *info)
>>> if (!switch_ids(10000, 11000))
>>> die("failure: switch fsids");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> /* create regular file via open() */
>>> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>>> if (file1_fd < 0)
>>> @@ -4014,8 +4014,6 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> pid = fork();
>>> if (pid < 0) {
>>> log_stderr("failure: fork");
>>> @@ -4025,6 +4023,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
>>> if (!switch_userns(attr.userns_fd, 0, 0, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> /* create regular file via open() */
>>> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>>> if (file1_fd < 0)
>>> @@ -4133,6 +4133,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
>>> if (!switch_userns(attr.userns_fd, 0, 0, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> if (!caps_down_fsetid())
>>> die("failure: caps_down_fsetid");
>>> @@ -4257,6 +4259,8 @@ int tcore_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
>>> if (!switch_userns(attr.userns_fd, 0, 1000, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> if (!caps_down_fsetid())
>>> die("failure: caps_down_fsetid");
>>> @@ -7733,8 +7737,6 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> pid = fork();
>>> if (pid < 0) {
>>> log_stderr("failure: fork");
>>> @@ -7752,6 +7754,8 @@ static int setgid_create_umask_idmapped(const struct vfstest_info *info)
>>> if (!switch_ids(10000, 11000))
>>> die("failure: switch fsids");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> /* create regular file via open() */
>>> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>>> if (file1_fd < 0)
>>> @@ -7947,8 +7951,6 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> /*
>>> * Below we verify that setgid inheritance for a newly created file or
>>> * directory works correctly. As part of this we need to verify that
>>> @@ -7984,6 +7986,8 @@ static int setgid_create_umask_idmapped_in_userns(const struct vfstest_info *inf
>>> if (!switch_userns(attr.userns_fd, 0, 0, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> if (!caps_down_fsetid())
>>> die("failure: caps_down_fsetid");
>>> @@ -8181,8 +8185,6 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> pid = fork();
>>> if (pid < 0) {
>>> log_stderr("failure: fork");
>>> @@ -8207,6 +8209,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
>>> if (!switch_ids(10000, 11000))
>>> die("failure: switch fsids");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> /* create regular file via open() */
>>> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>>> if (file1_fd < 0)
>>> @@ -8342,6 +8346,8 @@ static int setgid_create_acl_idmapped(const struct vfstest_info *info)
>>> if (!switch_ids(10000, 11000))
>>> die("failure: switch fsids");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> /* create regular file via open() */
>>> file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>>> if (file1_fd < 0)
>>> @@ -8536,8 +8542,6 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
>>> goto out;
>>> }
>>> - supported = openat_tmpfile_supported(open_tree_fd);
>>> -
>>> /*
>>> * Below we verify that setgid inheritance for a newly created file or
>>> * directory works correctly. As part of this we need to verify that
>>> @@ -8580,6 +8584,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
>>> if (!switch_userns(attr.userns_fd, 0, 0, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> if (!caps_down_fsetid())
>>> die("failure: caps_down_fsetid");
>>> @@ -8723,6 +8729,8 @@ static int setgid_create_acl_idmapped_in_userns(const struct vfstest_info *info)
>>> if (!switch_userns(attr.userns_fd, 0, 0, false))
>>> die("failure: switch_userns");
>>> + supported = openat_tmpfile_supported(open_tree_fd);
>>> +
>>> if (!caps_down_fsetid())
>>> die("failure: caps_down_fsetid");
>>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-11 1:35 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31 9:02 [PATCH] idmapped-mounts: probe O_TMPFILE support with the caller's mapped id Zizhi Wo
2026-08-06 6:11 ` Zizhi Wo
2026-08-10 20:40 ` Zorro Lang
2026-08-11 1:35 ` Zizhi Wo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.