From 26e0dea1270556b08c37c20da9db229de664dbd1 Mon Sep 17 00:00:00 2001
From: jikai <jikai11@huawei.com>
Date: Fri, 23 Feb 2024 17:30:12 +0800
Subject: [PATCH] unfreeze freezing container and bugfix for files.limit and
 syscontainer

1. container in the freezing state must be unfreeze
https://gitee.com/src-openeuler/lxc/pulls/498

2. bugfix for files.limit invalid
should return false if failed to write cgroup.procs after max times,
or will lead to files.limit invalid

3. run oci-prestart hook before switch root
In: https://gitee.com/src-openeuler/lxc/pulls/513, we move oci-prestart hook
after sync_cgroup_limits, for sync_cgroup_limits will write a *:* rwm device rule
which will lead the device rule we write in oci-prestart hook useless.
However the modification move oci-prestart hook after change root.
We restore the changes. Since setup_limits_legacy will do the a *:* rwm write,
we only ensure that setup_limits_legacy executes before oci-prestart.

Signed-off-by: jikai <jikai11@huawei.com>
---
 src/lxc/cgroups/cgfsng.c |  2 ++
 src/lxc/conf.c           |  6 ++++
 src/lxc/lxccontainer.c   |  7 +++++
 src/lxc/start.c          | 61 +++++++++++++++++++++++++---------------
 src/lxc/sync.c           |  6 ++--
 src/lxc/sync.h           | 10 ++++---
 6 files changed, 62 insertions(+), 30 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 471c281..311bdf7 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1889,6 +1889,8 @@ retry:
 				retry_count++;
 				goto retry;
 			}
+			SYSERROR("Failed to enter cgroup \"%s/cgroup.procs\"", h->path_con);
+			return false;
 		}
 #else
 		ret = lxc_writeat(h->dfd_con, "cgroup.procs", pidstr, len);
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 595e605..9e7f6a2 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4900,6 +4900,12 @@ int lxc_setup(struct lxc_handler *handler)
 	if (ret < 0)
 		return log_error(-1, "Failed to setup \"/dev\" symlinks");
 
+#ifdef HAVE_ISULAD
+	/* Ask parent to run oci prestart hooks and wait for him to finish. */
+	if (!lxc_sync_barrier_parent(handler, START_SYNC_OCI_PRESTART_HOOK)) {
+		return log_error(-1, "Failed to sync parent to start host hook");
+	}
+#endif
 	ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs);
 	if (ret < 0)
 		return log_error(-1, "Failed to pivot root into rootfs");
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 5720cf7..318b7f5 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -560,7 +560,14 @@ static bool do_lxcapi_unfreeze(struct lxc_container *c)
 		return false;
 
 	s = lxc_getstate(c->name, c->config_path);
+#ifdef HAVE_ISULAD
+	// Prevent lxc from unexpectedly exiting when executing freeze,
+	// causing the container to be in the FREEZING state,
+	// making normal life cycle management impossible.
+	if (s == FROZEN || s == FREEZING) {
+#else
 	if (s == FROZEN) {
+#endif
 		ret = cgroup_unfreeze(c->name, c->config_path, -1);
 		if (ret == -ENOCGROUP2)
 			ret = lxc_unfreeze(c->lxc_conf, c->name, c->config_path);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 0a5cb26..2fea7b0 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1643,11 +1643,6 @@ static int do_start(void *data)
 	}
 
 #ifdef HAVE_ISULAD
-	/* Ask father to run oci prestart hooks and wait for him to finish. */
-	if (!lxc_sync_barrier_parent(handler, START_SYNC_OCI_PRESTART_HOOK)) {
-		return log_error(-1, "Failed to sync parent to start host hook");
-	}
-
 	/* close pipes after sync fds */
 	/* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */
 	if (handler->disable_pty) {
@@ -2383,7 +2378,9 @@ static int lxc_spawn(struct lxc_handler *handler)
 		goto out_delete_net;
 	}
 
-	if (!lxc_sync_wait_child(handler, START_SYNC_CGROUP_LIMITS))
+#ifdef HAVE_ISULAD
+	// OCI prestart hook should run before lxc_setup_rootfs_switch_root.
+	if (!lxc_sync_wait_child(handler, START_SYNC_OCI_PRESTART_HOOK))
 		goto out_delete_net;
 
 	/*
@@ -2403,25 +2400,8 @@ static int lxc_spawn(struct lxc_handler *handler)
 	}
 	TRACE("Set up cgroup2 device controller limits");
 
-	cgroup_ops->finalize(cgroup_ops);
-	TRACE("Finished setting up cgroups");
-
-	/* Run any host-side start hooks */
-	ret = run_lxc_hooks(name, "start-host", conf, NULL);
-	if (ret < 0) {
-		ERROR("Failed to run lxc.hook.start-host");
-		goto out_delete_net;
-	}
-
-	if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
-		goto out_delete_net;
-
-#ifdef HAVE_ISULAD
 	// OCI prestart hook should run after setup_limits_legacy.
 	// Otherwise 'syscontainer-hooks' write devices rule will be useless.
-	if (!lxc_sync_wait_child(handler, START_SYNC_OCI_PRESTART_HOOK))
-		goto out_delete_net;
-
 	/* isulad: Run oci prestart hook at here */
 	ret = run_oci_hooks(name, "oci-prestart", conf, lxcpath);
 	if (ret < 0) {
@@ -2442,6 +2422,41 @@ static int lxc_spawn(struct lxc_handler *handler)
 		goto out_delete_net;
 #endif
 
+	if (!lxc_sync_wait_child(handler, START_SYNC_CGROUP_LIMITS))
+		goto out_delete_net;
+
+#ifndef HAVE_ISULAD
+	/*
+	 * With isolation the limiting devices cgroup was already setup, so
+	 * only setup devices here if we have no namespace directory.
+	 */
+	if (!handler->conf->cgroup_meta.namespace_dir &&
+	    !cgroup_ops->setup_limits_legacy(cgroup_ops, handler->conf, true)) {
+		ERROR("Failed to setup legacy device cgroup controller limits");
+		goto out_delete_net;
+	}
+	TRACE("Set up legacy device cgroup controller limits");
+
+	if (!cgroup_ops->devices_activate(cgroup_ops, handler)) {
+		ERROR("Failed to setup cgroup2 device controller limits");
+		goto out_delete_net;
+	}
+	TRACE("Set up cgroup2 device controller limits");
+#endif
+
+	cgroup_ops->finalize(cgroup_ops);
+	TRACE("Finished setting up cgroups");
+
+	/* Run any host-side start hooks */
+	ret = run_lxc_hooks(name, "start-host", conf, NULL);
+	if (ret < 0) {
+		ERROR("Failed to run lxc.hook.start-host");
+		goto out_delete_net;
+	}
+
+	if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
+		goto out_delete_net;
+
 	if (handler->ns_unshare_flags & CLONE_NEWCGROUP) {
 		/* Now we're ready to preserve the cgroup namespace */
 		ret = lxc_try_preserve_namespace(handler, LXC_NS_CGROUP, "cgroup");
diff --git a/src/lxc/sync.c b/src/lxc/sync.c
index f156809..09d932b 100644
--- a/src/lxc/sync.c
+++ b/src/lxc/sync.c
@@ -66,16 +66,16 @@ static inline const char *start_sync_to_string(int state)
 		return "configure";
 	case START_SYNC_POST_CONFIGURE:
 		return "post-configure";
-	case START_SYNC_CGROUP_LIMITS:
-		return "cgroup-limits";
 	case START_SYNC_IDMAPPED_MOUNTS:
 		return "idmapped-mounts";
-#ifdef HAVE_ISULAd
+#ifdef HAVE_ISULAD
 	case START_SYNC_OCI_PRESTART_HOOK:
 		return "oci-prestart-hook";
 	case START_SYNC_POST_OCI_PRESTART_HOOK:
 		return "post-oci-prestart-hook";
 #endif
+	case START_SYNC_CGROUP_LIMITS:
+		return "cgroup-limits";
 	case START_SYNC_FDS:
 		return "fds";
 	case START_SYNC_READY_START:
diff --git a/src/lxc/sync.h b/src/lxc/sync.h
index b6080dd..6802d32 100644
--- a/src/lxc/sync.h
+++ b/src/lxc/sync.h
@@ -20,15 +20,17 @@ enum /* start */ {
 	START_SYNC_CONFIGURE		=  1,
 	START_SYNC_POST_CONFIGURE	=  2,
 	START_SYNC_IDMAPPED_MOUNTS	=  3,
-	START_SYNC_CGROUP_LIMITS	=  4,
-	START_SYNC_FDS			=  5,
 #ifdef HAVE_ISULAD
-	START_SYNC_OCI_PRESTART_HOOK = 6,
-	START_SYNC_POST_OCI_PRESTART_HOOK = 7,
+	START_SYNC_OCI_PRESTART_HOOK = 4,
+	START_SYNC_POST_OCI_PRESTART_HOOK = 5,
+	START_SYNC_CGROUP_LIMITS	=  6,
+	START_SYNC_FDS			=  7,
 	START_SYNC_READY_START		=  8,
 	START_SYNC_RESTART		=  9,
 	START_SYNC_POST_RESTART		=  10,
 #else
+	START_SYNC_CGROUP_LIMITS	=  4,
+	START_SYNC_FDS			=  5,
 	START_SYNC_READY_START		=  6,
 	START_SYNC_RESTART		=  7,
 	START_SYNC_POST_RESTART		=  8,
-- 
2.33.0

