From: GuLingguang <liu83783@gmail.com>
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, containers@lists.linux.dev,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>,
"Eric W . Biederman" <ebiederm@xmission.com>,
Aleksa Sarai <cyphar@cyphar.com>,
Alexey Gladkov <legion@kernel.org>,
"Serge E . Hallyn" <serge@hallyn.com>,
GuLingguang <liu83783@gmail.com>
Subject: [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
Date: Sat, 8 Aug 2026 21:23:09 +0800 [thread overview]
Message-ID: <20260808132309.35924-1-liu83783@gmail.com> (raw)
Hi all,
I have a question about the child-mount check in mnt_already_visible()
in fs/namespace.c, and I would like to understand the intended
invariant before proposing anything.
Background
The check considers an existing proc mount "not fully visible" when
it has a locked child mount whose mountpoint is not a permanently
empty directory:
list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
struct inode *inode = child->mnt_mountpoint->d_inode;
/* Only worry about locked mounts */
if (!(child->mnt.mnt_flags & MNT_LOCKED))
continue;
/* Is the directory permanently empty? */
if (!is_empty_dir_inode(inode))
goto next;
}
is_empty_dir_inode() returns false for regular files, so a locked
file mount under /proc (e.g. /proc/uptime) makes the whole proc mount
"not fully visible", and mounting a fresh proc instance inside a user
namespace is rejected with EPERM:
bwrap: Can't mount proc on /newroot/proc: Operation not permitted
Real-world impact
This affects established workloads:
* lxcfs (since 2014) overmounts /proc/meminfo and /proc/uptime with
FUSE files; lxc reported in March 2016 that this blocked running
an unprivileged container inside a privileged one
(LKML: "user namespace and fully visible proc and sys mounts").
* systemd-nspawn can mask paths under /proc (via --inaccessible=,
overmounting them with inaccessible placeholder nodes);
flatpak/bwrap inside the container then fails with the EPERM
above (systemd issue #34226, still open).
* droidspaces virtualizes /proc/uptime and /proc/loadavg the same
way today.
* Kubernetes works around mount_too_revealing() by mounting proc
from an empty pid namespace (noted in the 2025 procfs pidns API
series, merge 46582a15c174).
The invariant
The check's stated purpose, in Eric Biederman's own words
(commit 7236c85e1be5), is that fresh mounts of proc and sysfs must
give the mounter:
"no more access to proc and sysfs than if they could have
by creating a bind mount"
The original commit (e51db73532955) phrased it as verifying that
"the mounted filesystem is not covered in any significant way".
For a regular-file mountpoint, does a fresh proc mount violate this
invariant? It seems not, on three counts:
1. Content. The only thing a fresh mount reveals beyond the covered
file is the kernel-generated value of that file, which is already
reachable through other means -- e.g. the real uptime is available
from /proc/stat's btime and from the uptime(2) syscall, which are
not affected by the overmount. No new information becomes
accessible.
2. Structure. A file mountpoint never covers a directory tree, so
the directory hierarchy of the fresh mount matches what a bind
mount of the existing proc would show.
3. Permissions. The files themselves remain subject to their own
permission checks; a fresh mount does not bypass them.
(One theoretical caveat: an overmount could in principle replace
a proc file with a bind of a less permissive file (e.g. mode
0600), which a fresh mount would undo, potentially giving
non-root users in the namespace access they did not have before.
I am not aware of any real deployment doing this -- the overmounts
I know of virtualize read-only values such as uptime/loadavg/
meminfo with unchanged permissions -- but I would like the
maintainers' view on whether this caveat is a concern.)
Directory mountpoints are a different matter: a locked directory
mount can hide an entire subtree (hidepid-style masking), which is
what the check is designed to catch. The question is whether file
mountpoints belong in the same determination.
Historical record
The behaviour for file mountpoints has been unchanged since the check
was introduced in 2013 (rejected then, rejected now), and I could not
find any record -- commit message, mailing list discussion, or code
comment -- in which file mountpoints were discussed. For example,
the commit message of the 2015 rewrite (7236c85e1be5) speaks only of
directories. If the rejection of file mountpoints is intentional,
could you point to where that intention was recorded?
Related upstream work
The check was relaxed earlier this year for restricted proc variants
(subset=pid) on the grounds that "almost all container
implementations override part of procfs to hide certain directories"
(merge a76640171b29, April 2026), and the 2016 LKML thread already
discussed the same problem, ending with a userspace workaround rather
than a kernel change.
Questions
1. Should regular-file mountpoints participate in the "not fully
visible" determination at all?
2. Is the invariant the check protects about the presence/type of
mounts on proc, or about the visibility of procfs's directory
tree?
3. Is there a recorded intent for rejecting file mountpoints, and
does it still apply given the above?
I am deliberately not proposing an implementation yet; I would like
to understand the intended invariant first.
Thanks,
GuLingguang <liu83783@gmail.com>
next reply other threads:[~2026-08-08 13:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-08 13:23 GuLingguang [this message]
2026-08-11 9:16 ` [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check? Alexey Gladkov
2026-08-11 9:19 ` Christian Brauner
2026-08-11 10:49 ` Gu Lingguang
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=20260808132309.35924-1-liu83783@gmail.com \
--to=liu83783@gmail.com \
--cc=brauner@kernel.org \
--cc=containers@lists.linux.dev \
--cc=cyphar@cyphar.com \
--cc=ebiederm@xmission.com \
--cc=legion@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=serge@hallyn.com \
--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