From: "Eric W. Biederman" <ebiederm@xmission.com>
To: Andy Lutomirski <luto@amacapital.net>
Cc: Linux FS Devel <linux-fsdevel@vger.kernel.org>,
Linux API <linux-api@vger.kernel.org>
Subject: Re: Accidental mountns/tmpfs API break from 2016?
Date: Mon, 09 Nov 2026 06:05:33 -0600 [thread overview]
Message-ID: <874idq8b1u.fsf@email.froward.int.ebiederm.org> (raw)
In-Reply-To: <87bj82d3ic.fsf@email.froward.int.ebiederm.org> (Eric W. Biederman's message of "Thu, 05 Nov 2026 21:48:11 -0600")
"Eric W. Biederman" <ebiederm@xmission.com> writes:
> Andy Lutomirski <luto@amacapital.net> writes:
>
> On Tue, Nov 3, 2026 at 7:37 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>>
>>> Andy Lutomirski <luto@amacapital.net> writes:
>> Hah, you haven't quite figured out the ridiculous thing I'm doing. :)
>> What I want is a temporary tmpfs that I can create as an unprivileged
>> user. Linux doesn't let me do that directly, so I'm kludging it.
>> Shell transcript, edited for clarity:
>>
>> #### Make a tmpfs, keeping the tool running to keep it alive
>> $ ./temp_shm &
>> [1] 34157
>> /proc/34157/cwd
>>
>> #### cd to the tmpfs, which references it and keeps it alive
>> $ cd /proc/34157/cwd
>>
>> #### Kill the tool, since we're done with it
>> $ fg
>> bin/lktool temp_shm (wd: /workspaces/master)
>> ^C
>>
>> #### cwd is a working tmpfs!
>> $ echo "Look a tmpfs!" >some_file
>>
>> #### and it has no '..', as expected :)
>> $ cd .. # and it has
>> cd: error retrieving current directory: getcwd: cannot access parent
>> directories: No such file or directory
>>
>> This whole workflow runs in the init userns and the init mountns,
>> which is exactly what I wanted. And now I have a tmpfs that I can use
>> to run my test suite unprivileged to test some cool code that *needs*
>> a tmpfs. (Yes, I could probably use /dev/shm, but that's messy and I
>> don't want to.)
>>
>> I'm not actually banging this out in shell, but I am running literally
>> the C++ code I posted as a subprocess called by my test harness.
>>
>> The user creating files is not in the mountns or the userns, by
>> design.
This reminded me of something so I looked it up.
Then I re-read your sample code.
And I think you have asked the wrong question.
The question should be why does fsopen test may_mount? As it doesn't
mount the filesystem at that point.
Your example code could just do:
int cmd_temp_shm(int argc, char **) {
if (argc != 1) {
fprintf(stderr, "Usage: lktool temp_shm\n");
return 1;
}
try {
OwnedFd context{static_cast<int>(syscall(SYS_fsopen, "tmpfs",
FSOPEN_CLOEXEC))};
Check(context.fd, "fsopen tmpfs");
Check(syscall(SYS_fsconfig, context.fd, FSCONFIG_CMD_CREATE,
nullptr, nullptr, 0),
"fsconfig create tmpfs");
OwnedFd mount{static_cast<int>(syscall(SYS_fsmount,
context.fd, FSMOUNT_CLOEXEC, 0))};
Check(mount.fd, "fsmount tmpfs");
Check(fchdir(mount.fd), "fchdir tmpfs");
// The detached mount is kept alive by cwd and the mount descriptor.
// No mount is attached to the inherited filesystem hierarchy.
std::string path = "/proc/" + std::to_string(getpid()) + "/cwd";
path.push_back('\0');
WriteAll(STDOUT_FILENO, path);
for (;;)
pause();
} catch (const std::system_error &e) {
fprintf(stderr, "lktool temp_shm: %s\n", e.what());
return 1;
}
}
It would not surprise me if in practice there are assumptions that have
to be worked through to allow that to work, but it seems a perfectly
reasonable thing to do on first glance. Especially since there are
useful application of doing that.
The really interesting piece to make it through is FSCONFIG_CMD_CREATE.
I think that permission check and the logic there are what needs to
be modified to make it work without a user namespace.
There is also fsopen which has that has a may_mount check that seems
to serve not immediately discernible purpose.
The part that can obviously break pre-existing privileged applications
is the mount_move that attaches the mount to an existing mount
namespace, and that is obviously not allowed. That definitely can not
be allowed.
The unprivileged mounter without a usernamespace at that point won't
have the ability to reconfigure the filesystem. So the attack vectors
I was worried about earlier don't seem to apply.
There is a practical question is the additional attack surface and
maintenance burden worth it.
At a quick look it seems reasonable for a handful of filesystems like
tmpfs to allow mounting without first creating a user namespace.
There might even be an argument in there somewhere for allowing
privilege separation of the mount command.
In summary. At first glance it seems reasonable to allow fsopen,
FSCONFIG_CMD_CREATE, fsmount on select filesystems without privilege and
without a user namespace.
Eric
prev parent reply other threads:[~2026-11-09 12:05 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 19:58 Accidental mountns/tmpfs API break from 2016? Andy Lutomirski
2026-11-04 3:37 ` Eric W. Biederman
2026-11-04 4:02 ` Andy Lutomirski
2026-11-06 3:48 ` Eric W. Biederman
2026-11-09 12:05 ` Eric W. Biederman [this message]
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=874idq8b1u.fsf@email.froward.int.ebiederm.org \
--to=ebiederm@xmission.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=luto@amacapital.net \
/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