[PATCH OLK-6.6] bpf: Reject pkt arguments in mutating subprogs
From: Emil Tsalapatis <emil@etsalapatis.com> mainline inclusion from mainline-v7.3-rc2 commit a6c1edfbe240e4377038a0e1d233ad81fde9a21b category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/20656 CVE: CVE-2026-98589 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- The verifier tracks changes in how PTR_TO_PACKET registers' bounds are modified across subprog boundaries. PTR_TO_PACKET registers are actually passed as PTR_TO_MEM, which is assumed valid for the entire call. This is not the case with packet memory, where a pskb_* call may invalidate its memory region. Reject BPF code that passes PTR_TO_PACKET pointers to subprogs that may mutate a packet. We cannot pass the pointer as a true PTR_TO_PACKET because we would also need to somehow pass the PTR_TO_PACKET_META or PTR_TO_PACKET_END to the subprog. Since we cannot avoid representing the pointer in the subprog as PTR_TO_MEM, only permit it if the subprog is guaranteed not to mutate the packet. Fixes: 80f281664f5a ("bpf: Support pointers in global func args") Reported-by: Nicholas Carlini <nicholas@carlini.com> Suggested-by: Nicholas Carlini <nicholas@carlini.com> Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20260922172028.6269-6-emil@etsalapatis.com Conflicts: kernel/bpf/verifier.c kernel/bpf/btf.c [commit 9b9f0b42703ceb88332bcb19453c4288c2683e34 not backport] Signed-off-by: Chen Yuxi <chenyuxi19@huawei.com> --- kernel/bpf/btf.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 3e3bfbbdbb5f..aad12310adb3 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -7159,11 +7159,25 @@ int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *pr return btf_check_func_type_match(log, btf1, t1, btf2, t2); } +static bool reg_is_pkt_pointer_any(const struct bpf_reg_state *reg) +{ + return base_type(reg->type) == PTR_TO_PACKET || + base_type(reg->type) == PTR_TO_PACKET_META || + reg->type == PTR_TO_PACKET_END; +} + +static bool reg_is_dynptr_slice_pkt(const struct bpf_reg_state *reg) +{ + return base_type(reg->type) == PTR_TO_MEM && + (reg->type & DYNPTR_TYPE_SKB || reg->type & DYNPTR_TYPE_XDP); +} + static int btf_check_func_arg_match(struct bpf_verifier_env *env, const struct btf *btf, u32 func_id, struct bpf_reg_state *regs, bool ptr_to_mem_ok, - bool processing_call) + bool processing_call, + int subprog) { enum bpf_prog_type prog_type = resolve_prog_type(env->prog); struct bpf_verifier_log *log = &env->log; @@ -7251,6 +7265,16 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, if (check_mem_reg(env, reg, regno, type_size)) return -EINVAL; + /* + * PTR_TO_PACKET get passed as PTR_TO_MEM, preventing + * us from adjusting bounds tracking info. + */ + if ((reg_is_pkt_pointer_any(reg) || reg_is_dynptr_slice_pkt(reg)) && + env->subprog_info[subprog].changes_pkt_data) { + bpf_log(log, "R%d is a packet pointer, but func#%d may change packet data\n", + regno, subprog); + return -EINVAL; + } } else { bpf_log(log, "reg type unsupported for arg#%d function %s#%d\n", i, func_name, func_id); @@ -7288,7 +7312,7 @@ int btf_check_subprog_arg_match(struct bpf_verifier_env *env, int subprog, return -EINVAL; is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, false); + err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, false, subprog); /* Compiler optimizations can remove arguments from static functions * or mismatched type can be passed into a global function. @@ -7331,7 +7355,7 @@ int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog, return -EINVAL; is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, true); + err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, true, subprog); /* Compiler optimizations can remove arguments from static functions * or mismatched type can be passed into a global function. -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/30223 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/COI... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/30223 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/COI...
participants (2)
-
Chen Yuxi -
patchwork bot