We're received reports of cBPF code failing to accept DHCP packets.
"BPF filter for DHCP not working (android14-6.1-lts + android-14.0.0_r74)"
The relevant Android code is at:
https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/NetworkStack/jni/network_stack_utils_jni.cpp;l=95;drc=9df50aef1fd163215dcba759045706253a5624f5
which uses a lot of macros from:
https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Connectivity/bpf/headers/include/bpf/BpfClassic.h;drc=c58cfb7c7da257010346bd2d6dcca1c0acdc8321
This is widely used and does work on the vast majority of drivers,
but is exposing a core kernel cBPF bug related to driver skb layout.
Root cause is iwlwifi driver, specifically on (at least):
Dell 7212: Intel Dual Band Wireless AC 8265
Dell 7220: Intel Wireless AC 9560
Dell 7230: Intel Wi-Fi 6E AX211
delivers frames where the UDP destination port is not in the skb linear
portion, while the cBPF code is using SKF_NET_OFF relative addressing.
simplified from above, effectively:
BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, SKF_NET_OFF)
BPF_STMT(BPF_LD | BPF_H | BPF_IND, SKF_NET_OFF + 2)
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 68, 1, 0)
BPF_STMT(BPF_RET | BPF_K, 0)
BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFFF)
fails to match udp dport=68 packets.
Specifically the 3rd cBPF instruction fails to match the condition:
if (ptr >= skb->head && ptr + size <= skb_tail_pointer(skb))
within bpf_internal_load_pointer_neg_helper() and thus returns NULL,
which results in reading -EFAULT.
This is because bpf_skb_load_helper_{8,16,32} don't include the
"data past headlen do skb_copy_bits()" logic from the non-negative
offset branch in the negative offset branch.
Note: I don't know sparc assembly, so this doesn't fix sparc...
ideally we should just delete bpf_internal_load_pointer_neg_helper()
This seems to have always been broken (but not pre-git era, since
obviously there was no eBPF helpers back then), but stuff older
than 5.4 is no longer LTS supported anyway, so using 5.4 as fixes tag.
Cc: Alexei Starovoitov <ast@xxxxxxxxxx>
Cc: Daniel Borkmann <daniel@xxxxxxxxxxxxx>
Cc: Stanislav Fomichev <sdf@xxxxxxxxxxx>
Cc: Willem de Bruijn <willemb@xxxxxxxxxx>
Reported-by: Matt Moeller <moeller.matt@xxxxxxxxx>
Closes: https://issuetracker.google.com/384636719 [Treble - GKI partner internal]
Signed-off-by: Maciej Żenczykowski <maze@xxxxxxxxxx>
Fixes: 219d54332a09 ("Linux 5.4")