github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/tests/integration/mounts.bats (about)

     1  #!/usr/bin/env bats
     2  
     3  load helpers
     4  
     5  function setup() {
     6  	setup_busybox
     7  }
     8  
     9  function teardown() {
    10  	teardown_bundle
    11  }
    12  
    13  # https://github.com/opencontainers/runc/security/advisories/GHSA-m8cg-xc2p-r3fc
    14  #
    15  # This needs to be placed at the top of the bats file to work around
    16  # a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
    17  function test_ro_cgroup_mount() {
    18  	local lines status
    19  	# shellcheck disable=SC2016
    20  	update_config '.process.args |= ["sh", "-euc", "for f in `grep /sys/fs/cgroup /proc/mounts | awk \"{print \\\\$2}\"| uniq`; do test -e $f && grep -w $f /proc/mounts | tail -n1; done"]'
    21  	runc run test_busybox
    22  	[ "$status" -eq 0 ]
    23  	[ "${#lines[@]}" -ne 0 ]
    24  	for line in "${lines[@]}"; do [[ "${line}" == *'ro,'* ]]; done
    25  }
    26  
    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  
   130  # https://github.com/opencontainers/runc/issues/3991
   131  @test "runc run [tmpcopyup]" {
   132  	mkdir -p rootfs/dir1/dir2
   133  	chmod 777 rootfs/dir1/dir2
   134  	update_config '	  .mounts += [{
   135  					source: "tmpfs",
   136  					destination: "/dir1",
   137  					type: "tmpfs",
   138  					options: ["tmpcopyup"]
   139  				}]
   140  			| .process.args |= ["ls", "-ld", "/dir1/dir2"]'
   141  
   142  	umask 022
   143  	runc run test_busybox
   144  	[ "$status" -eq 0 ]
   145  	[[ "${lines[0]}" == *'drwxrwxrwx'* ]]
   146  }
   147  
   148  @test "runc run [bind mount]" {
   149  	update_config '	  .mounts += [{
   150  					source: ".",
   151  					destination: "/tmp/bind",
   152  					options: ["bind"]
   153  				}]
   154  			| .process.args |= ["ls", "/tmp/bind/config.json"]'
   155  
   156  	runc run test_busybox
   157  	[ "$status" -eq 0 ]
   158  	[[ "${lines[0]}" == *'/tmp/bind/config.json'* ]]
   159  }
   160  
   161  # https://github.com/opencontainers/runc/issues/2246
   162  @test "runc run [ro tmpfs mount]" {
   163  	update_config '	  .mounts += [{
   164  					source: "tmpfs",
   165  					destination: "/mnt",
   166  					type: "tmpfs",
   167  					options: ["ro", "nodev", "nosuid", "mode=755"]
   168  				}]
   169  			| .process.args |= ["grep", "^tmpfs /mnt", "/proc/mounts"]'
   170  
   171  	runc run test_busybox
   172  	[ "$status" -eq 0 ]
   173  	[[ "${lines[0]}" == *'ro,'* ]]
   174  }
   175  
   176  # https://github.com/opencontainers/runc/issues/3248
   177  @test "runc run [ro /dev mount]" {
   178  	update_config '   .mounts |= map((select(.destination == "/dev") | .options += ["ro"]) // .)
   179  			| .process.args |= ["grep", "^tmpfs /dev", "/proc/mounts"]'
   180  
   181  	runc run test_busybox
   182  	[ "$status" -eq 0 ]
   183  	[[ "${lines[0]}" == *'ro,'* ]]
   184  }
   185  
   186  # https://github.com/opencontainers/runc/issues/2683
   187  @test "runc run [tmpfs mount with absolute symlink]" {
   188  	# in container, /conf -> /real/conf
   189  	mkdir -p rootfs/real/conf
   190  	ln -s /real/conf rootfs/conf
   191  	update_config '	  .mounts += [{
   192  					type: "tmpfs",
   193  					source: "tmpfs",
   194  					destination: "/conf/stack",
   195  					options: ["ro", "nodev", "nosuid"]
   196  				}]
   197  			| .process.args |= ["true"]'
   198  	runc run test_busybox
   199  	[ "$status" -eq 0 ]
   200  }
   201  
   202  @test "runc run [ro /sys/fs/cgroup mounts]" {
   203  	# Without cgroup namespace.
   204  	update_config '.linux.namespaces -= [{"type": "cgroup"}]'
   205  	test_ro_cgroup_mount
   206  }
   207  
   208  @test "runc run [ro /sys/fs/cgroup mounts + cgroupns]" {
   209  	requires cgroupns
   210  	# With cgroup namespace.
   211  	update_config '.linux.namespaces |= if index({"type": "cgroup"}) then . else . + [{"type": "cgroup"}] end'
   212  	test_ro_cgroup_mount
   213  }
   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  }