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. */
|
/* BPF_FUNC_l4_csum_replace flags. */
|
||||||
#define BPF_F_PSEUDO_HDR (1ULL << 4)
|
#define BPF_F_PSEUDO_HDR (1ULL << 4)
|
||||||
|
#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
|
||||||
|
|
||||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||||
#define BPF_F_INGRESS (1ULL << 0)
|
#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;
|
struct sk_buff *skb = (struct sk_buff *) (long) r1;
|
||||||
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
|
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
|
||||||
|
bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
|
||||||
int offset = (int) r2;
|
int offset = (int) r2;
|
||||||
__sum16 sum, *ptr;
|
__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;
|
return -EINVAL;
|
||||||
if (unlikely((u32) offset > 0xffff))
|
if (unlikely((u32) offset > 0xffff))
|
||||||
return -EFAULT;
|
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);
|
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
|
||||||
if (unlikely(!ptr))
|
if (unlikely(!ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
if (is_mmzero && !*ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (flags & BPF_F_HDR_FIELD_MASK) {
|
switch (flags & BPF_F_HDR_FIELD_MASK) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -1508,6 +1512,8 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mmzero && !*ptr)
|
||||||
|
*ptr = CSUM_MANGLED_0;
|
||||||
if (ptr == &sum)
|
if (ptr == &sum)
|
||||||
/* skb_store_bits guaranteed to not return -EFAULT here */
|
/* skb_store_bits guaranteed to not return -EFAULT here */
|
||||||
skb_store_bits(skb, offset, ptr, sizeof(sum));
|
skb_store_bits(skb, offset, ptr, sizeof(sum));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче