Skip to content

Commit 2f72959

Browse files
borkmanndavem330
authored andcommitted
bpf: fix csum update in bpf_l4_csum_replace helper for udp
When using this helper for updating UDP checksums, we need to extend this in order to write CSUM_MANGLED_0 for csum computations that result into 0 as sum. Reason we need this is because packets with a checksum could otherwise become incorrectly marked as a packet without a checksum. Likewise, if the user indicates BPF_F_MARK_MANGLED_0, then we should not turn packets without a checksum into ones with a checksum. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3697649 commit 2f72959

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ enum bpf_func_id {
313313

314314
/* BPF_FUNC_l4_csum_replace flags. */
315315
#define BPF_F_PSEUDO_HDR (1ULL << 4)
316+
#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
316317

317318
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
318319
#define BPF_F_INGRESS (1ULL << 0)

net/core/filter.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,10 +1477,12 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
14771477
{
14781478
struct sk_buff *skb = (struct sk_buff *) (long) r1;
14791479
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
1480+
bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
14801481
int offset = (int) r2;
14811482
__sum16 sum, *ptr;
14821483

1483-
if (unlikely(flags & ~(BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK)))
1484+
if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_PSEUDO_HDR |
1485+
BPF_F_HDR_FIELD_MASK)))
14841486
return -EINVAL;
14851487
if (unlikely((u32) offset > 0xffff))
14861488
return -EFAULT;
@@ -1490,6 +1492,8 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
14901492
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
14911493
if (unlikely(!ptr))
14921494
return -EFAULT;
1495+
if (is_mmzero && !*ptr)
1496+
return 0;
14931497

14941498
switch (flags & BPF_F_HDR_FIELD_MASK) {
14951499
case 0:
@@ -1508,6 +1512,8 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
15081512
return -EINVAL;
15091513
}
15101514

1515+
if (is_mmzero && !*ptr)
1516+
*ptr = CSUM_MANGLED_0;
15111517
if (ptr == &sum)
15121518
/* skb_store_bits guaranteed to not return -EFAULT here */
15131519
skb_store_bits(skb, offset, ptr, sizeof(sum));

0 commit comments

Comments
 (0)