@@ -24,6 +24,109 @@ function test_ro_cgroup_mount() {
2424 for line in " ${lines[@]} " ; do [[ " ${line} " == * ' ro,' * ]]; done
2525}
2626
27+ # Parse an "optstring" of the form foo,bar into $is_foo and $is_bar variables.
28+ # Usage: parse_optstring foo,bar foo bar baz
29+ function parse_optstring() {
30+ optstring=" $1 "
31+ shift
32+
33+ for flag in " $@ " ; do
34+ is_set=
35+ if grep -wq " $flag " <<< " $optstring" ; then
36+ is_set=1
37+ fi
38+ eval " is_$flag =$is_set "
39+ done
40+ }
41+
42+ function config_add_bind_mount() {
43+ src=" $1 "
44+ dst=" $2 "
45+ parse_optstring " ${3:- } " rbind idmap
46+
47+ bindtype=bind
48+ if [ -n " $is_rbind " ]; then
49+ bindtype=rbind
50+ fi
51+
52+ mappings=" "
53+ if [ -n " $is_idmap " ]; then
54+ mappings='
55+ "uidMappings": [{"containerID": 0, "hostID": 100000, "size": 65536}],
56+ "gidMappings": [{"containerID": 0, "hostID": 100000, "size": 65536}],
57+ '
58+ fi
59+
60+ update_config ' .mounts += [{
61+ "source": "' " $src " ' ",
62+ "destination": "' " $dst " ' ",
63+ "type": "bind",
64+ ' " $mappings " '
65+ "options": [ "' " $bindtype " ' ", "rprivate" ]
66+ }]'
67+ }
68+
69+ # This needs to be placed at the top of the bats file to work around
70+ # a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
71+ function test_mount_order() {
72+ parse_optstring " ${1:- } " userns idmap
73+
74+ if [ -n " $is_userns " ]; then
75+ requires root
76+
77+ update_config ' .linux.namespaces += [{"type": "user"}]
78+ | .linux.uidMappings += [{"containerID": 0, "hostID": 100000, "size": 65536}]
79+ | .linux.gidMappings += [{"containerID": 0, "hostID": 100000, "size": 65536}]'
80+ remap_rootfs
81+ fi
82+
83+ ctr_src_opts=" rbind"
84+ if [ -n " $is_idmap " ]; then
85+ requires root
86+ requires_kernel 5.12
87+ requires_idmap_fs .
88+
89+ ctr_src_opts+=" ,idmap"
90+ fi
91+
92+ mkdir -p rootfs/{mnt,final}
93+ # Create a set of directories we can create a mount tree with.
94+ for subdir in a/x b/y c/z; do
95+ dir=" bind-src/$subdir "
96+ mkdir -p " $dir "
97+ echo " $subdir " > " $dir /file"
98+ # Add a symlink to make sure
99+ topdir=" $( dirname " $subdir " ) "
100+ ln -s " $topdir " " bind-src/sym-$topdir "
101+ done
102+ # In userns tests, make sure that the source directory cannot be accessed,
103+ # to make sure we're exercising the bind-mount source fd logic.
104+ chmod o-rwx bind-src
105+
106+ rootfs=" $( pwd) /rootfs"
107+ rm -rf rootfs/mnt
108+ mkdir rootfs/mnt
109+
110+ # Create a bind-mount tree.
111+ config_add_bind_mount " $PWD /bind-src/a" " /mnt"
112+ config_add_bind_mount " $PWD /bind-src/sym-b" " /mnt/x"
113+ config_add_bind_mount " $PWD /bind-src/c" " /mnt/x/y"
114+ config_add_bind_mount " $PWD /bind-src/sym-a" " /mnt/x/y/z"
115+ # Create a recursive bind-mount that uses part of the current tree in the
116+ # container.
117+ config_add_bind_mount " $rootfs /mnt/x" " $rootfs /mnt/x/y/z/x" " $ctr_src_opts "
118+ config_add_bind_mount " $rootfs /mnt/x/y" " $rootfs /mnt/x/y/z" " $ctr_src_opts "
119+ # Finally, bind-mount the whole thing on top of /final.
120+ config_add_bind_mount " $rootfs /mnt" " $rootfs /final" " $ctr_src_opts "
121+
122+ # Check that the entire tree was copied and the mounts were done in the
123+ # expected order.
124+ update_config ' .process.args = ["cat", "/final/x/y/z/z/x/y/z/x/file"]'
125+ runc run test_busybox
126+ [ " $status " -eq 0 ]
127+ [[ " $output " == * " a/x" * ]] # the final "file" was from a/x.
128+ }
129+
27130# https://github.com/opencontainers/runc/issues/3991
28131@test " runc run [tmpcopyup]" {
29132 mkdir -p rootfs/dir1/dir2
@@ -108,3 +211,19 @@ function test_ro_cgroup_mount() {
108211 update_config ' .linux.namespaces |= if index({"type": "cgroup"}) then . else . + [{"type": "cgroup"}] end'
109212 test_ro_cgroup_mount
110213}
214+
215+ @test " runc run [mount order, container bind-mount source]" {
216+ test_mount_order
217+ }
218+
219+ @test " runc run [mount order, container bind-mount source] (userns)" {
220+ test_mount_order userns
221+ }
222+
223+ @test " runc run [mount order, container idmap source]" {
224+ test_mount_order idmap
225+ }
226+
227+ @test " runc run [mount order, container idmap source] (userns)" {
228+ test_mount_order userns,idmap
229+ }
0 commit comments