Skip to content

Preserve nosymfollow across bind-mount flag fixups - #770

Open
tjunnone wants to merge 1 commit into
containers:mainfrom
tjunnone:bwrap-flag-fixup-drops-nosymfollow
Open

Preserve nosymfollow across bind-mount flag fixups#770
tjunnone wants to merge 1 commit into
containers:mainfrom
tjunnone:bwrap-flag-fixup-drops-nosymfollow

Conversation

@tjunnone

Copy link
Copy Markdown

When bubblewrap binds a host mount that was mounted nosymfollow (for example systemd credential mounts), the flag is silently cleared inside the sandbox whenever the bind triggers bubblewrap's flag-fixup remount.

Example:

unshare -rm sh -c '
  mkdir -p /mnt/nsf
  mount -t tmpfs -o nosymfollow tmpfs /mnt/nsf
  printf secret > /mnt/nsf/x
  ln -s x /mnt/nsf/l
  cat /mnt/nsf/l                       # host:    Too many levels of symbolic links
  bwrap --ro-bind / / cat /mnt/nsf/l   # sandbox: prints "secret"
'

Expected: the sandbox refuses to follow the symlink (ELOOP), just like the host.
Actual: the sandbox prints secret, as nosymfollow was dropped.

This happens because decode_mountoptions parses the mount's flags from /proc/self/mountinfo through a table that has no nosymfollow entry. The fixup remount then passes only the decoded flags and nosymfollow is cleared. The fix is to add the table entry. A test entry for the case is also added to test-run.sh for good measure.

Add a nosymfollow entry to decode_mountoptions so the flag is not
dropped on a fixup remount.

Added a regression test, binding a `nosymfollow` tmpfs read-only
(therefore forcing a fixup remount) that fails if symlink is
followed.

Signed-off-by: Tomas Junnonen <tomas1@gmail.com>
@tjunnone
tjunnone force-pushed the bwrap-flag-fixup-drops-nosymfollow branch from 1ab2a54 to 3579e14 Compare August 23, 2026 18:27
@smcv

smcv commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

This should be partially solved already by #756: if I understand correctly, we'll now preserve nosymfollow (and all other mount flags) when we're on the mount_setattr() code path, and this change will only be necessary if we're on the old code path where mount_setattr() fails with ENOSYS (kernels older than 5.12).

@smcv smcv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good for the fallback code path, please rebase after the merge of #756 (or you might prefer to wait until after #777 has been merged, since that will probably introduce new conflicts).

@smcv

smcv commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

To force the test onto the fallback code path, you could do it twice, with and without --debug-opt=force-mount-setattr-fallback. I think you will find that after #756, the test will pass even with your bugfix reverted in the normal case, but will fail when --debug-opt=force-mount-setattr-fallback is used (and then your bugfix will fix that).

Because of the way you've structured the test, if bubblewrap is compiled to require a modern kernel and not fall back if mount_setattr() fails with ENOSYS, I think your test will still pass.

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