-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Fix failure with rw bind mount of a ro fuse #3283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix failure with rw bind mount of a ro fuse #3283
Conversation
08915b8 to
dd466b3
Compare
dd466b3 to
fe6a902
Compare
fe6a902 to
d7846bc
Compare
tests/integration/mounts.bats
Outdated
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| @test "runc run [rw bind mount of a ro fuse sshfs mount]" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move this into mounts_sshfs.bats, as this has huge extra depenedency?
Or maybe just skip the sshfs test by default and require some env var to opt-in to the sshfs test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. If sshfs is not installed or not working for some reason, the test is skipped.
| return mount(source, m.Destination, procfd, m.Device, uintptr(m.Flags|unix.MS_REMOUNT), "") | ||
| flags := uintptr(m.Flags | unix.MS_REMOUNT) | ||
| err := mount(source, m.Destination, procfd, m.Device, flags, "") | ||
| if err == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rather check errors.Is(err, syscall.EPERM)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A different kernel might return a different error, and if the original mount is not read-only, we still return that error, and if it is, a retry with added RO flag will most probably return the very same error.
In other words, the error path overhead of a statfs() and (maybe) a mount() is pretty small, and the error returned is most probably the same, so it makes sense to retry on any error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In short, it doesn't hurt to retry even if there was an error other than EPERM.
d5bf4e0 to
20e15a2
Compare
As reported in [1], in a case where read-only fuse (sshfs) mount
is used as a volume without specifying ro flag, the kernel fails
to remount it (when adding various flags such as nosuid and nodev),
returning EPERM.
Here's the relevant strace line:
> [pid 333966] mount("/tmp/bats-run-PRVfWc/runc.RbNv8g/bundle/mnt", "/proc/self/fd/7", 0xc0001e9164, MS_NOSUID|MS_NODEV|MS_REMOUNT|MS_BIND|MS_REC, NULL) = -1 EPERM (Operation not permitted)
I was not able to reproduce it with other read-only mounts as the source
(tried tmpfs, read-only bind mount, and an ext2 mount), so somehow this
might be specific to fuse.
The fix is to check whether the source has RDONLY flag, and retry the
remount with this flag added.
A test case (which was kind of hard to write) is added, and it fails
without the fix. Note that rootless user need to be able to ssh to
rootless@localhost in order to sshfs to work -- amend setup scripts
to make it work, and skip the test if the setup is not working.
[1] containers/podman#12205
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
20e15a2 to
50105de
Compare
|
@thaJeztah PTAL |
|
This fixes a real bug and we need to backport it to 1.0.3. Can this be merged? PTAL @opencontainers/runc-maintainers |
|
Ahm, sorry, I started looking, but got pulled away |
thaJeztah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| if err == nil { | ||
| return nil | ||
| } | ||
| // Check if the source has ro flag... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meta question: Can this be solved by requiring the entity configuring the mounts to set the necessary flags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but it's not clear who should handle this (e.g. podman thinks it shouldn't, see containers/podman#12205) , and handling it in runc is kind of trivial. Besides, crun already does this, and this makes it hard to convince upper layers should do this.
As reported in containers/podman#12205, in a case where read-only fuse (sshfs)
mount is used as a volume without specifying ro flag, the kernel fails
to remount it (when adding various flags such as nosuid and nodev),
returning EPERM.
Here's the relevant strace line:
I was not able to reproduce it with other read-only mounts as the source
(tried tmpfs, read-only bind mount, and an ext2 mount), so somehow this
might be specific to fuse.
The fix is to check whether the source has RDONLY flag, and retry the
remount with this flag added.
A test case (which was kind of hard to write) is added, and it fails
without the fix:
Note that rootless user need to be able to ssh to rootless@localhost
in order to sshfs to work -- amend setup scripts to make it work.
1.0 backport: #3292