]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
proc: handle subset=pid separately in userns visibility checks
authorAlexey Gladkov <legion@kernel.org>
Mon, 27 Apr 2026 08:26:07 +0000 (10:26 +0200)
committerChristian Brauner <brauner@kernel.org>
Mon, 11 May 2026 21:13:02 +0000 (23:13 +0200)
When procfs is mounted with subset=pid, only the dynamic process-related
part of the filesystem remains visible. That part cannot be hidden by
overmounts, so checking whether an existing procfs mount is fully
visible does not make sense for this mode.

At the same time, a subset=pid procfs mount must not be used as evidence
that a later procfs mount would not reveal additional information. It
provides a restricted view of procfs, not the full filesystem view.

Mark subset=pid procfs instances as restricted variants. Ignore
restricted variants when looking for an already-visible mount, and allow
new restricted variants without consulting mnt_already_visible().

Signed-off-by: Alexey Gladkov <legion@kernel.org>
Link: https://patch.msgid.link/4d5e760c3d534dd2e05578d119cc408450053a98.1777278334.git.legion@kernel.org
Reviewed-by: Aleksa Sarai <aleksa@amutable.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/namespace.c
fs/proc/root.c
include/linux/fs/super_types.h

index e6e58117c778b0f743f1f0fe453a73b2ed472e1e..9a66a806a9b8a46ba96bc3045dca9f53fc6d0b12 100644 (file)
@@ -6353,10 +6353,18 @@ static bool mnt_already_visible(struct mnt_namespace *ns,
 
        guard(namespace_shared)();
        hlist_for_each_entry(mnt, &ns->mnt_visible_mounts, mnt_ns_visible) {
+               const struct super_block *sb_visible = mnt->mnt.mnt_sb;
                struct mount *child;
                int mnt_flags;
 
-               if (mnt->mnt.mnt_sb->s_type != sb->s_type)
+               if (sb_visible->s_type != sb->s_type)
+                       continue;
+
+               /*
+                * Restricted variants are not compatible with anything, even
+                * other restricted variants.
+                */
+               if (sb_visible->s_iflags & SB_I_RESTRICTED_VARIANT)
                        continue;
 
                /* A local view of the mount flags */
@@ -6418,6 +6426,13 @@ static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags
                return true;
        }
 
+       /*
+        * Restricted variants don't need an already visible mount because they
+        * don't expose the full filesystem view.
+        */
+       if (s_iflags & SB_I_RESTRICTED_VARIANT)
+               return false;
+
        return !mnt_already_visible(ns, sb, new_mnt_flags);
 }
 
index 1bf75a4ee146f2de144cd84c982eed07cdd1909e..99adddfeb4a44c89ddcb9e72643973878ef8f9fe 100644 (file)
@@ -275,6 +275,9 @@ static int proc_fill_super(struct super_block *s, struct fs_context *fc)
        s->s_time_gran = 1;
        s->s_fs_info = fs_info;
 
+       if (fs_info->pidonly == PROC_PIDONLY_ON)
+               s->s_iflags |= SB_I_RESTRICTED_VARIANT;
+
        /*
         * procfs isn't actually a stacking filesystem; however, there is
         * too much magic going on inside it to permit stacking things on
index 182efbeb9520926d3a26a75f9d9f481d8f1d89e0..a6cdc8f6de4e81968a5605dc44d241d4c45e96fd 100644 (file)
@@ -326,6 +326,7 @@ struct super_block {
 #define SB_I_STABLE_WRITES 0x00000008  /* don't modify blks until WB is done */
 
 /* sb->s_iflags to limit user namespace mounts */
+#define SB_I_RESTRICTED_VARIANT                0x00000010
 #define SB_I_IMA_UNVERIFIABLE_SIGNATURE        0x00000020
 #define SB_I_UNTRUSTED_MOUNTER         0x00000040
 #define SB_I_EVM_HMAC_UNSUPPORTED      0x00000080