Skip to content

Fix legacy recursive mount restrictions without procfs - #352

Merged
robertswiecki merged 1 commit into
google:masterfrom
wlgn4119:fix/legacy-recursive-mount-restrictions-without-proc
Oct 2, 2026
Merged

robertswiecki merged 1 commit into
google:masterfrom
wlgn4119:fix/legacy-recursive-mount-restrictions-without-proc

Conversation

@wlgn4119

Copy link
Copy Markdown
Contributor

Summary

The legacy mount backend reapplies requested flags to nested mounts by scanning /proc/self/mountinfo after the jail root transition. If the final jail has no procfs, fopen() fails, the descendant scan is skipped, and remountPt() still reports success.

For a recursive read-only bind, this can leave the top-level mount ro while a nested mount remains rw. A jailed workload can write through that nested mount if its ordinary permissions allow it.

Affected source revision tested: f100fd917c6d3ed0fd15d868528b735cb5fb1a1.

Impact

This bypasses an explicitly requested mount restriction. The reproduction writes only a marker to synthetic tmpfs mounts; it does not demonstrate authentication bypass, arbitrary host access, or code execution outside the jail.

Fix

Run the legacy remount pass after building the jail mount tree but before pivot_root() / chroot(), while the original /proc/self/mountinfo is accessible. Pass the temporary jail root to remountPt() and normalize destination paths before matching descendants. Fail jail setup if mountinfo is unavailable, a descendant remount fails, or any attached mount cannot receive its requested flags.

Reproduction and validation

The attached nsjail-pr-repro.zip contains a Docker fixture and a static write probe. Its README gives the build and run commands. On the affected source, the --experimental_mnt old --disable_proc cases write the marker, while the procfs-enabled controls fail with Read-only file system. The fixture covers both an explicit bind destination and the automatic chroot root bind.

The final patch builds successfully. With EXPECT_NO_PROC_WRITE=blocked, the fixture blocks writes for the default /mnt destination and /; with TEST_TRAILING_SLASH_DEST=1, it also blocks writes for /mnt/. The separate unreadable-mountinfo and failed-descendant-remount error branches were not forced in these runs.

Related work

PR #311 handles escaped mountinfo path fields after the file is opened. Open PR #344 makes some mount-flag and final-remount failures fatal, but its current change does not address the legacy fopen('/proc/self/mountinfo') failure path that skips descendant processing while returning success. This change addresses that missing-proc case. Issue #312 concerns ignored mount_setattr() errors in the new mount API.

Hi @robertswiecki — could you please review when convenient?
nsjail-pr-repro.zip

@google-cla

google-cla Bot commented Sep 29, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@robertswiecki

Copy link
Copy Markdown
Collaborator

Thank you!

@robertswiecki
robertswiecki merged commit be32694 into google:master Oct 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants