From 1942efc9c4b776257707e78bffff0c50c16b475c Mon Sep 17 00:00:00 2001 From: Michal Sieron Date: Thu, 21 Nov 2024 16:26:00 +0100 Subject: [PATCH] Handle case where cgroup v1 freezer is disabled On cgroup v1 it is possible to disable freezer subsystem. In such case freezer.state file won't be present. Due to the race condition handling in libcrun_get_container_state_string, missing freezer.state would be interpreted as cgroup being removed when check is being performed. But as indicated earlier, that is not the case when it's cgroup v1 and the freezer is disabled. Therefore introduce logic that checks for that using type of the filesystem mounted under the freezer directory. When freezer is disabled, container simply cannot be paused. Fixes #1612 Signed-off-by: Michal Sieron --- src/libcrun/cgroup.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/libcrun/cgroup.c b/src/libcrun/cgroup.c index 846023c93..781a34e4e 100644 --- a/src/libcrun/cgroup.c +++ b/src/libcrun/cgroup.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -142,7 +143,41 @@ libcrun_cgroup_is_container_paused (struct libcrun_cgroup_status *status, bool * ret = read_all_file (path, &content, NULL, err); if (UNLIKELY (ret < 0)) - return ret; + { + errno = crun_error_get_errno (err); + /* If the file is missing and we were checking for freezer.state + (so either cgroup v1 or hybrid), it may be the freezer is + simply disabled. In such case the container cannot be paused. + On cgroup v2 freezer is always there. + */ + if (errno != ENOENT || cgroup_mode == CGROUP_MODE_UNIFIED) + return ret; + + /* Even with freezer disabled, its directory is still there. But + when it's disabled it has type tmpfs, while on systems with + freezer enabled, its type is cgroupfs. Use that to determine + whether freezer is enabled or not. + */ + struct statfs freezer_stat; + if (statfs (CGROUP_ROOT "/freezer", &freezer_stat)) + { + crun_error_release (err); + return crun_make_error (err, errno, "error when using statfs on `%s`", CGROUP_ROOT "/freezer"); + } + + /* If the freezer is mounted as cgroupfs type, then missing + freezer.state file is an error and should be handled like before. + */ + if (freezer_stat.f_type == CGROUP_SUPER_MAGIC) + return ret; + + /* When freezer dir is not mounted as cgroupfs, then it's + disabled, therefore container cannot be in paused state. + */ + crun_error_release (err); + *paused = false; + return 0; + } *paused = strstr (content, state) != NULL; return 0;