* [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
@ 2026-08-08 13:23 GuLingguang
2026-08-11 9:16 ` Alexey Gladkov
2026-08-11 9:19 ` Christian Brauner
0 siblings, 2 replies; 4+ messages in thread
From: GuLingguang @ 2026-08-08 13:23 UTC (permalink / raw)
To: linux-fsdevel
Cc: linux-kernel, containers, Alexander Viro, Christian Brauner,
Eric W . Biederman, Aleksa Sarai, Alexey Gladkov,
Serge E . Hallyn, GuLingguang
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>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
2026-08-08 13:23 [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check? GuLingguang
@ 2026-08-11 9:16 ` Alexey Gladkov
2026-08-11 9:19 ` Christian Brauner
1 sibling, 0 replies; 4+ messages in thread
From: Alexey Gladkov @ 2026-08-11 9:16 UTC (permalink / raw)
To: GuLingguang
Cc: linux-fsdevel, linux-kernel, containers, Alexander Viro,
Christian Brauner, Eric W . Biederman, Aleksa Sarai,
Serge E . Hallyn
On Sat, Aug 08, 2026 at 09:23:09PM +0800, GuLingguang wrote:
> 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.
In this particular case, yes, but that is not true for other files in
/proc.
> 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.)
A new mount may give you access to content that you could potentially have
(due to insecure file permissions), but the container's creators do not
want to grant you access to it.
For example, podman does not allow you to view the contents of /proc/keys
(0444) or /proc/interrupts (0444), which is set to read-only for everyone
on the system.
> 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.
This change was acceptable because the dynamic part of the proc cannot
be overridden by another mount.
> Questions
>
> 1. Should regular-file mountpoints participate in the "not fully
> visible" determination at all?
Yes. Otherwise, you'll break the existing container creation systems like
docker or podman.
> 2. Is the invariant the check protects about the presence/type of
> mounts on proc, or about the visibility of procfs's directory
> tree?
The purpose of the check is described by Eric and applies not only to
directories but also to files.
> 3. Is there a recorded intent for rejecting file mountpoints, and
> does it still apply given the above?
Previously, this behavior existed in practice, and the container
developers were aware of it. And now it's documented.
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.rst#n2440
> I am deliberately not proposing an implementation yet; I would like
> to understand the intended invariant first.
>
> Thanks,
> GuLingguang <liu83783@gmail.com>
>
--
Rgrds, legion
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
2026-08-08 13:23 [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check? GuLingguang
2026-08-11 9:16 ` Alexey Gladkov
@ 2026-08-11 9:19 ` Christian Brauner
2026-08-11 10:49 ` Gu Lingguang
1 sibling, 1 reply; 4+ messages in thread
From: Christian Brauner @ 2026-08-11 9:19 UTC (permalink / raw)
To: GuLingguang
Cc: linux-fsdevel, linux-kernel, containers, Alexander Viro,
Eric W . Biederman, Aleksa Sarai, Alexey Gladkov,
Serge E . Hallyn
On Sat, Aug 08, 2026 at 09:23:09PM +0800, GuLingguang wrote:
> 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.
It's an information leak. Please trim LLM generated questions to the
bare minimum. We don't have time to read essays the whole day...
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
2026-08-11 9:19 ` Christian Brauner
@ 2026-08-11 10:49 ` Gu Lingguang
0 siblings, 0 replies; 4+ messages in thread
From: Gu Lingguang @ 2026-08-11 10:49 UTC (permalink / raw)
To: Alexey Gladkov, Christian Brauner
Cc: linux-fsdevel, linux-kernel, containers, Alexander Viro,
Eric W . Biederman, Aleksa Sarai, Serge E . Hallyn, Gu Lingguang
Thanks to both of you for the replies.
@legion: The /proc/keys and /proc/interrupts case you raised is one
I missed, and it shows that a new mount can grant access that the
container's creators do not want to grant. I withdraw the suggestion.
@Brauner: you're right, and I apologize for the length. I'll keep
future questions to the bare minimum.
Thanks,
Gu Lingguang
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-11 10:49 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-08 13:23 [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check? GuLingguang
2026-08-11 9:16 ` Alexey Gladkov
2026-08-11 9:19 ` Christian Brauner
2026-08-11 10:49 ` Gu Lingguang
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.