Skip to content

Commit 8335f8c

Browse files
committed
rootfs: only set mode= for tmpfs mount if target already existed
This was always the intended behaviour but commit 72fbb34 ("rootfs: switch to fd-based handling of mountpoint targets") regressed it when adding a mechanism to create a file handle to the target if it didn't already exist (causing the later stat to always succeed). A lot of people depend on this functionality, so add some tests to make sure we don't break it in the future. Fixes: 72fbb34 ("rootfs: switch to fd-based handling of mountpoint targets") Signed-off-by: Aleksa Sarai <[email protected]>
1 parent 95762b6 commit 8335f8c

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

libcontainer/rootfs_linux.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,18 @@ func (m *mountEntry) createOpenMountpoint(rootfs string) (Err error) {
513513
_ = dstFile.Close()
514514
}
515515
}()
516+
if err == nil && m.Device == "tmpfs" {
517+
// If the original target exists, copy the mode for the tmpfs mount.
518+
stat, err := dstFile.Stat()
519+
if err != nil {
520+
return fmt.Errorf("check tmpfs source mode: %w", err)
521+
}
522+
dt := fmt.Sprintf("mode=%04o", syscallMode(stat.Mode()))
523+
if m.Data != "" {
524+
dt = dt + "," + m.Data
525+
}
526+
m.Data = dt
527+
}
516528
if err != nil {
517529
if !errors.Is(err, unix.ENOENT) {
518530
return fmt.Errorf("lookup mountpoint target: %w", err)
@@ -553,19 +565,6 @@ func (m *mountEntry) createOpenMountpoint(rootfs string) (Err error) {
553565
}
554566
}
555567

556-
if m.Device == "tmpfs" {
557-
// If the original target exists, copy the mode for the tmpfs mount.
558-
stat, err := dstFile.Stat()
559-
if err != nil {
560-
return fmt.Errorf("check tmpfs source mode: %w", err)
561-
}
562-
dt := fmt.Sprintf("mode=%04o", syscallMode(stat.Mode()))
563-
if m.Data != "" {
564-
dt = dt + "," + m.Data
565-
}
566-
m.Data = dt
567-
}
568-
569568
dstFullPath, err := procfs.ProcSelfFdReadlink(dstFile)
570569
if err != nil {
571570
return fmt.Errorf("get mount destination real path: %w", err)

tests/integration/mounts.bats

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,60 @@ function test_mount_order() {
234234
[[ "$(stat -c %a rootfs/setgid/a/b/c)" == 2755 ]]
235235
}
236236

237+
# https://github.com/opencontainers/runc/issues/4971
238+
@test "runc run [tmpfs mount mode= inherit]" {
239+
mkdir rootfs/tmpfs
240+
chmod "=0710" rootfs/tmpfs
241+
242+
update_config '.mounts += [{
243+
type: "tmpfs",
244+
source: "tmpfs",
245+
destination: "/tmpfs",
246+
options: ["rw", "nodev", "nosuid"]
247+
}]'
248+
update_config '.process.args = ["stat", "-c", "%a", "/tmpfs"]'
249+
250+
runc run test_busybox
251+
[ "$status" -eq 0 ]
252+
[[ "$output" == "710" ]]
253+
254+
update_config '.process.args = ["cat", "/proc/self/mounts"]'
255+
runc run test_busybox
256+
[ "$status" -eq 0 ]
257+
grep -Ex "tmpfs /tmpfs tmpfs [^ ]*\bmode=710\b[^ ]* .*" <<<"$output"
258+
}
259+
260+
# https://github.com/opencontainers/runc/issues/4971
261+
@test "runc run [tmpfs mount mode=1777 default]" {
262+
update_config '.mounts += [{
263+
type: "tmpfs",
264+
source: "tmpfs",
265+
destination: "/non-existent/foo/bar/baz",
266+
options: ["rw", "nodev", "nosuid"]
267+
}]'
268+
update_config '.process.args = ["stat", "-c", "%a", "/non-existent/foo/bar/baz"]'
269+
270+
rm -rf rootfs/non-existent
271+
runc run test_busybox
272+
[ "$status" -eq 0 ]
273+
[[ "$output" == "1777" ]]
274+
275+
update_config '.process.args = ["cat", "/proc/self/mounts"]'
276+
277+
rm -rf rootfs/non-existent
278+
runc run test_busybox
279+
[ "$status" -eq 0 ]
280+
# We don't explicitly set a mode= in this case, it is just the tmpfs default.
281+
grep -Ex "tmpfs /non-existent/foo/bar/baz tmpfs .*" <<<"$output"
282+
run ! grep -Ex "tmpfs /non-existent/foo/bar/baz tmpfs [^ ]*\bmode=[0-7]+\b[^ ]* .*" <<<"$output"
283+
284+
# Verify that the actual modes are *not* 1777.
285+
[[ "$(stat -c %a rootfs/non-existent)" == 755 ]]
286+
[[ "$(stat -c %a rootfs/non-existent/foo)" == 755 ]]
287+
[[ "$(stat -c %a rootfs/non-existent/foo/bar)" == 755 ]]
288+
[[ "$(stat -c %a rootfs/non-existent/foo/bar/baz)" == 755 ]]
289+
}
290+
237291
@test "runc run [ro /sys/fs/cgroup mounts]" {
238292
# Without cgroup namespace.
239293
update_config '.linux.namespaces -= [{"type": "cgroup"}]'

0 commit comments

Comments
 (0)