@@ -187,3 +187,114 @@ function check_exec_debug() {
187187 [[ " ${output} " == * " level=debug" * ]]
188188 check_exec_debug " $output "
189189}
190+
191+ @test " runc exec --cgroup sub-cgroups [v1]" {
192+ requires root cgroups_v1
193+
194+ set_cgroups_path
195+ set_cgroup_mount_writable
196+
197+ __runc run -d --console-socket " $CONSOLE_SOCKET " test_busybox
198+ testcontainer test_busybox running
199+
200+ # Check we can't join non-existing subcgroup.
201+ runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
202+ [ " $status " -ne 0 ]
203+ [[ " $output " == * " adding pid " * " /nonexistent/cgroup.procs: no such file " * ]]
204+
205+ # Check we can't join non-existing subcgroup (for a particular controller).
206+ runc exec --cgroup cpu:nonexistent test_busybox cat /proc/self/cgroup
207+ [ " $status " -ne 0 ]
208+ [[ " $output " == * " adding pid " * " /nonexistent/cgroup.procs: no such file " * ]]
209+
210+ # Check we can't specify non-existent controller.
211+ runc exec --cgroup whaaat:/ test_busybox true
212+ [ " $status " -ne 0 ]
213+ [[ " $output " == * " unknown controller " * ]]
214+
215+ # Check we can join top-level cgroup (implicit).
216+ runc exec test_busybox cat /proc/self/cgroup
217+ [ " $status " -eq 0 ]
218+ ! grep -v " :$REL_CGROUPS_PATH \$ " <<< " $output"
219+
220+ # Check we can join top-level cgroup (explicit).
221+ runc exec --cgroup / test_busybox cat /proc/self/cgroup
222+ [ " $status " -eq 0 ]
223+ ! grep -v " :$REL_CGROUPS_PATH \$ " <<< " $output"
224+
225+ # Create a few subcgroups.
226+ # Note that cpu,cpuacct may be mounted together or separate.
227+ runc exec test_busybox sh -euc " mkdir -p /sys/fs/cgroup/memory/submem /sys/fs/cgroup/cpu/subcpu /sys/fs/cgroup/cpuacct/subcpu"
228+ [ " $status " -eq 0 ]
229+
230+ # Check that explicit --cgroup works.
231+ runc exec --cgroup memory:submem --cgroup cpu,cpuacct:subcpu test_busybox cat /proc/self/cgroup
232+ [ " $status " -eq 0 ]
233+ [[ " $output " == * " :memory:$REL_CGROUPS_PATH /submem" * ]]
234+ [[ " $output " == * " :cpu" * " :$REL_CGROUPS_PATH /subcpu" * ]]
235+ }
236+
237+ @test " runc exec --cgroup subcgroup [v2]" {
238+ requires root cgroups_v2
239+
240+ set_cgroups_path
241+ set_cgroup_mount_writable
242+
243+ __runc run -d --console-socket " $CONSOLE_SOCKET " test_busybox
244+ testcontainer test_busybox running
245+
246+ # Check we can't join non-existing subcgroup.
247+ runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
248+ [ " $status " -ne 0 ]
249+ [[ " $output " == * " adding pid " * " /nonexistent/cgroup.procs: no such file " * ]]
250+
251+ # Check we can join top-level cgroup (implicit).
252+ runc exec test_busybox grep ' ^0::/$' /proc/self/cgroup
253+ [ " $status " -eq 0 ]
254+
255+ # Check we can join top-level cgroup (explicit).
256+ runc exec --cgroup / test_busybox grep ' ^0::/$' /proc/self/cgroup
257+ [ " $status " -eq 0 ]
258+
259+ # Now move "init" to a subcgroup, and check it was moved.
260+ runc exec test_busybox sh -euc " mkdir /sys/fs/cgroup/foobar \
261+ && echo 1 > /sys/fs/cgroup/foobar/cgroup.procs \
262+ && grep -w foobar /proc/1/cgroup"
263+ [ " $status " -eq 0 ]
264+
265+ # The following part is taken from
266+ # @test "runc exec (cgroup v2 + init process in non-root cgroup) succeeds"
267+
268+ # The init process is now in "/foo", but an exec process can still
269+ # join "/" because we haven't enabled any domain controller yet.
270+ runc exec test_busybox grep ' ^0::/$' /proc/self/cgroup
271+ [ " $status " -eq 0 ]
272+
273+ # Turn on a domain controller (memory).
274+ runc exec test_busybox sh -euc ' echo $$ > /sys/fs/cgroup/foobar/cgroup.procs; echo +memory > /sys/fs/cgroup/cgroup.subtree_control'
275+ [ " $status " -eq 0 ]
276+
277+ # An exec process can no longer join "/" after turning on a domain
278+ # controller. Check that cgroup v2 fallback to init cgroup works.
279+ runc exec test_busybox sh -euc " cat /proc/self/cgroup && grep '^0::/foobar$' /proc/self/cgroup"
280+ [ " $status " -eq 0 ]
281+
282+ # Check that --cgroup / disables the init cgroup fallback.
283+ runc exec --cgroup / test_busybox true
284+ [ " $status " -ne 0 ]
285+ [[ " $output " == * " adding pid " * " to cgroups" * " /cgroup.procs: device or resource busy" * ]]
286+
287+ # Check that explicit --cgroup foobar works.
288+ runc exec --cgroup foobar test_busybox grep ' ^0::/foobar$' /proc/self/cgroup
289+ [ " $status " -eq 0 ]
290+
291+ # Check all processes is in foobar (this check is redundant).
292+ runc exec --cgroup foobar test_busybox sh -euc ' ! grep -vwH foobar /proc/*/cgroup'
293+ [ " $status " -eq 0 ]
294+
295+ # Add a second subcgroup, check we're in it.
296+ runc exec --cgroup foobar test_busybox mkdir /sys/fs/cgroup/second
297+ [ " $status " -eq 0 ]
298+ runc exec --cgroup second test_busybox grep -w second /proc/self/cgroup
299+ [ " $status " -eq 0 ]
300+ }
0 commit comments