mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
bpf: test_run: Fix false -EBADMSG after skb leaves CHECKSUM_COMPLETE
With BPF_F_TEST_SKB_CHECKSUM_COMPLETE, bpf_prog_test_run_skb() computes
skb->csum over the packet from the network header to the end and marks
the skb CHECKSUM_COMPLETE. After the program has run, it recomputes the
checksum and returns -EBADMSG if it does not match skb->csum.
bpf_skb_change_tail() resizes the skb with __skb_trim_rcsum() and
__skb_grow_rcsum(), which move a CHECKSUM_COMPLETE skb to CHECKSUM_NONE
and leave skb->csum as it is. The post-run check still compares against
that stale value, so a correct program fails with -EBADMSG. After a
trim, skb->csum still covers the removed bytes. After a grow, later
writes cannot update skb->csum, even with BPF_F_RECOMPUTE_CSUM, because
skb->csum is only adjusted for CHECKSUM_COMPLETE skbs.
skb->csum only holds the packet checksum while ip_summed is
CHECKSUM_COMPLETE. With CHECKSUM_NONE the stack does not rely on it and
validates the packet in software, so there is nothing to compare. Only
do the check if the skb is still CHECKSUM_COMPLETE after the run. A
program that keeps the skb CHECKSUM_COMPLETE but leaves skb->csum stale
still gets -EBADMSG.
Dropping the checksum offload is documented behaviour of
bpf_skb_change_tail() ("implicitly linearizes, unclones and drops
offloads"), and the stack does the same in other places, for example
skb_forward_csum(). The test harness has to accept CHECKSUM_NONE either
way, whether or not the helper is later taught to keep
CHECKSUM_COMPLETE.
Fixes: a3cfe84cca ("bpf: Add CHECKSUM_COMPLETE to bpf test progs")
Signed-off-by: Maxim Skokov <skokovmaksimevg@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261009174755.22026-2-skokovmaksimevg@gmail.com
This commit is contained in:
parent
15b578b171
commit
36edb1c773
|
|
@ -1237,7 +1237,13 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
|
|||
memset(__skb_push(skb, hh_len), 0, hh_len);
|
||||
}
|
||||
|
||||
if (kattr->test.flags & BPF_F_TEST_SKB_CHECKSUM_COMPLETE) {
|
||||
/*
|
||||
* A helper such as bpf_skb_change_tail() may have downgraded the skb
|
||||
* from CHECKSUM_COMPLETE. skb->csum is then unused by the stack and
|
||||
* there is nothing to validate.
|
||||
*/
|
||||
if ((kattr->test.flags & BPF_F_TEST_SKB_CHECKSUM_COMPLETE) &&
|
||||
skb->ip_summed == CHECKSUM_COMPLETE) {
|
||||
const int off = skb_network_offset(skb);
|
||||
int len = skb->len - off;
|
||||
__wsum csum;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user