[PATCH bpf-next] bpf: sched_ext: Mark ops argument container pointer fields as trusted

From: Tejun Heo

Date: Thu Aug 20 2026 - 01:20:37 EST


Walking an unannotated pointer field of a trusted struct yields a bare
PTR_TO_BTF_ID in non-sleepable programs, which kfuncs and helpers accept,
but PTR_UNTRUSTED in sleepable programs, which they reject. This gets in the
way of making ops.init_task() sleepable, which schedulers want for
allocations. For example, passing args->cgroup into bpf_cgrp_storage_get()
then fails verification and the only recourse is round-tripping through the
cgroup ID with bpf_cgroup_from_id().

The pointer fields in the sched_ext ops argument containers are all pinned
by the callers for the duration of the ops calls and are never NULL. Add
them to the verifier's trusted-fields whitelist so that they are PTR_TRUSTED
in both sleepable and non-sleepable programs.

Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
---
kernel/bpf/verifier.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5661,6 +5661,28 @@ BTF_TYPE_SAFE_TRUSTED(struct file) {
struct inode *f_inode;
};

+/*
+ * The pointer fields in the sched_ext ops argument containers are pinned by the
+ * callers for the duration of the ops calls and are never NULL.
+ */
+BTF_TYPE_SAFE_TRUSTED(struct scx_init_task_args) {
+#ifdef CONFIG_EXT_GROUP_SCHED
+ struct cgroup *cgroup;
+#endif
+};
+
+BTF_TYPE_SAFE_TRUSTED(struct scx_cpu_release_args) {
+ struct task_struct *task;
+};
+
+BTF_TYPE_SAFE_TRUSTED(struct scx_sub_attach_args) {
+ struct sched_ext_ops *ops;
+};
+
+BTF_TYPE_SAFE_TRUSTED(struct scx_sub_detach_args) {
+ struct sched_ext_ops *ops;
+};
+
BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry) {
struct inode *d_inode;
};
@@ -5705,6 +5727,10 @@ static bool type_is_trusted(struct bpf_v
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct bpf_iter__task));
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct linux_binprm));
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct file));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct scx_init_task_args));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct scx_cpu_release_args));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct scx_sub_attach_args));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct scx_sub_detach_args));

return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__safe_trusted");
}