
From: Toke Høiland-Jørgensen <toke@redhat.com> mainline inclusion from mainline-v6.2-rc1 commit 1c123c567fb138ebd187480b7fc0610fcb0851f5 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICTB0G CVE: CVE-2025-38502 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- The bpf_prog_map_compatible() check makes sure that BPF program types are not mixed inside BPF map types that can contain programs (tail call maps, cpumaps and devmaps). It does this by setting the fields of the map->owner struct to the values of the first program being checked against, and rejecting any subsequent programs if the values don't match. One of the values being set in the map owner struct is the program type, and since the code did not resolve the prog type for fext programs, the map owner type would be set to PROG_TYPE_EXT and subsequent loading of programs of the target type into the map would fail. This bug is seen in particular for XDP programs that are loaded as PROG_TYPE_EXT using libxdp; these cannot insert programs into devmaps and cpumaps because the check fails as described above. Fix the bug by resolving the fext program type to its target program type as elsewhere in the verifier. v3: - Add Yonghong's ACK Fixes: f45d5b6ce2e8 ("bpf: generalise tail call map compatibility check") Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Link: https://lore.kernel.org/r/20221214230254.790066-1-toke@redhat.com Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Conflicts: include/linux/bpf_verifier.h kernel/bpf/core.c kernel/bpf/verifier.c [The conflicts were due to some minor issue.] Signed-off-by: Xiaomeng Zhang <zhangxiaomeng13@huawei.com> --- include/linux/bpf_verifier.h | 5 +++++ kernel/bpf/core.c | 6 ++++-- kernel/bpf/verifier.c | 5 ----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index c300b2816e07..32b304844949 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -569,4 +569,9 @@ static inline u32 type_flag(u32 type) return type & ~BPF_BASE_TYPE_MASK; } +static inline enum bpf_prog_type resolve_prog_type(struct bpf_prog *prog) +{ + return prog->aux->dst_prog ? prog->aux->dst_prog->type : prog->type; +} + #endif /* _LINUX_BPF_VERIFIER_H */ diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 5a31bce4cf5a..4d72a8651de5 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -32,6 +32,7 @@ #include <linux/perf_event.h> #include <linux/extable.h> #include <linux/log2.h> +#include <linux/bpf_verifier.h> #include <linux/nospec.h> #include <asm/barrier.h> @@ -1778,6 +1779,7 @@ static unsigned int __bpf_prog_ret0_warn(const void *ctx, bool bpf_prog_map_compatible(struct bpf_map *map, const struct bpf_prog *fp) { + enum bpf_prog_type prog_type = resolve_prog_type(fp); struct bpf_prog_aux *aux = fp->aux; enum bpf_cgroup_storage_type i; bool ret = false; @@ -1789,7 +1791,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map, map->owner = bpf_map_owner_alloc(map); if (!map->owner) goto err; - map->owner->type = fp->type; + map->owner->type = prog_type; map->owner->jited = fp->jited; map->owner->attach_func_proto = aux->attach_func_proto; for_each_cgroup_storage_type(i) { @@ -1799,7 +1801,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map, } ret = true; } else { - ret = map->owner->type == fp->type && + ret = map->owner->type == prog_type && map->owner->jited == fp->jited; for_each_cgroup_storage_type(i) { if (!ret) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index f8c6ea69ea41..13849004ae38 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3322,11 +3322,6 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, #define MAX_PACKET_OFF 0xffff -static enum bpf_prog_type resolve_prog_type(struct bpf_prog *prog) -{ - return prog->aux->dst_prog ? prog->aux->dst_prog->type : prog->type; -} - static bool may_access_direct_pkt_data(struct bpf_verifier_env *env, const struct bpf_call_arg_meta *meta, enum bpf_access_type t) -- 2.34.1