Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Allow union argument in trampoline based programs

Currently, functions with 'union' arguments cannot be traced with
fentry/fexit:

bpftrace -e 'fentry:release_pages { exit(); }' -v

The function release_pages arg0 type UNION is unsupported.

The type of the 'release_pages' arg0 is defined as:

typedef union {
struct page **pages;
struct folio **folios;
struct encoded_page **encoded_pages;
} release_pages_arg __attribute__ ((__transparent_union__));

This patch relaxes the restriction by allowing function arguments of type
'union' to be traced in verifier.

Reviewed-by: Amery Hung <ameryhung@gmail.com>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/r/20250919044110.23729-2-leon.hwang@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Leon Hwang and committed by
Alexei Starovoitov
ccb4f5d9 2383e45f

+5 -5
+1 -1
include/linux/bpf.h
··· 1128 1128 */ 1129 1129 #define MAX_BPF_FUNC_REG_ARGS 5 1130 1130 1131 - /* The argument is a structure. */ 1131 + /* The argument is a structure or a union. */ 1132 1132 #define BTF_FMODEL_STRUCT_ARG BIT(0) 1133 1133 1134 1134 /* The argument is signed. */
+4 -4
kernel/bpf/btf.c
··· 6751 6751 /* skip modifiers */ 6752 6752 while (btf_type_is_modifier(t)) 6753 6753 t = btf_type_by_id(btf, t->type); 6754 - if (btf_type_is_small_int(t) || btf_is_any_enum(t) || __btf_type_is_struct(t)) 6754 + if (btf_type_is_small_int(t) || btf_is_any_enum(t) || btf_type_is_struct(t)) 6755 6755 /* accessing a scalar */ 6756 6756 return true; 6757 6757 if (!btf_type_is_ptr(t)) { ··· 7323 7323 if (btf_type_is_ptr(t)) 7324 7324 /* kernel size of pointer. Not BPF's size of pointer*/ 7325 7325 return sizeof(void *); 7326 - if (btf_type_is_int(t) || btf_is_any_enum(t) || __btf_type_is_struct(t)) 7326 + if (btf_type_is_int(t) || btf_is_any_enum(t) || btf_type_is_struct(t)) 7327 7327 return t->size; 7328 7328 return -EINVAL; 7329 7329 } ··· 7332 7332 { 7333 7333 u8 flags = 0; 7334 7334 7335 - if (__btf_type_is_struct(t)) 7335 + if (btf_type_is_struct(t)) 7336 7336 flags |= BTF_FMODEL_STRUCT_ARG; 7337 7337 if (btf_type_is_signed_int(t)) 7338 7338 flags |= BTF_FMODEL_SIGNED_ARG; ··· 7373 7373 return -EINVAL; 7374 7374 } 7375 7375 ret = __get_type_size(btf, func->type, &t); 7376 - if (ret < 0 || __btf_type_is_struct(t)) { 7376 + if (ret < 0 || btf_type_is_struct(t)) { 7377 7377 bpf_log(log, 7378 7378 "The function %s return type %s is unsupported.\n", 7379 7379 tname, btf_type_str(t));