Skip to content

linux: fix bind mount flags - #2247

Merged
giuseppe merged 4 commits into
containers:mainfrom
kolyshkin:bind-mount-flags
Sep 11, 2026
Merged

giuseppe merged 4 commits into
containers:mainfrom
kolyshkin:bind-mount-flags

Conversation

@kolyshkin

@kolyshkin kolyshkin commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

The flags of a bind mount with some mount flag options should be exactly the requested ones (with the unrequested ones cleared), while a bind mount with no such options (e.g. just bind) should keep the flags of the source. This is how runc works, and mostly how crun works, too, except for these cases:

  1. linux: clear unrequested flags on read-only remount

    Commit f53aa37 made finalize_mounts use mount_setattr for read-only remounts (e.g. for a bind,ro mount), which only sets the requested flags, not clearing the rest (unlike do_remount used before). As a result, a bind,ro mount of a nosuid,nodev,noexec source keeps all those flags. Clear the flags which are not set, like do_remount does.

    Fixes: f53aa37 ("linux: use mount_setattr for readonly remounts in finalize_mounts")

  2. linux: honor clearing-only options for bind mounts

    A bind mount source is cloned in advance, and after it is moved into place, its flags are only changed if there are some flags to set. Options which only clear flags (e.g. dev, suid, exec, rw) do not set any, so they are silently ignored. For example, a bind,dev,suid,exec mount of a ro,nosuid,nodev,noexec source is left with all these flags. Do the remount if there are any mount flag options. Add a test case (covering the previous commit, too).

  3. linux: clear nosymfollow on remount unless requested

    Add MS_NOSYMFOLLOW to the flags which are cleared when not requested, like runc does. It is not a locked flag, so it can be cleared in a user namespace, too.

  4. linux: set atime flags like mount(2) does

    When remounting with mount_setattr, the atime part of the flags is only reset if the requested flags contain a non-zero atime value. Yet, relatime is zero, and nodiratime is not a part of the atime value, so e.g. a bind,relatime mount of a noatime source is left with noatime, and so is a bind,nodiratime one. Do what mount(2) (and so runc) does: if any atime flag is set, set all the atime ones anew; otherwise, keep them as is. Add test cases.

Checked against runc with a set of source flags / bind options combinations (the ones from runc's mounts_sshfs.bats), now giving the same results (without a user namespace).

Found by the mounts_sshfs.bats runc integration tests (see #2238).

Commit f53aa37 made finalize_mounts use mount_setattr for read-only
remounts, which is done for e.g. a "bind,ro" mount. Unlike do_remount
it used before, it only sets the requested flags, not clearing the rest.
As a result, a "bind,ro" mount of a nosuid,nodev,noexec source keeps all
those flags, while it should only have the requested one (ro), as it was
before, and as it is in runc.

Clear the flags which are not set, like do_remount does.

Found by the mounts_sshfs.bats runc integration tests.

Fixes: f53aa37 ("linux: use mount_setattr for readonly remounts in finalize_mounts")
Signed-off-by: Kir Kolyshkin <[email protected]>
A bind mount source is opened (cloned) in advance, and after it is
moved into place, its flags are only changed if there are some flags to
set. Options which only clear flags (e.g. "dev", "suid", "exec", "rw")
do not set any, so they are silently ignored, and the flags of the
source are kept. For example, a "bind,dev,suid,exec" mount of a
ro,nosuid,nodev,noexec source is left with all these flags.

Do the remount if there are any mount flag options, so the resulting
flags are exactly the requested ones, like it is done for a bind mount
with some flags to set (e.g. "bind,nosuid"), and like runc does. A bind
mount with no such options (e.g. "bind", "rbind,rprivate") still keeps
the flags of the source.

Add a test case, covering the previous commit, too.

Found by the mounts_sshfs.bats runc integration tests.

Signed-off-by: Kir Kolyshkin <[email protected]>
When remounting to apply the requested flags, the flags which are not
requested are cleared, except for nosymfollow, which is inherited from
the source mount. E.g., a "bind,ro" mount of a nosymfollow source is
left with nosymfollow.

Add MS_NOSYMFOLLOW to the flags which are cleared, like runc does.
Note it is not a locked flag, so it can be cleared in a user namespace,
too.

Found by the mounts_sshfs.bats runc integration tests.

Signed-off-by: Kir Kolyshkin <[email protected]>
When remounting with mount_setattr, the atime part of the mount flags
is only reset if the requested flags contain a non-zero atime value.
Yet, relatime is zero, and nodiratime is not a part of the atime value,
so, e.g., a "bind,relatime" mount of a noatime source is left with
noatime, and so is a "bind,nodiratime" one.

Do what mount(2) does: if any atime flag is set, set all the atime ones
anew (relatime is the default, noatime and strictatime override it, and
nodiratime is independent); otherwise, keep the atime flags as is. This
is also what runc does, as it uses mount(2).

Add test cases.

Found by the "runc run [bind mount {no,rel,strict}atime semantics]"
runc integration test.

Signed-off-by: Kir Kolyshkin <[email protected]>

@giuseppe giuseppe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@giuseppe
giuseppe merged commit a9e235d into containers:main Sep 11, 2026
59 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