@@ -348,13 +348,13 @@ move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libc
348348}
349349
350350static int
351- enter_cgroup_subsystem (pid_t pid , const char * subsystem , const char * path , int ensure_missing , libcrun_error_t * err )
351+ enter_cgroup_subsystem (pid_t pid , const char * subsystem , const char * path , bool create_if_missing , libcrun_error_t * err )
352352{
353353 cleanup_free char * cgroup_path = NULL ;
354354 int ret ;
355355
356356 xasprintf (& cgroup_path , "/sys/fs/cgroup/%s%s" , subsystem , path ? path : "" );
357- if (ensure_missing )
357+ if (create_if_missing )
358358 {
359359 ret = crun_ensure_directory (cgroup_path , 0755 , false, err );
360360 if (UNLIKELY (ret < 0 ))
@@ -482,54 +482,45 @@ copy_owner (const char *from, const char *to, libcrun_error_t *err)
482482}
483483
484484static int
485- enter_cgroup ( int cgroup_mode , pid_t pid , const char * path , bool ensure_missing , libcrun_error_t * err )
485+ read_unified_cgroup_pid ( pid_t pid , char * * path , libcrun_error_t * err )
486486{
487- char pid_str [16 ];
488487 int ret ;
489- size_t i ;
490- int entered_any = 0 ;
491- int rootless ;
492- const cgroups_subsystem_t * subsystems ;
488+ char cgroup_path [32 ];
489+ char * from , * to ;
490+ cleanup_free char * content = NULL ;
493491
494- sprintf (pid_str , "%d " , pid );
492+ sprintf (cgroup_path , "/proc/%d/cgroup " , pid );
495493
496- if (cgroup_mode == CGROUP_MODE_UNIFIED )
497- {
498- cleanup_free char * cgroup_path_procs = NULL ;
499- cleanup_free char * cgroup_path = NULL ;
494+ ret = read_all_file (cgroup_path , & content , NULL , err );
495+ if (UNLIKELY (ret < 0 ))
496+ return ret ;
500497
501- xasprintf (& cgroup_path , "/sys/fs/cgroup/%s" , path );
502- if (ensure_missing )
503- {
504- ret = crun_ensure_directory (cgroup_path , 0755 , false, err );
505- if (UNLIKELY (ret < 0 ))
506- return ret ;
507- }
498+ from = strstr (content , "0::" );
499+ if (UNLIKELY (from == NULL ))
500+ return crun_make_error (err , -1 , "cannot find cgroup2 for the process %d" , pid );
508501
509- xasprintf (& cgroup_path_procs , "/sys/fs/cgroup/%s/cgroup.procs" , path );
510- ret = write_file (cgroup_path_procs , pid_str , strlen (pid_str ), err );
511- if (UNLIKELY (ret < 0 ))
512- {
513- if (!ensure_missing && (* err )-> status == EBUSY )
514- {
515- /* There are subdirectories so it is not possible to join the initial
516- cgroup. Create a subdirectory and use that.
517- It can still fail if the container creates a subdirectory under
518- /sys/fs/cgroup/../crun-exec/ */
519- cleanup_free char * cgroup_crun_exec_path = NULL ;
502+ from += 3 ;
503+ to = strchr (from , '\n' );
504+ to = strchr (from , '\n' );
505+ if (UNLIKELY (to == NULL ))
506+ return crun_make_error (err , -1 , "cannot parse `%s`" , cgroup_path );
507+ * to = '\0' ;
520508
521- xasprintf (& cgroup_crun_exec_path , "%s/crun-exec" , path );
509+ * path = xstrdup (from );
510+ return 0 ;
511+ }
522512
523- ret = enter_cgroup (cgroup_mode , pid , cgroup_crun_exec_path , true, err );
524- if (UNLIKELY (ret < 0 ))
525- return ret ;
513+ static int
514+ enter_cgroup_v1 (int cgroup_mode , pid_t pid , const char * path , bool create_if_missing , libcrun_error_t * err )
515+ {
516+ char pid_str [16 ];
517+ int ret ;
518+ size_t i ;
519+ int entered_any = 0 ;
520+ int rootless ;
521+ const cgroups_subsystem_t * subsystems ;
526522
527- return copy_owner (cgroup_path_procs , cgroup_crun_exec_path , err );
528- }
529- return ret ;
530- }
531- return 0 ;
532- }
523+ sprintf (pid_str , "%d" , pid );
533524
534525 subsystems = libcrun_get_cgroups_subsystems (err );
535526 if (UNLIKELY (subsystems == NULL ))
@@ -554,7 +545,7 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing,
554545 continue ;
555546
556547 entered_any = 1 ;
557- ret = enter_cgroup_subsystem (pid , subsystems [i ], path , ensure_missing , err );
548+ ret = enter_cgroup_subsystem (pid , subsystems [i ], path , create_if_missing , err );
558549 if (UNLIKELY (ret < 0 ))
559550 {
560551 int errcode = crun_error_get_errno (err );
@@ -570,6 +561,91 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing,
570561 return entered_any ? 0 : -1 ;
571562}
572563
564+ static int
565+ enter_cgroup_v2 (pid_t pid , pid_t init_pid , const char * path , bool create_if_missing , libcrun_error_t * err )
566+ {
567+ cleanup_free char * cgroup_path_procs = NULL ;
568+ cleanup_free char * cgroup_path = NULL ;
569+ char pid_str [16 ];
570+ int repeat ;
571+ int ret ;
572+
573+ sprintf (pid_str , "%d" , pid );
574+
575+ xasprintf (& cgroup_path , "/sys/fs/cgroup/%s" , path );
576+ if (create_if_missing )
577+ {
578+ ret = crun_ensure_directory (cgroup_path , 0755 , false, err );
579+ if (UNLIKELY (ret < 0 ))
580+ return ret ;
581+ }
582+
583+ xasprintf (& cgroup_path_procs , "/sys/fs/cgroup/%s/cgroup.procs" , path );
584+ ret = write_file (cgroup_path_procs , pid_str , strlen (pid_str ), err );
585+ if (LIKELY (ret == 0 ))
586+ return ret ;
587+
588+ /* If the cgroup is not being created, try to handle EBUSY. */
589+ if (create_if_missing || crun_error_get_errno (err ) != EBUSY )
590+ return ret ;
591+
592+ crun_error_release (err );
593+
594+ /* There are subdirectories so it is not possible to join the initial
595+ cgroup. Create a subdirectory and use that.
596+ It can still fail if the container creates a subdirectory under
597+ /sys/fs/cgroup/../crun-exec/ */
598+ for (repeat = 0 ;; repeat ++ )
599+ {
600+ cleanup_free char * cgroup_crun_exec_path = NULL ;
601+ cleanup_free char * cgroup_sub_path_procs = NULL ;
602+
603+ /* There is an init pid, try to join its cgroup. */
604+ if (init_pid > 0 )
605+ {
606+ ret = read_unified_cgroup_pid (init_pid , & cgroup_crun_exec_path , err );
607+ if (UNLIKELY (ret < 0 ))
608+ return ret ;
609+
610+ /* Make sure the cgroup is below the initial cgroup specified for the container. */
611+ if (strncmp (path , cgroup_crun_exec_path , strlen (path )))
612+ {
613+ free (cgroup_crun_exec_path );
614+ cgroup_crun_exec_path = NULL ;
615+ }
616+ }
617+
618+ /* There is no init_pid to lookup, try a static path. */
619+ if (cgroup_crun_exec_path == NULL )
620+ xasprintf (& cgroup_crun_exec_path , "%s/crun-exec" , path );
621+
622+ xasprintf (& cgroup_sub_path_procs , "/sys/fs/cgroup/%s/cgroup.procs" , cgroup_crun_exec_path );
623+
624+ ret = write_file (cgroup_sub_path_procs , pid_str , strlen (pid_str ), err );
625+ if (UNLIKELY (ret < 0 ))
626+ {
627+ /* The init process might have moved to a different cgroup, try again. */
628+ if (crun_error_get_errno (err ) == EBUSY && init_pid && repeat < 20 )
629+ {
630+ crun_error_release (err );
631+ continue ;
632+ }
633+ return ret ;
634+ }
635+ return copy_owner (cgroup_path_procs , cgroup_crun_exec_path , err );
636+ }
637+ return ret ;
638+ }
639+
640+ static int
641+ enter_cgroup (int cgroup_mode , pid_t pid , pid_t init_pid , const char * path , bool create_if_missing , libcrun_error_t * err )
642+ {
643+ if (cgroup_mode == CGROUP_MODE_UNIFIED )
644+ return enter_cgroup_v2 (pid , init_pid , path , create_if_missing , err );
645+
646+ return enter_cgroup_v1 (cgroup_mode , pid , path , create_if_missing , err );
647+ }
648+
573649int
574650libcrun_cgroups_create_symlinks (int dirfd , libcrun_error_t * err )
575651{
@@ -591,7 +667,7 @@ libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err)
591667}
592668
593669int
594- libcrun_move_process_to_cgroup (pid_t pid , char * path , libcrun_error_t * err )
670+ libcrun_move_process_to_cgroup (pid_t pid , pid_t init_pid , char * path , libcrun_error_t * err )
595671{
596672 int cgroup_mode = libcrun_get_cgroup_mode (err );
597673 if (UNLIKELY (cgroup_mode < 0 ))
@@ -600,7 +676,7 @@ libcrun_move_process_to_cgroup (pid_t pid, char *path, libcrun_error_t *err)
600676 if (path == NULL || * path == '\0' )
601677 return 0 ;
602678
603- return enter_cgroup (cgroup_mode , pid , path , false, err );
679+ return enter_cgroup (cgroup_mode , pid , init_pid , path , false, err );
604680}
605681
606682#ifdef HAVE_SYSTEMD
@@ -1221,7 +1297,7 @@ libcrun_cgroup_enter_cgroupfs (struct libcrun_cgroup_args *args, libcrun_error_t
12211297 return ret ;
12221298 }
12231299
1224- return enter_cgroup (cgroup_mode , pid , * path , true, err );
1300+ return enter_cgroup (cgroup_mode , pid , 0 , * path , true, err );
12251301}
12261302
12271303static int
0 commit comments