Skip to content

0.12.0 regression?: Can't bind-mount a directory whose parent is unreadable #806

Description

@smcv

After updating the Steam Runtime's internal copy of bubblewrap (srt-bwrap) to 0.13.0 0.12.0, launching its containers no longer works on a system with Debian's pam_tmpdir, or with OpenWall's pam_mktemp as packaged by Gentoo. Despite being unrelated codebases, these two are basically equivalent: they're implementations of the same idea.

These PAM modules create a restricted parent directory that ordinary users can traverse through, but not list (this is unusual!), and then a per-user private temp directory inside that, and set TMPDIR (among other environment variables) to that per-user directory. The same effect can be reproduced on a test system with something like this:

sudo mkdir -m711 /tmp/private
sudo install -d -o$(id -nu) -g$(id -ng) -m1770 /tmp/private/$(id -nu)
# the PAM module would do the equivalent of: export TMPDIR=/tmp/private/$(id -nu)

bwrap --ro-bind / / --bind "/tmp/private/$(id -nu)" "/tmp/private/$(id -nu) -- true

With older bwrap builds this seems to have worked.

With a newer bwrap build, it fails with bwrap: Can't mkdir parents for /tmp/private/user: Permission denied.

This appears to be because openat2 (oldroot, "/tmp/private", { flags=O_RDONLY|O_DIRECTORY, resolve=RESOLVE_IN_ROOT|RESOLVE_NO_MAGICLINKS) is failing with EACCES when we open it as part of the solution for CVE-2026-87766 - which is expected, we don't have read access to /tmp/private in this scenario. Perhaps it could be opened with O_PATH to avoid needing the read permission?

(The real use-case is that the Steam Runtime wants to bind-mount a long list of directories into a container, including the user's $TMPDIR.)

cc @ao2 @mlauss2

Activity

  1. smcv commented on Sep 24, 2026

    @smcv
    CollaboratorAuthor

    These PAM modules create a restricted parent directory that ordinary users can traverse through, but not list (this is unusual!), and then a per-user private temp directory inside that

    This was historically done as a defence-in-depth against /tmp symlink attacks. On modern Linux kernels in most distros, the protected_symlinks sysctl is another way to mitigate those attacks and is usually on-by-default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions