* [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility
@ 2026-09-08 14:28 Miguel Gazquez (Schneider Electric)
2026-09-08 14:49 ` sashiko-bot
2026-09-09 20:26 ` Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Miguel Gazquez (Schneider Electric) @ 2026-09-08 14:28 UTC (permalink / raw)
To: stable, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer,
Andrey Ignatov
Cc: Thomas Petazzoni, netdev, bpf, linux-kernel, Yinhao Hu,
Kaiyan Mei, Dongliang Mu, Sasha Levin,
Miguel Gazquez (Schneider Electric)
From: Daniel Borkmann <daniel@iogearbox.net>
[ Upstream commit 4540aed51b12bc13364149bf95f6ecef013197c0 ]
Yinhao et al. recently reported:
Our fuzzer tool discovered an uninitialized pointer issue in the
bpf_prog_test_run_xdp() function within the Linux kernel's BPF subsystem.
This leads to a NULL pointer dereference when a BPF program attempts to
deference the txq member of struct xdp_buff object.
The test initializes two programs of BPF_PROG_TYPE_XDP: progA acts as the
entry point for bpf_prog_test_run_xdp() and its expected_attach_type can
neither be of be BPF_XDP_DEVMAP nor BPF_XDP_CPUMAP. progA calls into a slot
of a tailcall map it owns. progB's expected_attach_type must be BPF_XDP_DEVMAP
to pass xdp_is_valid_access() validation. The program returns struct xdp_md's
egress_ifindex, and the latter is only allowed to be accessed under mentioned
expected_attach_type. progB is then inserted into the tailcall which progA
calls.
The underlying issue goes beyond XDP though. Another example are programs
of type BPF_PROG_TYPE_CGROUP_SOCK_ADDR. sock_addr_is_valid_access() as well
as sock_addr_func_proto() have different logic depending on the programs'
expected_attach_type. Similarly, a program attached to BPF_CGROUP_INET4_GETPEERNAME
should not be allowed doing a tailcall into a program which calls bpf_bind()
out of BPF which is only enabled for BPF_CGROUP_INET4_CONNECT.
In short, specifying expected_attach_type allows to open up additional
functionality or restrictions beyond what the basic bpf_prog_type enables.
The use of tailcalls must not violate these constraints. Fix it by enforcing
expected_attach_type in __bpf_prog_map_compatible().
Note that we only enforce this for tailcall maps, but not for BPF devmaps or
cpumaps: There, the programs are invoked through dev_map_bpf_prog_run*() and
cpu_map_bpf_prog_run*() which set up a new environment / context and therefore
these situations are not prone to this issue.
[ Fixed conflict, applied the changes to bpf_prog_array_compatible
instead of __bpf_prog_map_compatible. Dropped the guard testing for
BPF_MAP_TYPE_PROG_ARRAY as bpf_prog_array_compatible is only called on maps whose
map_type is already BPF_MAP_TYPE_PROG_ARRAY, so the check was always true ]
Fixes: 5e43f899b03a ("bpf: Check attach type at prog load time")
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20250926171201.188490-1-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Miguel Gazquez (Schneider Electric) <miguel.gazquez@bootlin.com>
---
include/linux/bpf.h | 1 +
kernel/bpf/core.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5d5d0bc7ca50..fb213524ccac 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -876,6 +876,7 @@ struct bpf_array_aux {
spinlock_t lock;
enum bpf_prog_type type;
bool jited;
+ enum bpf_attach_type expected_attach_type;
} owner;
/* Programs with direct jumps into programs part of this array. */
struct list_head poke_progs;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index db613a97ee5f..c9b3fe8b250a 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1795,10 +1795,14 @@ bool bpf_prog_array_compatible(struct bpf_array *array,
*/
array->aux->owner.type = fp->type;
array->aux->owner.jited = fp->jited;
+ array->aux->owner.expected_attach_type = fp->expected_attach_type;
ret = true;
} else {
ret = array->aux->owner.type == fp->type &&
array->aux->owner.jited == fp->jited;
+ if (ret &&
+ array->aux->owner.expected_attach_type != fp->expected_attach_type)
+ ret = false;
}
spin_unlock(&array->aux->owner.lock);
return ret;
---
base-commit: 2a3da1f4966798b0b48ce302944ad356b2c98b5d
change-id: 20260907-cve-2025-40123-e08968057032
Best regards,
--
Miguel Gazquez (Schneider Electric) <miguel.gazquez@bootlin.com>
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility
2026-09-08 14:28 [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility Miguel Gazquez (Schneider Electric)
@ 2026-09-08 14:49 ` sashiko-bot
2026-09-09 20:26 ` Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-09-08 14:49 UTC (permalink / raw)
To: Miguel Gazquez (Schneider Electric); +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Incomplete fix for tailcall expected_attach_type bypass: BPF_PROG_TYPE_EXT programs bypass the check.
--
commit d87774423a605def68b6715a3edf5dc1feea5da7
Author: Daniel Borkmann <daniel@iogearbox.net>
bpf: Enforce expected_attach_type for tailcall compatibility
This patch aims to prevent context confusion by enforcing that programs
inserted into a tailcall map share the same expected_attach_type.
This restricts tailcalls from violating attach type constraints.
Link: https://lore.kernel.org/r/20250926171201.188490-1-daniel@iogearbox.net
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
[ ... ]
> @@ -1795,10 +1795,14 @@ bool bpf_prog_array_compatible(struct bpf_array *array,
[ ... ]
> } else {
> ret = array->aux->owner.type == fp->type &&
> array->aux->owner.jited == fp->jited;
> + if (ret &&
> + array->aux->owner.expected_attach_type != fp->expected_attach_type)
> + ret = false;
[Severity: High]
This is a pre-existing issue, but does this check effectively become 0 != 0
for all BPF_PROG_TYPE_EXT programs, allowing arbitrary mixing of EXT programs
with different underlying target contexts?
It appears that for BPF_PROG_TYPE_EXT programs, expected_attach_type is
reset to 0 at the end of verification in bpf_check().
If userspace loads two BPF_PROG_TYPE_EXT programs targeting entirely
different functions (e.g., XDP_DEVMAP vs XDP_CPUMAP) and inserts them both
into the same BPF_MAP_TYPE_PROG_ARRAY, couldn't a tailcall between them
bypass this expected_attach_type check?
Can this allow a program verified for one target context to execute in a
different context, potentially leading to out-of-bounds accesses or NULL
pointer dereferences?
> }
> spin_unlock(&array->aux->owner.lock);
> return ret;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-cve-2025-40123-v1-1-be62451196fb@bootlin.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility
2026-09-08 14:28 [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility Miguel Gazquez (Schneider Electric)
2026-09-08 14:49 ` sashiko-bot
@ 2026-09-09 20:26 ` Sasha Levin
2026-09-10 9:34 ` Miguel Gazquez
1 sibling, 1 reply; 4+ messages in thread
From: Sasha Levin @ 2026-09-09 20:26 UTC (permalink / raw)
To: stable, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer,
Andrey Ignatov
Cc: Sasha Levin, Thomas Petazzoni, netdev, bpf, linux-kernel,
Yinhao Hu, Kaiyan Mei, Dongliang Mu,
Miguel Gazquez (Schneider Electric)
> The underlying issue goes beyond XDP though. Another example are programs
> of type BPF_PROG_TYPE_CGROUP_SOCK_ADDR. sock_addr_is_valid_access() as well
> as sock_addr_func_proto() have different logic depending on the programs'
> expected_attach_type.
Thanks for the 5.10.y backport of 4540aed51b12 ("bpf: Enforce
expected_attach_type for tailcall compatibility"). Holding this until a 5.15.y
version exists too, since fixes need to land on newer trees first.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility
2026-09-09 20:26 ` Sasha Levin
@ 2026-09-10 9:34 ` Miguel Gazquez
0 siblings, 0 replies; 4+ messages in thread
From: Miguel Gazquez @ 2026-09-10 9:34 UTC (permalink / raw)
To: Sasha Levin, stable, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Song Liu, Yonghong Song,
John Fastabend, KP Singh, David S. Miller, Jakub Kicinski,
Jesper Dangaard Brouer, Andrey Ignatov
Cc: Thomas Petazzoni, netdev, bpf, linux-kernel, Yinhao Hu,
Kaiyan Mei, Dongliang Mu
Hi
Le 09/09/2026 à 22:26, Sasha Levin a écrit :
>> The underlying issue goes beyond XDP though. Another example are programs
>> of type BPF_PROG_TYPE_CGROUP_SOCK_ADDR. sock_addr_is_valid_access() as well
>> as sock_addr_func_proto() have different logic depending on the programs'
>> expected_attach_type.
>
> Thanks for the 5.10.y backport of 4540aed51b12 ("bpf: Enforce
> expected_attach_type for tailcall compatibility"). Holding this until a 5.15.y
> version exists too, since fixes need to land on newer trees first.
>
Sorry I missed that there was no 5.15 backport, I sent it.
--
Miguel Gazquez, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-10 9:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 14:28 [PATCH 5.10.y] bpf: Enforce expected_attach_type for tailcall compatibility Miguel Gazquez (Schneider Electric)
2026-09-08 14:49 ` sashiko-bot
2026-09-09 20:26 ` Sasha Levin
2026-09-10 9:34 ` Miguel Gazquez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox