| 
 | 1 | +#!/usr/bin/env bats  | 
 | 2 | + | 
 | 3 | +load helpers  | 
 | 4 | + | 
 | 5 | +function setup() {  | 
 | 6 | +	requires root  | 
 | 7 | +	requires_kernel 5.12  | 
 | 8 | +	requires_idmap_fs /tmp  | 
 | 9 | + | 
 | 10 | +	setup_debian  | 
 | 11 | + | 
 | 12 | +	# Prepare source folders for bind mount  | 
 | 13 | +	mkdir -p source-{1,2}/  | 
 | 14 | +	touch source-{1,2}/foo.txt  | 
 | 15 | + | 
 | 16 | +	# Use other owner for source-2  | 
 | 17 | +	chown 1:1 source-2/foo.txt  | 
 | 18 | + | 
 | 19 | +	mkdir -p rootfs/{proc,sys,tmp}  | 
 | 20 | +	mkdir -p rootfs/tmp/mount-{1,2}  | 
 | 21 | +	mkdir -p rootfs/mnt/bind-mount-{1,2}  | 
 | 22 | + | 
 | 23 | +	update_config ' .process.args += ["-c", "stat -c =%u=%g= /tmp/mount-1/foo.txt"]  | 
 | 24 | +		| .mounts += [  | 
 | 25 | +					{  | 
 | 26 | +						"source": "source-1/",  | 
 | 27 | +						"destination": "/tmp/mount-1",  | 
 | 28 | +						"options": ["bind"],  | 
 | 29 | +						"uidMappings": [ {  | 
 | 30 | +						                  "containerID": 0,  | 
 | 31 | +						                  "hostID": 100000,  | 
 | 32 | +						                  "size": 65536  | 
 | 33 | +						                }  | 
 | 34 | +						],  | 
 | 35 | +						"gidMappings": [        {  | 
 | 36 | +						                  "containerID": 0,  | 
 | 37 | +						                  "hostID": 100000,  | 
 | 38 | +						                  "size": 65536  | 
 | 39 | +						                }  | 
 | 40 | +						]  | 
 | 41 | +					}  | 
 | 42 | +				] '  | 
 | 43 | +}  | 
 | 44 | + | 
 | 45 | +function teardown() {  | 
 | 46 | +	teardown_bundle  | 
 | 47 | +}  | 
 | 48 | + | 
 | 49 | +@test "simple idmap mount" {  | 
 | 50 | +	runc run test_debian  | 
 | 51 | +	[ "$status" -eq 0 ]  | 
 | 52 | +	[[ "$output" == *"=100000=100000="* ]]  | 
 | 53 | +}  | 
 | 54 | + | 
 | 55 | +@test "write to an idmap mount" {  | 
 | 56 | +	# We need to change the config to permit UID 0 to write the mount id map.  | 
 | 57 | +	update_config ' .process.args = ["sh", "-c", "touch /tmp/mount-1/bar && stat -c =%u=%g= /tmp/mount-1/bar"]  | 
 | 58 | +		| .mounts |= map((select(.source == "source-1/") | .uidMappings[0].hostID = 0 | .gidMappings[0].hostID = 0) // .)'  | 
 | 59 | +	runc run test_debian  | 
 | 60 | +	[ "$status" -eq 0 ]  | 
 | 61 | +	[[ "$output" == *"=0=0="* ]]  | 
 | 62 | +}  | 
 | 63 | + | 
 | 64 | +@test "idmap mount with propagation flag" {  | 
 | 65 | +	update_config ' .process.args = ["sh", "-c", "findmnt -o PROPAGATION /tmp/mount-1"]'  | 
 | 66 | +	# Add the shared option to the idmap mount  | 
 | 67 | +	update_config ' .mounts |= map((select(.source == "source-1/") | .options += ["shared"]) // .)'  | 
 | 68 | + | 
 | 69 | +	runc run test_debian  | 
 | 70 | +	[ "$status" -eq 0 ]  | 
 | 71 | +	[[ "$output" == *"shared"* ]]  | 
 | 72 | +}  | 
 | 73 | + | 
 | 74 | +@test "idmap mount with bind mount" {  | 
 | 75 | +	update_config '   .mounts += [  | 
 | 76 | +					{  | 
 | 77 | +						"source": "source-2/",  | 
 | 78 | +						"destination": "/tmp/mount-2",  | 
 | 79 | +						"options": ["bind"]  | 
 | 80 | +					}  | 
 | 81 | +				] '  | 
 | 82 | + | 
 | 83 | +	runc run test_debian  | 
 | 84 | +	[ "$status" -eq 0 ]  | 
 | 85 | +	[[ "$output" == *"=100000=100000="* ]]  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +@test "two idmap mounts with two bind mounts" {  | 
 | 89 | +	update_config '   .process.args = ["sh", "-c", "stat -c =%u=%g= /tmp/mount-1/foo.txt /tmp/mount-2/foo.txt"]  | 
 | 90 | +			| .mounts += [  | 
 | 91 | +					{  | 
 | 92 | +						"source": "source-1/",  | 
 | 93 | +						"destination": "/mnt/bind-mount-1",  | 
 | 94 | +						"options": ["bind"]  | 
 | 95 | +					},  | 
 | 96 | +					{  | 
 | 97 | +						"source": "source-2/",  | 
 | 98 | +						"destination": "/mnt/bind-mount-2",  | 
 | 99 | +						"options": ["bind"]  | 
 | 100 | +					},  | 
 | 101 | +					{  | 
 | 102 | +						"source": "source-2/",  | 
 | 103 | +						"destination": "/tmp/mount-2",  | 
 | 104 | +						"options": ["bind"],  | 
 | 105 | +						"uidMappings": [ {  | 
 | 106 | +						                  "containerID": 0,  | 
 | 107 | +						                  "hostID": 100000,  | 
 | 108 | +						                  "size": 65536  | 
 | 109 | +						                }  | 
 | 110 | +						],  | 
 | 111 | +						"gidMappings": [        {  | 
 | 112 | +						                  "containerID": 0,  | 
 | 113 | +						                  "hostID": 100000,  | 
 | 114 | +						                  "size": 65536  | 
 | 115 | +						                }  | 
 | 116 | +						]  | 
 | 117 | +					}  | 
 | 118 | +				] '  | 
 | 119 | + | 
 | 120 | +	runc run test_debian  | 
 | 121 | +	[ "$status" -eq 0 ]  | 
 | 122 | +	[[ "$output" == *"=100000=100000="* ]]  | 
 | 123 | +	# source-2/ is owned by 1:1, so we expect this with the idmap mount too.  | 
 | 124 | +	[[ "$output" == *"=100001=100001="* ]]  | 
 | 125 | +}  | 
 | 126 | + | 
 | 127 | +@test "idmap mount without gidMappings fails" {  | 
 | 128 | +	update_config ' .mounts |= map((select(.source == "source-1/") | del(.gidMappings) ) // .)'  | 
 | 129 | + | 
 | 130 | +	runc run test_debian  | 
 | 131 | +	[ "$status" -eq 1 ]  | 
 | 132 | +	[[ "${output}" == *"invalid mount"* ]]  | 
 | 133 | +}  | 
 | 134 | + | 
 | 135 | +@test "idmap mount without uidMappings fails" {  | 
 | 136 | +	update_config ' .mounts |= map((select(.source == "source-1/") | del(.uidMappings) ) // .)'  | 
 | 137 | + | 
 | 138 | +	runc run test_debian  | 
 | 139 | +	[ "$status" -eq 1 ]  | 
 | 140 | +	[[ "${output}" == *"invalid mount"* ]]  | 
 | 141 | +}  | 
 | 142 | + | 
 | 143 | +@test "idmap mount without bind fails" {  | 
 | 144 | +	update_config ' .mounts |= map((select(.source == "source-1/") | .options = [""]) // .)'  | 
 | 145 | + | 
 | 146 | +	runc run test_debian  | 
 | 147 | +	[ "$status" -eq 1 ]  | 
 | 148 | +	[[ "${output}" == *"invalid mount"* ]]  | 
 | 149 | +}  | 
0 commit comments