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>
This commit is contained in:
Родитель
3697649ff2
Коммит
2f72959a9c
|
@ -313,6 +313,7 @@ enum bpf_func_id {
|
|||
|
||||
/* BPF_FUNC_l4_csum_replace flags. */
|
||||
#define BPF_F_PSEUDO_HDR (1ULL << 4)
|
||||
#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
|
||||
|
||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||
#define BPF_F_INGRESS (1ULL << 0)
|
||||
|
|
|
@ -1477,10 +1477,12 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
|
|||
{
|
||||
struct sk_buff *skb = (struct sk_buff *) (long) r1;
|
||||
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
|
||||
bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
|
||||
int offset = (int) r2;
|
||||
__sum16 sum, *ptr;
|
||||
|
||||
if (unlikely(flags & ~(BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK)))
|
||||
if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_PSEUDO_HDR |
|
||||
BPF_F_HDR_FIELD_MASK)))
|
||||
return -EINVAL;
|
||||
if (unlikely((u32) offset > 0xffff))
|
||||
return -EFAULT;
|
||||
|
@ -1490,6 +1492,8 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
|
|||
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
|
||||
if (unlikely(!ptr))
|
||||
return -EFAULT;
|
||||
if (is_mmzero && !*ptr)
|
||||
return 0;
|
||||
|
||||
switch (flags & BPF_F_HDR_FIELD_MASK) {
|
||||
case 0:
|
||||
|
@ -1508,6 +1512,8 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_mmzero && !*ptr)
|
||||
*ptr = CSUM_MANGLED_0;
|
||||
if (ptr == &sum)
|
||||
/* skb_store_bits guaranteed to not return -EFAULT here */
|
||||
skb_store_bits(skb, offset, ptr, sizeof(sum));
|
||||
|
|
Загрузка…
Ссылка в новой задаче