@@ -29,7 +29,7 @@ function teardown() {
29
29
if [ -v to_umount_list ]; then
30
30
while read -r mount_path; do
31
31
umount -l " $mount_path " || :
32
- rm -f " $mount_path "
32
+ rm -rf " $mount_path "
33
33
done < " $to_umount_list "
34
34
rm -f " $to_umount_list "
35
35
unset to_umount_list
@@ -184,3 +184,62 @@ function teardown() {
184
184
grep -E ' ^\s+0\s+' $EUID ' \s+1$' <<< " $output"
185
185
fi
186
186
}
187
+
188
+ # <https://github.com/opencontainers/runc/issues/4390>
189
+ @test " userns join external namespaces [wrong userns owner]" {
190
+ requires root
191
+
192
+ # Create an external user namespace for us to join (we can't mount from
193
+ # inside the user namespace so we need to background it to do the mount
194
+ # from the host).
195
+ userns_path=" $( mktemp " $BATS_RUN_TMPDIR /userns.XXXXXX" ) "
196
+ unshare -U -- sleep 3m &
197
+ userns_pid=" $! "
198
+ # Synchronise with the container startup...
199
+ cat " /proc/$userns_pid /uid_map" " /proc/$userns_pid /gid_map" >&2
200
+ # Configure the mapping to match the rootfs mapping.
201
+ echo " 0 100000 65534" > " /proc/$userns_pid /uid_map"
202
+ echo " 0 200000 65534" > " /proc/$userns_pid /gid_map"
203
+ # Stash the nsfsfd.
204
+ mount --bind " /proc/$userns_pid /ns/user" " $userns_path "
205
+ echo " $userns_path " >> " $to_umount_list "
206
+ # Kill the helper.
207
+ kill -9 " $userns_pid "
208
+
209
+ # Configure our container to attach to the external userns.
210
+ update_config ' .linux.namespaces |= map(if .type == "user" then (.path = "' " $userns_path " ' ") else . end)
211
+ | del(.linux.uidMappings)
212
+ | del(.linux.gidMappings)'
213
+
214
+ # Also create a network namespace that *is not owned* by the above userns.
215
+ # NOTE: Having no permissions in a namespaces makes it necessary to modify
216
+ # the config so that we don't get mount errors (for reference: no netns
217
+ # permissions == no sysfs mounts, no pidns permissoins == no procfs mounts,
218
+ # no utsns permissions == no sethostname(2), no ipc permissions == no
219
+ # mqueue mounts, etc).
220
+ netns_path=" $( mktemp " $BATS_RUN_TMPDIR /netns.XXXXXX" ) "
221
+ unshare -i -- mount --bind " /proc/self/ns/net" " $netns_path "
222
+ echo " $netns_path " >> " $to_umount_list "
223
+ # Configure our container to attach to the external netns.
224
+ update_config ' .linux.namespaces |= map(if .type == "network" then (.path = "' " $netns_path " ' ") else . end)'
225
+
226
+ # Convert sysfs mounts to a bind-mount from the host, to avoid the
227
+ # permission issues due to the netns setup we have.
228
+ update_config ' .mounts |= map((select(.type == "sysfs") | { "source": "/sys", "destination": .destination, "type": "bind", "options": ["rbind"] }) // .)'
229
+
230
+ # Create a detached container to verify the namespaces are correct.
231
+ update_config ' .process.args = ["sleep", "infinity"]'
232
+ runc --debug run -d --console-socket " $CONSOLE_SOCKET " ctr
233
+ [ " $status " -eq 0 ]
234
+
235
+ userns_id=" user:[$( stat -c " %i" " $userns_path " ) ]"
236
+ netns_id=" net:[$( stat -c " %i" " $netns_path " ) ]"
237
+
238
+ runc exec ctr readlink /proc/self/ns/user
239
+ [ " $status " -eq 0 ]
240
+ [[ " $output " == " $userns_id " ]]
241
+
242
+ runc exec ctr readlink /proc/self/ns/net
243
+ [ " $status " -eq 0 ]
244
+ [[ " $output " == " $netns_id " ]]
245
+ }
0 commit comments