Linux Container Development
 help / color / mirror / Atom feed
From: Alexey Gladkov <legion@kernel.org>
To: GuLingguang <liu83783@gmail.com>
Cc: linux-fsdevel@vger.kernel.org, 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>,
	"Serge E . Hallyn" <serge@hallyn.com>
Subject: Re: [RFC] mnt_already_visible(): should regular-file mountpoints participate in the visibility check?
Date: Tue, 11 Aug 2026 11:16:58 +0200	[thread overview]
Message-ID: <anroiuNYZTID6VXS@example.org> (raw)
In-Reply-To: <20260808132309.35924-1-liu83783@gmail.com>

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


  reply	other threads:[~2026-08-11  9:17 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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=anroiuNYZTID6VXS@example.org \
    --to=legion@kernel.org \
    --cc=brauner@kernel.org \
    --cc=containers@lists.linux.dev \
    --cc=cyphar@cyphar.com \
    --cc=ebiederm@xmission.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liu83783@gmail.com \
    --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