Forking git processes fails with 'EACCES' on hosts with cgroups-v2 enabled

On a host with cgroups-v2 enabled, Gitaly is unable to add its child processes to the target gitaly/gitaly-<PID>/repos-<N> cgroup due to delegation containment rules that were not present with cgroups-v1. These specify that the user must have write access to the common ancestor of the source and target cgroups.

When forking the process and then adding the new process to the cgroup the write to cgroup.procs fails:

26066 14:15:42.933792 write(16</sys/fs/cgroup/gitaly/gitaly-26066/repos-530/cgroup.procs>, "26151", 5 = -1 EACCES (Permission denied) <0.009410>

When the CLONE_INTO_CGROUP feature is used for child git processes, the clone3 call invoked by Gitaly will fail with EACCES.

52789 15:29:09.271953 clone3({flags=CLONE_VM|CLONE_VFORK|CLONE_INTO_CGROUP, exit_signal=SIGCHLD, stack=NULL, stack_size=0, cgroup=15}, 88 = -1 EACCES (Permission denied) <0.000080>

In an Omnibus install, Gitaly runs in /sys/fs/cgroup/system.slice/gitlab-runsvdir.service, with the target being /sys/fs/cgroup/gitaly/gitaly-<PID>/repos-<REPO_BUCKET>, making the common ancestor the root /sys/fs/cgroup.

One option would be to move the Gitaly process to a cgroup within the /sys/fs/cgroup/gitaly tree, e.g. /sys/fs/cgroup/gitaly/gitaly-<PID>/gitaly-main, resolves this error. This lets us use the hierarchy defined by the admin in config.toml, but requires Omnibus to move the Gitaly process to the cgroup.

Another option is to create the Gitaly cgroup hierarchy within /system.slice/gitlab-runsvdir.service, which is operationally simpler. This won't work as gitlab-runsvdir.service is a leaf node and cannot have child groups that contain processes.

Edited by Emily Chui
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information