[Devel] [RFC 25/54] cgroup-v1: fix CONFIG_VE=n build
Eva Kurchatova
eva.kurchatova at virtuozzo.com
Wed Apr 29 22:58:25 MSK 2026
Signed-off-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
---
kernel/cgroup/cgroup-v1.c | 100 +++++++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 6 deletions(-)
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index e4ef76e4bde6..f8a117d02d0b 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -39,6 +39,11 @@ static bool cgroup_no_v1_named;
*/
static struct workqueue_struct *cgroup_pidlist_destroy_wq;
+#ifndef CONFIG_VE
+/* protects cgroup_subsys->release_agent_path */
+static DEFINE_SPINLOCK(release_agent_path_lock);
+#endif
+
bool cgroup1_ssid_disabled(int ssid)
{
return cgroup_no_v1_mask & (1 << ssid);
@@ -548,10 +553,12 @@ static ssize_t cgroup1_tasks_write(struct kernfs_open_file *of,
static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off)
{
- struct cgroup *root_cgrp;
- struct ve_struct *ve = NULL;
struct cgroup *cgrp;
struct cgroup_file_ctx *ctx;
+
+#ifdef CONFIG_VE
+ struct cgroup *root_cgrp;
+ struct ve_struct *ve = NULL;
int ret;
/*
@@ -599,13 +606,37 @@ static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of,
put_ve(ve);
cgroup_kn_unlock(of->kn);
return ret ? : nbytes;
+#else
+ BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
+
+ /*
+ * Release agent gets called with all capabilities,
+ * require capabilities to set release agent.
+ */
+ ctx = of->priv;
+ if ((ctx->ns->user_ns != &init_user_ns) ||
+ !file_ns_capable(of->file, &init_user_ns, CAP_SYS_ADMIN))
+ return -EPERM;
+
+ cgrp = cgroup_kn_lock_live(of->kn, false);
+ if (!cgrp)
+ return -ENODEV;
+ spin_lock(&release_agent_path_lock);
+ strscpy(cgrp->root->release_agent_path, strstrip(buf),
+ sizeof(cgrp->root->release_agent_path));
+ spin_unlock(&release_agent_path_lock);
+ cgroup_kn_unlock(of->kn);
+ return nbytes;
+#endif
}
static int cgroup_release_agent_show(struct seq_file *seq, void *v)
{
+ struct cgroup *cgrp = seq_css(seq)->cgroup;
+
+#ifdef CONFIG_VE
const char *release_agent = NULL;
struct cgroup *root_cgrp;
- struct cgroup *cgrp = seq_css(seq)->cgroup;
struct ve_struct *ve = NULL;
rcu_read_lock();
@@ -623,6 +654,12 @@ static int cgroup_release_agent_show(struct seq_file *seq, void *v)
if (release_agent)
seq_puts(seq, release_agent);
rcu_read_unlock();
+#else
+ spin_lock(&release_agent_path_lock);
+ seq_puts(seq, cgrp->root->release_agent_path);
+ spin_unlock(&release_agent_path_lock);
+ seq_putc(seq, '\n');
+#endif
seq_putc(seq, '\n');
return 0;
@@ -832,7 +869,11 @@ void cgroup1_check_for_release(struct cgroup *cgrp)
{
if (notify_on_release(cgrp) && !cgroup_is_populated(cgrp) &&
!css_has_online_children(&cgrp->self) && !cgroup_is_dead(cgrp))
+#ifdef CONFIG_VE
ve_add_to_release_list(cgrp);
+#else
+ schedule_work(&cgrp->release_agent_work);
+#endif
}
/*
@@ -860,6 +901,7 @@ void cgroup1_check_for_release(struct cgroup *cgrp)
*/
void cgroup1_release_agent(struct work_struct *work)
{
+#ifdef CONFIG_VE
struct ve_struct *ve =
container_of(work, struct ve_struct, release_agent_work);
/*
@@ -871,6 +913,10 @@ void cgroup1_release_agent(struct work_struct *work)
*/
struct cgroup_namespace *ve_cgroup_ns =
rcu_dereference_protected(ve->ve_nsproxy, 1)->cgroup_ns;
+#else
+ struct cgroup *cgrp =
+ container_of(work, struct cgroup, release_agent_work);
+#endif
char *pathbuf, *agentbuf;
char *argv[3], *envp[3];
unsigned long flags;
@@ -882,6 +928,7 @@ void cgroup1_release_agent(struct work_struct *work)
if (!pathbuf || !agentbuf)
goto out_free;
+#ifdef CONFIG_VE
spin_lock_irqsave(&ve->release_list_lock, flags);
while (!list_empty(&ve->release_list)) {
struct cgroup *cgrp;
@@ -939,6 +986,28 @@ void cgroup1_release_agent(struct work_struct *work)
spin_lock_irqsave(&ve->release_list_lock, flags);
}
spin_unlock_irqrestore(&ve->release_list_lock, flags);
+#else
+ spin_lock(&release_agent_path_lock);
+ strscpy(agentbuf, cgrp->root->release_agent_path, PATH_MAX);
+ spin_unlock(&release_agent_path_lock);
+ if (!agentbuf[0])
+ goto out_free;
+
+ ret = cgroup_path_ns(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns);
+ if (ret < 0)
+ goto out_free;
+
+ argv[0] = agentbuf;
+ argv[1] = pathbuf;
+ argv[2] = NULL;
+
+ /* minimal command environment */
+ envp[0] = "HOME=/";
+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[2] = NULL;
+
+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+#endif
out_free:
kfree(agentbuf);
kfree(pathbuf);
@@ -985,10 +1054,12 @@ static int cgroup1_rename(struct kernfs_node *kn, struct kernfs_node *new_parent
static int cgroup1_show_options(struct seq_file *seq, struct kernfs_root *kf_root)
{
- const char *release_agent;
struct cgroup_root *root = cgroup_root_from_kf(kf_root);
struct cgroup_subsys *ss;
int ssid;
+#ifdef CONFIG_VE
+ const char *release_agent;
+#endif
for_each_subsys(ss, ssid)
if (root->subsys_mask & (1 << ssid))
@@ -1002,11 +1073,20 @@ static int cgroup1_show_options(struct seq_file *seq, struct kernfs_root *kf_roo
if (root->flags & CGRP_ROOT_FAVOR_DYNMODS)
seq_puts(seq, ",favordynmods");
+#ifdef CONFIG_VE
rcu_read_lock();
release_agent = ve_ra_data_get_path_locked(get_exec_env(), root);
if (release_agent && release_agent[0])
seq_show_option(seq, "release_agent", release_agent);
rcu_read_unlock();
+#else
+ spin_lock(&release_agent_path_lock);
+ if (strlen(root->release_agent_path))
+ seq_show_option(seq, "release_agent",
+ root->release_agent_path);
+ spin_unlock(&release_agent_path_lock);
+#endif
+
if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags))
seq_puts(seq, ",clone_children");
if (strlen(root->name))
@@ -1238,8 +1318,16 @@ int cgroup1_reconfigure(struct fs_context *fc)
WARN_ON(rebind_subsystems(&cgrp_dfl_root, removed_mask));
+#ifdef CONFIG_VE
if (ctx->release_agent)
ret = ve_ra_data_set(get_exec_env(), root, ctx->release_agent);
+#else
+ if (ctx->release_agent) {
+ spin_lock(&release_agent_path_lock);
+ strcpy(root->release_agent_path, ctx->release_agent);
+ spin_unlock(&release_agent_path_lock);
+ }
+#endif
trace_cgroup_remount(root);
@@ -1372,10 +1460,10 @@ int cgroup1_get_tree(struct fs_context *fc)
ret = 1; /* restart */
cgroup_unlock();
-
+#ifdef CONFIG_VE
if (!ret && ve_hide_cgroups(ctx->root))
ret = -EPERM;
-
+#endif
if (!ret)
ret = cgroup_do_get_tree(fc);
--
2.54.0
More information about the Devel
mailing list