summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-11-01 19:05:19 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-11-02 00:10:39 +0000
commitfaea3cda41d3deb4f28e7970c556896b1aa8bd76 (patch)
treea16c321eb9ac44a85b4c5280cbcd558e6cf3a393 /include
parented02b9cc1d377d03da2507c3a858f0874aef7494 (diff)
bpf: Compare the arguments of an extension with those of its target
An extension replaces its target, a global function of another prog. From BTF, btf_prepare_func_args() derives the kind of each argument, such as the context, memory of a given size or a kernel object. The verifier checks the callers with the BTF of the target and the extension with its own BTF. Only btf_check_func_type_match() compares the two prototypes. For a pointer to a struct, it compares only the struct names and assumes that the pointer is the context. That was true until the commit below added pointers to memory. Later the __arg_* tags added more kinds. Thus an extension can rely on more than the callers guarantee (size, not NULL, kind). Then what the verifier proved for it is false at run time. Keep the result of btf_prepare_func_args() in bpf_func_info_aux and compare the two results at load and on attach to another target. Return -EINVAL unless the kind and the BTF id are the same and the memory is not larger. The extension can also accept NULL where the callers never pass it. An extension with the prototype and the tags of its target loads as before. An argument that is the context only because of __arg_ctx needs the tag in the extension too. The tag __arg_untrusted or __arg_arena on the extension only is safe, but it is rejected because the kind differs. Fixes: e5069b9c23b3 ("bpf: Support pointers in global func args") Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261101190535.1454146-12-alexei.starovoitov@gmail.com
Diffstat (limited to 'include')
-rw-r--r--include/linux/bpf.h10
-rw-r--r--include/linux/bpf_verifier.h8
2 files changed, 10 insertions, 8 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 1a8c3e514284..0b44bcb4f56e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1752,12 +1752,22 @@ enum bpf_func_context {
BPF_FUNC_CTX_CNT,
};
+struct bpf_subprog_arg_info {
+ enum bpf_arg_type arg_type;
+ union {
+ u32 mem_size;
+ u32 btf_id;
+ };
+};
+
struct bpf_func_info_aux {
u16 linkage;
bool unreliable;
bool called[BPF_FUNC_CTX_CNT];
bool verified[BPF_FUNC_CTX_CNT];
bool called_with_pkt_ptrs;
+ /* what the callers of a global function are checked against */
+ struct bpf_subprog_arg_info args[MAX_BPF_FUNC_REG_ARGS];
};
enum bpf_jit_poke_reason {
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 8852c173c53e..33dc3d402057 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -923,14 +923,6 @@ struct bpf_func_ptr {
/* the subprog that a bpf_func_ptr pointed to was removed as dead code */
#define BPF_FUNC_PTR_DELETED ((u32)-1)
-struct bpf_subprog_arg_info {
- enum bpf_arg_type arg_type;
- union {
- u32 mem_size;
- u32 btf_id;
- };
-};
-
enum priv_stack_mode {
PRIV_STACK_UNKNOWN,
NO_PRIV_STACK,