Re: [PATCH 1/4] sched_ext: Don't sign-extend unsigned enums in __COMPAT_read_enum()
From: Andrea Righi
Date: Sun Oct 25 2026 - 06:21:19 EST
Hi Tejun,
On Fri, Oct 23, 2026 at 01:20:59PM -1000, Tejun Heo wrote:
> __COMPAT_read_enum() looks an enumerator up in the running kernel's BTF. For
> a 4-byte enum, it assigns struct btf_enum.val, an __s32, to the u64 result,
> which sign-extends. BTF records the enum's signedness in the type's kflag.
> The code ignores it, so an unsigned enumerator with bit 31 set is
> sign-extended too.
>
> b1c2a6b0d90d ("sched_ext: scx_qmap: Read SCX_RESCUE_DISABLE through the enum
> lookup tables") added SCX_RESCUE_DISABLE to the enum lookup tables. It is
> U32_MAX in enum scx_consts and the only such enumerator in the tables. BPF
> code sees it as 0xffffffffffffffff instead of 0xffffffff, so a comparison
> against a u32 holding the real value never matches.
>
> scx_qmap, its only user, narrows the value to u32 in userspace and is
> unaffected.
>
> Sign-extend only when the kflag says the enum is signed and zero-extend
> otherwise. A signed enum keeps the sign extension, which is what C gives
> when the enumerator converts to u64. SCX_TASK_CURSOR, 1 << 31 in a signed
> enum, still reads 0xffffffff80000000. Verified with a probe against a built
> kernel's BTF.
>
> Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
> ---
> tools/sched_ext/include/scx/compat.h | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/tools/sched_ext/include/scx/compat.h b/tools/sched_ext/include/scx/compat.h
> index 07fb55e63c57..c8d7280ceffa 100644
> --- a/tools/sched_ext/include/scx/compat.h
> +++ b/tools/sched_ext/include/scx/compat.h
> @@ -143,7 +143,11 @@ static inline bool __COMPAT_read_enum(const char *type, const char *name, u64 *v
> if (t->size == 8 && !strncmp(type, "scx_", 4))
> return __COMPAT_recover_truncated_enum64(type, name,
> (u32)e[i].val, v);
> - *v = e[i].val;
> + /* kflag marks a signed enum */
> + if (btf_kflag(t))
> + *v = (s64)e[i].val;
> + else
> + *v = (u32)e[i].val;
nit: BTF generated by pahole < 1.24 never sets the enum kflag, so on
those kernels signed enums are zero-extended as well. It's harmless
today (SCX_TASK_CURSOR is the only affected entry and it's only used as
a u32 flag), but maybe it's worth mentioning it in the comment?
Something like:
/*
* kflag marks a signed enum. BTF from pahole < 1.24 never sets it,
* so signed enums are zero-extended there too.
*/
Reviewed-by: Andrea Righi <arighi@xxxxxxxxxx>
Thanks,
-Andrea
> return true;
> }
> }
> --
> 2.56.0
>