1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

nspawn: fix cgroup mode detection

cgroup mode detection is broken in two different ways.

* detect_unified_cgroup_hierarchy() is called too nested in outer_child().
  sync_cgroup() which is used by run() also needs to know the requested cgroup
  mode but it's currently always getting CGROUP_UNIFIED_UNKNOWN.  This makes it
  skip syncing the inner cgroup hierarchy on some config combinations.

   $ cat /proc/self/cgroup | grep systemd
   1:name=systemd:/user.slice/user-0.slice/session-c1.scope

   $ UNIFIED_CGROUP_HIERARCHY=0 SYSTEMD_NSPAWN_USE_CGNS=0 systemd-nspawn -M container
   ...
   [root@container ~]# cat /proc/self/cgroup | grep systemd
   1:name=systemd:/machine.slice/machine-container.x86_64.scope
   $ exit

   $ UNIFIED_CGROUP_HIERARCHY=1 SYSTEMD_NSPAWN_USE_CGNS=0 systemd-nspawn -M container
   [root@container ~]# cat /proc/self/cgroup | grep 0::
   0::/
   $ exit

  Note how the unified hierarchy case's path is not synchronized with the host.
  This for example can cause issues when there are multiple such containers.

  Fixed by moving detect_unified_cgroup_hierarchy() invocation to main().

* inner_child() was invoking cg_unified_flush().  inner_child() executes fully
  scoped and can't determine which cgroup mode the host was in.  It doesn't
  make sense to keep flushing the detected mode when the host mode can't
  change.

  Fixed by replacing cg_unified_flush() invocations in outer_child() and
  inner_child() with one in main().
This commit is contained in:
Tejun Heo 2016-11-21 14:45:53 -05:00 committed by Zbigniew Jędrzejewski-Szmek
parent 1e94df4471
commit bd15ab41a1

View File

@ -2168,8 +2168,6 @@ static int inner_child(
assert(directory);
assert(kmsg_socket >= 0);
cg_unified_flush();
if (arg_userns_mode != USER_NAMESPACE_NO) {
/* Tell the parent, that it now can write the UID map. */
(void) barrier_place(barrier); /* #1 */
@ -2440,8 +2438,6 @@ static int outer_child(
assert(notify_socket >= 0);
assert(kmsg_socket >= 0);
cg_unified_flush();
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
@ -2486,10 +2482,6 @@ static int outer_child(
if (r < 0)
return r;
r = detect_unified_cgroup_hierarchy(directory);
if (r < 0)
return r;
if (arg_userns_mode != USER_NAMESPACE_NO) {
/* Let the parent know which UID shift we read from the image */
l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL);
@ -3541,6 +3533,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
cg_unified_flush();
/* Make sure rename_process() in the stub init process can work */
saved_argv = argv;
@ -3810,6 +3803,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
r = detect_unified_cgroup_hierarchy(arg_directory);
if (r < 0)
goto finish;
interactive =
isatty(STDIN_FILENO) > 0 &&
isatty(STDOUT_FILENO) > 0;