@@ -167,3 +167,68 @@ function check_exec_debug() {
167167 [[ " ${output} " == * " level=debug" * ]]
168168 check_exec_debug " $output "
169169}
170+
171+ @test " runc exec --cgroup subcgroup [v2]" {
172+ requires root cgroups_v2
173+
174+ set_cgroups_path
175+ set_cgroup_mount_writable
176+
177+ __runc run -d --console-socket " $CONSOLE_SOCKET " test_busybox
178+ testcontainer test_busybox running
179+
180+ # Check we can't join non-existing subcgroup.
181+ runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
182+ [ " $status " -ne 0 ]
183+ [[ " $output " == * " adding pid " * " /nonexistent/cgroup.procs: no such file " * ]]
184+
185+ # Check we can join top-level cgroup (implicit).
186+ runc exec test_busybox grep ' ^0::/$' /proc/self/cgroup
187+ [ " $status " -eq 0 ]
188+
189+ # Check we can join top-level cgroup (explicit).
190+ runc exec --cgroup / test_busybox grep ' ^0::/$' /proc/self/cgroup
191+ [ " $status " -eq 0 ]
192+
193+ # Now move "init" to a subcgroup, and check it was moved.
194+ runc exec test_busybox sh -euc " mkdir /sys/fs/cgroup/foobar \
195+ && echo 1 > /sys/fs/cgroup/foobar/cgroup.procs \
196+ && grep -w foobar /proc/1/cgroup"
197+ [ " $status " -eq 0 ]
198+
199+ # The following part is taken from
200+ # @test "runc exec (cgroup v2 + init process in non-root cgroup) succeeds"
201+
202+ # The init process is now in "/foo", but an exec process can still
203+ # join "/" because we haven't enabled any domain controller yet.
204+ runc exec test_busybox grep ' ^0::/$' /proc/self/cgroup
205+ [ " $status " -eq 0 ]
206+
207+ # Turn on a domain controller (memory).
208+ runc exec test_busybox sh -euc ' echo $$ > /sys/fs/cgroup/foobar/cgroup.procs; echo +memory > /sys/fs/cgroup/cgroup.subtree_control'
209+ [ " $status " -eq 0 ]
210+
211+ # An exec process can no longer join "/" after turning on a domain
212+ # controller. Check that cgroup v2 fallback to init cgroup works.
213+ runc exec test_busybox sh -euc " cat /proc/self/cgroup && grep '^0::/foobar$' /proc/self/cgroup"
214+ [ " $status " -eq 0 ]
215+
216+ # Check that --cgroup / disables the init cgroup fallback.
217+ runc exec --cgroup / test_busybox true
218+ [ " $status " -ne 0 ]
219+ [[ " $output " == * " adding pid " * " to cgroups" * " /cgroup.procs: device or resource busy" * ]]
220+
221+ # Check that explicit --cgroup foobar works.
222+ runc exec --cgroup foobar test_busybox grep ' ^0::/foobar$' /proc/self/cgroup
223+ [ " $status " -eq 0 ]
224+
225+ # Check all processes is in foobar (this check is redundant).
226+ runc exec --cgroup foobar test_busybox sh -euc ' ! grep -vwH foobar /proc/*/cgroup'
227+ [ " $status " -eq 0 ]
228+
229+ # Add a second subcgroup, check we're in it.
230+ runc exec --cgroup foobar test_busybox mkdir /sys/fs/cgroup/second
231+ [ " $status " -eq 0 ]
232+ runc exec --cgroup second test_busybox grep -w second /proc/self/cgroup
233+ [ " $status " -eq 0 ]
234+ }
0 commit comments