diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 44befb9f7a9..cff3d922d45 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -153,15 +153,16 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) { // finalizeRootfs sets anything to ro if necessary. You must call // prepareRootfs first. func finalizeRootfs(config *configs.Config) (err error) { - // remount dev as ro if specified + // All tmpfs mounts and /dev were previously mounted as rw + // by mountPropagate. Remount them read-only as requested. for _, m := range config.Mounts { - if utils.CleanPath(m.Destination) == "/dev" { - if m.Flags&unix.MS_RDONLY == unix.MS_RDONLY { - if err := remountReadonly(m); err != nil { - return newSystemErrorWithCausef(err, "remounting %q as readonly", m.Destination) - } + if m.Flags&unix.MS_RDONLY != unix.MS_RDONLY { + continue + } + if m.Device == "tmpfs" || utils.CleanPath(m.Destination) == "/dev" { + if err := remountReadonly(m); err != nil { + return newSystemErrorWithCausef(err, "remounting %q as readonly", m.Destination) } - break } } @@ -431,12 +432,6 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { return err } } - // Initially mounted rw in mountPropagate, remount to ro if flag set. - if m.Flags&unix.MS_RDONLY != 0 { - if err := remount(m, rootfs); err != nil { - return err - } - } return nil case "bind": if err := prepareBindMount(m, rootfs); err != nil { @@ -1046,10 +1041,10 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { flags = m.Flags ) // Delay mounting the filesystem read-only if we need to do further - // operations on it. We need to set up files in "/dev" and tmpfs mounts may - // need to be chmod-ed after mounting. The mount will be remounted ro later - // in finalizeRootfs() if necessary. - if utils.CleanPath(m.Destination) == "/dev" || m.Device == "tmpfs" { + // operations on it. We need to set up files in "/dev", and other tmpfs + // mounts may need to be chmod-ed after mounting. These mounts will be + // remounted ro later in finalizeRootfs(), if necessary. + if m.Device == "tmpfs" || utils.CleanPath(m.Destination) == "/dev" { flags &= ^unix.MS_RDONLY } diff --git a/tests/integration/mounts.bats b/tests/integration/mounts.bats index 5d1ba0974ef..1ec675aca55 100644 --- a/tests/integration/mounts.bats +++ b/tests/integration/mounts.bats @@ -38,6 +38,16 @@ function teardown() { [[ "${lines[0]}" == *'ro,'* ]] } +# https://github.com/opencontainers/runc/issues/3248 +@test "runc run [ro /dev mount]" { + update_config ' .mounts |= map((select(.destination == "/dev") | .options += ["ro"]) // .) + | .process.args |= ["grep", "^tmpfs /dev", "/proc/mounts"]' + + runc run test_busybox + [ "$status" -eq 0 ] + [[ "${lines[0]}" == *'ro,'* ]] +} + # https://github.com/opencontainers/runc/issues/2683 @test "runc run [tmpfs mount with absolute symlink]" { # in container, /conf -> /real/conf