mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
Merge branch 'bpf-fix-memory-access-flags-in-helper-prototypes'
Zesen Liu says: ==================== bpf: Fix memory access flags in helper prototypes This series adds missing memory access flags (MEM_RDONLY or MEM_WRITE) to several bpf helper function prototypes that use ARG_PTR_TO_MEM but lack the correct flag. It also adds a new check in verifier to ensure the flag is specified. Missing memory access flags in helper prototypes can lead to critical correctness issues when the verifier tries to perform code optimization. After commit37cce22dbd("bpf: verifier: Refactor helper access type tracking"), the verifier relies on the memory access flags, rather than treating all arguments in helper functions as potentially modifying the pointed-to memory. Using ARG_PTR_TO_MEM alone without flags does not make sense because: - If the helper does not change the argument, missing MEM_RDONLY causes the verifier to incorrectly reject a read-only buffer. - If the helper does change the argument, missing MEM_WRITE causes the verifier to incorrectly assume the memory is unchanged, leading to errors in code optimization. We have already seen several reports regarding this: - commitac44dcc788("bpf: Fix verifier assumptions of bpf_d_path's output buffer") adds MEM_WRITE to bpf_d_path; - commit2eb7648558("bpf: Specify access type of bpf_sysctl_get_name args") adds MEM_WRITE to bpf_sysctl_get_name. This series looks through all prototypes in the kernel and completes the flags. It also adds check_mem_arg_rw_flag_ok() and wires it into check_func_proto() to statically restrict ARG_PTR_TO_MEM from appearing without memory access flags. Changelog ========= v3: - Rebased to bpf-next to address check_func_proto() signature changes, as suggested by Eduard Zingerman. v2: - Add missing MEM_RDONLY flags to protos with ARG_PTR_TO_FIXED_SIZE_MEM. ==================== Link: https://patch.msgid.link/20260120-helper_proto-v3-0-27b0180b4e77@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
2516a9c5a5
|
|
@ -1077,7 +1077,7 @@ const struct bpf_func_proto bpf_snprintf_proto = {
|
|||
.func = bpf_snprintf,
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_MEM_OR_NULL | MEM_WRITE,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_PTR_TO_CONST_STR,
|
||||
.arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
|
|
|
|||
|
|
@ -6451,7 +6451,7 @@ static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = {
|
|||
.func = bpf_kallsyms_lookup_name,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
|
||||
|
|
|
|||
|
|
@ -10441,10 +10441,27 @@ static bool check_btf_id_ok(const struct bpf_func_proto *fn)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool check_mem_arg_rw_flag_ok(const struct bpf_func_proto *fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fn->arg_type); i++) {
|
||||
enum bpf_arg_type arg_type = fn->arg_type[i];
|
||||
|
||||
if (base_type(arg_type) != ARG_PTR_TO_MEM)
|
||||
continue;
|
||||
if (!(arg_type & (MEM_WRITE | MEM_RDONLY)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int check_func_proto(const struct bpf_func_proto *fn)
|
||||
{
|
||||
return check_raw_mode_ok(fn) &&
|
||||
check_arg_pair_ok(fn) &&
|
||||
check_mem_arg_rw_flag_ok(fn) &&
|
||||
check_btf_id_ok(fn) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,7 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
|
|||
.func = bpf_snprintf_btf,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
|
|
@ -1526,7 +1526,7 @@ static const struct bpf_func_proto bpf_read_branch_records_proto = {
|
|||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM_OR_NULL,
|
||||
.arg2_type = ARG_PTR_TO_MEM_OR_NULL | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
|
@ -1661,7 +1661,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
|
|||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6399,7 +6399,7 @@ static const struct bpf_func_proto bpf_xdp_fib_lookup_proto = {
|
|||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
|
@ -6454,7 +6454,7 @@ static const struct bpf_func_proto bpf_skb_fib_lookup_proto = {
|
|||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
|
@ -8008,9 +8008,9 @@ static const struct bpf_func_proto bpf_tcp_raw_gen_syncookie_ipv4_proto = {
|
|||
.gpl_only = true, /* __cookie_v4_init_sequence() is GPL */
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct iphdr),
|
||||
.arg2_type = ARG_PTR_TO_MEM,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
|
|
@ -8040,9 +8040,9 @@ static const struct bpf_func_proto bpf_tcp_raw_gen_syncookie_ipv6_proto = {
|
|||
.gpl_only = true, /* __cookie_v6_init_sequence() is GPL */
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct ipv6hdr),
|
||||
.arg2_type = ARG_PTR_TO_MEM,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
|
|
@ -8060,9 +8060,9 @@ static const struct bpf_func_proto bpf_tcp_raw_check_syncookie_ipv4_proto = {
|
|||
.gpl_only = true, /* __cookie_v4_check is GPL */
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct iphdr),
|
||||
.arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg2_size = sizeof(struct tcphdr),
|
||||
};
|
||||
|
||||
|
|
@ -8084,9 +8084,9 @@ static const struct bpf_func_proto bpf_tcp_raw_check_syncookie_ipv6_proto = {
|
|||
.gpl_only = true, /* __cookie_v6_check is GPL */
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct ipv6hdr),
|
||||
.arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM,
|
||||
.arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg2_size = sizeof(struct tcphdr),
|
||||
};
|
||||
#endif /* CONFIG_SYN_COOKIES */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user