...
1#!/usr/bin/env bats
2
3load helpers
4
5function setup() {
6 setup_busybox
7}
8
9function teardown() {
10 teardown_bundle
11}
12
13@test "runc exec" {
14 # run busybox detached
15 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
16 [ "$status" -eq 0 ]
17
18 runc exec test_busybox echo Hello from exec
19 [ "$status" -eq 0 ]
20 echo text echoed = "'""${output}""'"
21 [[ "${output}" == *"Hello from exec"* ]]
22}
23
24@test "runc exec [exit codes]" {
25 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
26 [ "$status" -eq 0 ]
27
28 runc exec test_busybox false
29 [ "$status" -eq 1 ]
30
31 runc exec test_busybox sh -c "exit 42"
32 [ "$status" -eq 42 ]
33
34 runc exec --pid-file /non-existent/directory test_busybox true
35 [ "$status" -eq 255 ]
36
37 runc exec test_busybox no-such-binary
38 [ "$status" -eq 255 ]
39
40 runc exec no_such_container true
41 [ "$status" -eq 255 ]
42}
43
44@test "runc exec --pid-file" {
45 # run busybox detached
46 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
47 [ "$status" -eq 0 ]
48
49 runc exec --pid-file pid.txt test_busybox echo Hello from exec
50 [ "$status" -eq 0 ]
51 echo text echoed = "'""${output}""'"
52 [[ "${output}" == *"Hello from exec"* ]]
53
54 # check pid.txt was generated
55 [ -e pid.txt ]
56
57 output=$(cat pid.txt)
58 [[ "$output" =~ [0-9]+ ]]
59 [[ "$output" != $(__runc state test_busybox | jq '.pid') ]]
60}
61
62@test "runc exec --pid-file with new CWD" {
63 bundle="$(pwd)"
64 # create pid_file directory as the CWD
65 mkdir pid_file
66 cd pid_file
67
68 # run busybox detached
69 runc run -d -b "$bundle" --console-socket "$CONSOLE_SOCKET" test_busybox
70 [ "$status" -eq 0 ]
71
72 runc exec --pid-file pid.txt test_busybox echo Hello from exec
73 [ "$status" -eq 0 ]
74 echo text echoed = "'""${output}""'"
75 [[ "${output}" == *"Hello from exec"* ]]
76
77 # check pid.txt was generated
78 [ -e pid.txt ]
79
80 output=$(cat pid.txt)
81 [[ "$output" =~ [0-9]+ ]]
82 [[ "$output" != $(__runc state test_busybox | jq '.pid') ]]
83}
84
85@test "runc exec ls -la" {
86 # run busybox detached
87 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
88 [ "$status" -eq 0 ]
89
90 runc exec test_busybox ls -la
91 [ "$status" -eq 0 ]
92 [[ ${lines[0]} == *"total"* ]]
93 [[ ${lines[1]} == *"."* ]]
94 [[ ${lines[2]} == *".."* ]]
95}
96
97@test "runc exec ls -la with --cwd" {
98 # run busybox detached
99 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
100 [ "$status" -eq 0 ]
101
102 runc exec --cwd /bin test_busybox pwd
103 [ "$status" -eq 0 ]
104 [[ ${output} == "/bin"* ]]
105}
106
107@test "runc exec --env" {
108 # run busybox detached
109 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
110 [ "$status" -eq 0 ]
111
112 runc exec --env RUNC_EXEC_TEST=true test_busybox env
113 [ "$status" -eq 0 ]
114
115 [[ ${output} == *"RUNC_EXEC_TEST=true"* ]]
116}
117
118@test "runc exec --user" {
119 # --user can't work in rootless containers that don't have idmap.
120 [[ "$ROOTLESS" -ne 0 ]] && requires rootless_idmap
121
122 # run busybox detached
123 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
124 [ "$status" -eq 0 ]
125
126 runc exec --user 1000:1000 test_busybox id
127 [ "$status" -eq 0 ]
128 [[ "${output}" == "uid=1000 gid=1000"* ]]
129}
130
131# https://github.com/opencontainers/runc/issues/3674.
132@test "runc exec --user vs /dev/null ownership" {
133 requires root
134
135 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
136 [ "$status" -eq 0 ]
137
138 ls -l /dev/null
139 __runc exec -d --user 1000:1000 test_busybox id </dev/null
140 ls -l /dev/null
141 UG=$(stat -c %u:%g /dev/null)
142
143 # Host's /dev/null must be owned by root.
144 [ "$UG" = "0:0" ]
145}
146
147@test "runc exec --additional-gids" {
148 requires root
149
150 # run busybox detached
151 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
152 [ "$status" -eq 0 ]
153
154 wait_for_container 15 1 test_busybox
155
156 runc exec --user 1000:1000 --additional-gids 100 --additional-gids 65534 test_busybox id -G
157 [ "$status" -eq 0 ]
158
159 [[ ${output} == "1000 100 65534" ]]
160}
161
162@test "runc exec --preserve-fds" {
163 # run busybox detached
164 runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
165 [ "$status" -eq 0 ]
166
167 echo hello >preserve-fds.test
168 # fd 3 is used by bats, so we use 4
169 exec 4<preserve-fds.test
170 runc exec --preserve-fds=2 test_busybox cat /proc/self/fd/4
171 [ "$status" -eq 0 ]
172 [[ "${output}" == "hello" ]]
173}
174
175function check_exec_debug() {
176 [[ "$*" == *"nsexec container setup"* ]]
177 [[ "$*" == *"child process in init()"* ]]
178 [[ "$*" == *"setns_init: about to exec"* ]]
179}
180
181@test "runc --debug exec" {
182 runc run -d --console-socket "$CONSOLE_SOCKET" test
183 [ "$status" -eq 0 ]
184
185 runc --debug exec test true
186 [ "$status" -eq 0 ]
187 [[ "${output}" == *"level=debug"* ]]
188 check_exec_debug "$output"
189}
190
191@test "runc --debug --log exec" {
192 runc run -d --console-socket "$CONSOLE_SOCKET" test
193 [ "$status" -eq 0 ]
194
195 runc --debug --log log.out exec test true
196 # check output does not include debug info
197 [[ "${output}" != *"level=debug"* ]]
198
199 cat log.out >&2
200 # check expected debug output was sent to log.out
201 output=$(cat log.out)
202 [[ "${output}" == *"level=debug"* ]]
203 check_exec_debug "$output"
204}
205
206@test "runc exec --cgroup sub-cgroups [v1]" {
207 requires root cgroups_v1
208
209 set_cgroups_path
210 set_cgroup_mount_writable
211
212 __runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
213 testcontainer test_busybox running
214
215 # Check we can't join parent cgroup.
216 runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
217 [ "$status" -ne 0 ]
218 [[ "$output" == *" .. is not a sub cgroup path"* ]]
219
220 # Check we can't join non-existing subcgroup.
221 runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
222 [ "$status" -ne 0 ]
223 [[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
224
225 # Check we can't join non-existing subcgroup (for a particular controller).
226 runc exec --cgroup cpu:nonexistent test_busybox cat /proc/self/cgroup
227 [ "$status" -ne 0 ]
228 [[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
229
230 # Check we can't specify non-existent controller.
231 runc exec --cgroup whaaat:/ test_busybox true
232 [ "$status" -ne 0 ]
233 [[ "$output" == *"unknown controller "* ]]
234
235 # Check we can join top-level cgroup (implicit).
236 runc exec test_busybox cat /proc/self/cgroup
237 [ "$status" -eq 0 ]
238 run ! grep -v ":$REL_CGROUPS_PATH\$" <<<"$output"
239
240 # Check we can join top-level cgroup (explicit).
241 runc exec --cgroup / test_busybox cat /proc/self/cgroup
242 [ "$status" -eq 0 ]
243 run ! grep -v ":$REL_CGROUPS_PATH\$" <<<"$output"
244
245 # Create a few subcgroups.
246 # Note that cpu,cpuacct may be mounted together or separate.
247 runc exec test_busybox sh -euc "mkdir -p /sys/fs/cgroup/memory/submem /sys/fs/cgroup/cpu/subcpu /sys/fs/cgroup/cpuacct/subcpu"
248 [ "$status" -eq 0 ]
249
250 # Check that explicit --cgroup works.
251 runc exec --cgroup memory:submem --cgroup cpu,cpuacct:subcpu test_busybox cat /proc/self/cgroup
252 [ "$status" -eq 0 ]
253 [[ "$output" == *":memory:$REL_CGROUPS_PATH/submem"* ]]
254 [[ "$output" == *":cpu"*":$REL_CGROUPS_PATH/subcpu"* ]]
255}
256
257@test "runc exec --cgroup subcgroup [v2]" {
258 requires root cgroups_v2
259
260 set_cgroups_path
261 set_cgroup_mount_writable
262
263 __runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
264 testcontainer test_busybox running
265
266 # Check we can't join parent cgroup.
267 runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
268 [ "$status" -ne 0 ]
269 [[ "$output" == *" .. is not a sub cgroup path"* ]]
270
271 # Check we can't join non-existing subcgroup.
272 runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
273 [ "$status" -ne 0 ]
274 [[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
275
276 # Check we can join top-level cgroup (implicit).
277 runc exec test_busybox grep '^0::/$' /proc/self/cgroup
278 [ "$status" -eq 0 ]
279
280 # Check we can join top-level cgroup (explicit).
281 runc exec --cgroup / test_busybox grep '^0::/$' /proc/self/cgroup
282 [ "$status" -eq 0 ]
283
284 # Now move "init" to a subcgroup, and check it was moved.
285 runc exec test_busybox sh -euc "mkdir /sys/fs/cgroup/foobar \
286 && echo 1 > /sys/fs/cgroup/foobar/cgroup.procs \
287 && grep -w foobar /proc/1/cgroup"
288 [ "$status" -eq 0 ]
289
290 # The following part is taken from
291 # @test "runc exec (cgroup v2 + init process in non-root cgroup) succeeds"
292
293 # The init process is now in "/foo", but an exec process can still
294 # join "/" because we haven't enabled any domain controller yet.
295 runc exec test_busybox grep '^0::/$' /proc/self/cgroup
296 [ "$status" -eq 0 ]
297
298 # Turn on a domain controller (memory).
299 runc exec test_busybox sh -euc 'echo $$ > /sys/fs/cgroup/foobar/cgroup.procs; echo +memory > /sys/fs/cgroup/cgroup.subtree_control'
300 [ "$status" -eq 0 ]
301
302 # An exec process can no longer join "/" after turning on a domain
303 # controller. Check that cgroup v2 fallback to init cgroup works.
304 runc exec test_busybox sh -euc "cat /proc/self/cgroup && grep '^0::/foobar$' /proc/self/cgroup"
305 [ "$status" -eq 0 ]
306
307 # Check that --cgroup / disables the init cgroup fallback.
308 runc exec --cgroup / test_busybox true
309 [ "$status" -ne 0 ]
310 [[ "$output" == *" adding pid "*" to cgroups"*"/cgroup.procs: device or resource busy"* ]]
311
312 # Check that explicit --cgroup foobar works.
313 runc exec --cgroup foobar test_busybox grep '^0::/foobar$' /proc/self/cgroup
314 [ "$status" -eq 0 ]
315
316 # Check all processes is in foobar (this check is redundant).
317 runc exec --cgroup foobar test_busybox sh -euc '! grep -vwH foobar /proc/*/cgroup'
318 [ "$status" -eq 0 ]
319
320 # Add a second subcgroup, check we're in it.
321 runc exec --cgroup foobar test_busybox mkdir /sys/fs/cgroup/second
322 [ "$status" -eq 0 ]
323 runc exec --cgroup second test_busybox grep -w second /proc/self/cgroup
324 [ "$status" -eq 0 ]
325}
View as plain text