[PATCH RFC v3 36/90] cgroup: fork a task of a cell into the budget
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:20:02 EST
A task that is born in a cell starts in the budget of the cell.
The spawner is not checked for permission to put a task into that cgroup.
That check was made when the "budget" slot was filled, and holding the
cellfd is the authority to spawn.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
kernel/cgroup/cgroup.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 051b220e2850..3869cfa6af50 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -28,6 +28,7 @@
#include "cgroup-internal.h"
#include <linux/bpf-cgroup.h>
+#include <linux/cell.h>
#include <linux/cred.h>
#include <linux/errno.h>
#include <linux/init_task.h>
@@ -6905,6 +6906,41 @@ static void cgroup_fork_child_unlock(struct task_struct *child)
up_read(&child->signal->cgroup_threadgroup_rwsem);
}
+/*
+ * Fork into the budget of a cell. The cellfd is the authority: whoever gave the
+ * cell this budget was asked everything cgroup_css_set_fork() asks of a caller
+ * that names a cgroup. Consumes @cset.
+ */
+static int cgroup_css_set_fork_cell(struct kernel_clone_args *kargs,
+ struct css_set *cset)
+{
+ struct cgroup *dst_cgrp = cell_budget(kargs->cell);
+ int ret;
+
+ ret = -ENODEV;
+ if (cgroup_is_dead(dst_cgrp))
+ goto err;
+ ret = cgroup_migrate_vet_dst(dst_cgrp);
+ if (ret)
+ goto err;
+ ret = -ENOMEM;
+ kargs->cset = find_css_set(cset, dst_cgrp);
+ if (!kargs->cset)
+ goto err;
+
+ put_css_set(cset);
+ cgroup_get(dst_cgrp);
+ kargs->cgrp = dst_cgrp;
+ kargs->kill_seq = dst_cgrp->kill_seq;
+ return 0;
+
+err:
+ cgroup_threadgroup_change_end(current);
+ cgroup_unlock();
+ put_css_set(cset);
+ return ret;
+}
+
/**
* cgroup_css_set_fork - find or create a css_set for a child process
* @kargs: the arguments passed to create the child process
@@ -6945,6 +6981,9 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
return 0;
}
+ if (kargs->cell)
+ return cgroup_css_set_fork_cell(kargs, cset);
+
CLASS(fd_raw, f)(kargs->cgroup);
if (fd_empty(f)) {
ret = -EBADF;
--
2.55.0