All of lore.kernel.org
 help / color / mirror / Atom feed
* bpf_csum_diff - R3 offset is outside of the packet
       [not found] <BYAPR11MB26157ACA256993F0F15D65E7B45F0@BYAPR11MB2615.namprd11.prod.outlook.com>
@ 2019-12-07  0:11 ` Francesco Ruta (fruta)
  2019-12-07 13:15   ` Anton Protopopov
  0 siblings, 1 reply; 3+ messages in thread
From: Francesco Ruta (fruta) @ 2019-12-07  0:11 UTC (permalink / raw)
  To: xdp-newbies

Hello,

I am trying to use bpf_csum_diff() to recompute a corrupted checksum in XDP; unfortunately, in this specific case, I am unable to just perform an incremental update.
I understand that the verifier will reject code that uses dynamic length, but even the stripped-down test shown below is rejected.
I tried directly in assembly adding extra range checks for the r3 register to placate the most phobic verifier to no avail.
Is there any workaround -or any alternative?
BR
F.

SEC("test")
int intercept(struct xdp_md *ctx) {
    void * data = (void*)(long)ctx->data;
    void * dataEnd = (void*)(long)ctx->data_end;
    void * dataPnt = data;
    if (dataPnt >= dataEnd) {
        return XDP_ABORTED;
    }
    __u32 dataLen = (__be32 *)dataEnd - (__be32 *)dataPnt;
    if (dataLen > sizeof(__be32)){
        (void)bpf_csum_diff(0, 0, (__be32 *)dataPnt, sizeof(__be32), 0);
   }
    return XDP_PASS;
}
char _license[] SEC("license") = "GPL";

Prog section 'test' rejected: Permission denied (13)!
- Type:         6
- Instructions: 18 (0 over limit)
- License:      GPL

Verifier analysis:

0: (b7) r6 = 1
1: (61) r2 = *(u32 *)(r1 +4)
2: (61) r3 = *(u32 *)(r1 +0)
3: (3d) if r3 >= r2 goto pc+12
R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=0,r=0,imm=0) R6=inv1 R10=fp0,call_-1
4: (1f) r2 -= r3
5: (18) r1 = 0x3fffffffc
7: (5f) r2 &= r1
8: (b7) r6 = 2
9: (b7) r1 = 17
10: (2d) if r1 > r2 goto pc+5
R1=inv17 R2=inv(id=0,umin_value=17,umax_value=17179869180,var_off=(0x0; 0x3fffffffc)) R3=pkt(id=0,off=0,r=0,imm=0) R6=inv2 R10=fp0,call_-1
11: (b7) r1 = 0
12: (b7) r2 = 0
13: (b7) r4 = 4
14: (b7) r5 = 0
15: (85) call bpf_csum_diff#28
invalid access to packet, off=0 size=4, R3(id=0,off=0,r=0)
R3 offset is outside of the packet

uname -sr
Linux 5.0.0-1022-gke

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: bpf_csum_diff - R3 offset is outside of the packet
  2019-12-07  0:11 ` bpf_csum_diff - R3 offset is outside of the packet Francesco Ruta (fruta)
@ 2019-12-07 13:15   ` Anton Protopopov
  2019-12-09  1:22     ` Francesco Ruta (fruta)
  0 siblings, 1 reply; 3+ messages in thread
From: Anton Protopopov @ 2019-12-07 13:15 UTC (permalink / raw)
  To: Francesco Ruta (fruta); +Cc: xdp-newbies

Hi Francesco,

пт, 6 дек. 2019 г. в 19:12, Francesco Ruta (fruta) <fruta@cisco.com>:
>
> Hello,
>
> I am trying to use bpf_csum_diff() to recompute a corrupted checksum in XDP; unfortunately, in this specific case, I am unable to just perform an incremental update.
> I understand that the verifier will reject code that uses dynamic length, but even the stripped-down test shown below is rejected.
> I tried directly in assembly adding extra range checks for the r3 register to placate the most phobic verifier to no avail.
> Is there any workaround -or any alternative?
> BR
> F.
>
> SEC("test")
> int intercept(struct xdp_md *ctx) {
>     void * data = (void*)(long)ctx->data;
>     void * dataEnd = (void*)(long)ctx->data_end;
>     void * dataPnt = data;
>     if (dataPnt >= dataEnd) {
>         return XDP_ABORTED;
>     }
>     __u32 dataLen = (__be32 *)dataEnd - (__be32 *)dataPnt;
>     if (dataLen > sizeof(__be32)){
>         (void)bpf_csum_diff(0, 0, (__be32 *)dataPnt, sizeof(__be32), 0);
>    }
>     return XDP_PASS;
> }
> char _license[] SEC("license") = "GPL";
>
> Prog section 'test' rejected: Permission denied (13)!
> - Type:         6
> - Instructions: 18 (0 over limit)
> - License:      GPL
>
> Verifier analysis:
>
> 0: (b7) r6 = 1
> 1: (61) r2 = *(u32 *)(r1 +4)
> 2: (61) r3 = *(u32 *)(r1 +0)
> 3: (3d) if r3 >= r2 goto pc+12
> R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=0,r=0,imm=0) R6=inv1 R10=fp0,call_-1
> 4: (1f) r2 -= r3
> 5: (18) r1 = 0x3fffffffc
> 7: (5f) r2 &= r1
> 8: (b7) r6 = 2
> 9: (b7) r1 = 17
> 10: (2d) if r1 > r2 goto pc+5
> R1=inv17 R2=inv(id=0,umin_value=17,umax_value=17179869180,var_off=(0x0; 0x3fffffffc)) R3=pkt(id=0,off=0,r=0,imm=0) R6=inv2 R10=fp0,call_-1
> 11: (b7) r1 = 0
> 12: (b7) r2 = 0
> 13: (b7) r4 = 4
> 14: (b7) r5 = 0
> 15: (85) call bpf_csum_diff#28
> invalid access to packet, off=0 size=4, R3(id=0,off=0,r=0)
> R3 offset is outside of the packet
>
> uname -sr
> Linux 5.0.0-1022-gke

You need to check pointer boundaries, try something like this:

SEC("test")
int intercept(struct xdp_md *ctx) {
    void * data = (void*)(long)ctx->data;
    void * data_end = (void*)(long)ctx->data_end;
    const int N = sizeof(__be32);

    if (data >= data_end)
        return XDP_ABORTED;

    if (data + N <= data_end) /* lets verifier to know that
data[0,...,N-1] is valid */
        bpf_csum_diff(0, 0, data, N, 0);

    return XDP_PASS;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: bpf_csum_diff - R3 offset is outside of the packet
  2019-12-07 13:15   ` Anton Protopopov
@ 2019-12-09  1:22     ` Francesco Ruta (fruta)
  0 siblings, 0 replies; 3+ messages in thread
From: Francesco Ruta (fruta) @ 2019-12-09  1:22 UTC (permalink / raw)
  To: Anton Protopopov; +Cc: xdp-newbies

Anton,

Thank you for your suggestion. Albeit that would work for the example, it doesn't seem to work for my original problem where the length of the buffer is computed dynamically.

Thank you again
Francesco

-----Original Message-----
From: Anton Protopopov <aspsk2@gmail.com> 
Sent: Saturday, December 7, 2019 7:16 AM
To: Francesco Ruta (fruta) <fruta@cisco.com>
Cc: xdp-newbies@vger.kernel.org
Subject: Re: bpf_csum_diff - R3 offset is outside of the packet

Hi Francesco,

пт, 6 дек. 2019 г. в 19:12, Francesco Ruta (fruta) <fruta@cisco.com>:
> Hello,
>
> I am trying to use bpf_csum_diff() to recompute a corrupted checksum in XDP; unfortunately, in this specific case, I am unable to just perform an incremental update.
> I understand that the verifier will reject code that uses dynamic length, but even the stripped-down test shown below is rejected.
> I tried directly in assembly adding extra range checks for the r3 register to placate the most phobic verifier to no avail.
> Is there any workaround -or any alternative?
> BR
> F.
>
> SEC("test")
> int intercept(struct xdp_md *ctx) {
>     void * data = (void*)(long)ctx->data;
>     void * dataEnd = (void*)(long)ctx->data_end;
>     void * dataPnt = data;
>     if (dataPnt >= dataEnd) {
>         return XDP_ABORTED;
>     }
>     __u32 dataLen = (__be32 *)dataEnd - (__be32 *)dataPnt;
>     if (dataLen > sizeof(__be32)){
>         (void)bpf_csum_diff(0, 0, (__be32 *)dataPnt, sizeof(__be32), 0);
>    }
>     return XDP_PASS;
> }
> char _license[] SEC("license") = "GPL";
>
> Prog section 'test' rejected: Permission denied (13)!
> - Type:         6
> - Instructions: 18 (0 over limit)
> - License:      GPL
>
> Verifier analysis:
>
> 0: (b7) r6 = 1
> 1: (61) r2 = *(u32 *)(r1 +4)
> 2: (61) r3 = *(u32 *)(r1 +0)
> 3: (3d) if r3 >= r2 goto pc+12
> R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0) 
> R3=pkt(id=0,off=0,r=0,imm=0) R6=inv1 R10=fp0,call_-1
> 4: (1f) r2 -= r3
> 5: (18) r1 = 0x3fffffffc
> 7: (5f) r2 &= r1
> 8: (b7) r6 = 2
> 9: (b7) r1 = 17
> 10: (2d) if r1 > r2 goto pc+5
> R1=inv17 
> R2=inv(id=0,umin_value=17,umax_value=17179869180,var_off=(0x0; 
> 0x3fffffffc)) R3=pkt(id=0,off=0,r=0,imm=0) R6=inv2 R10=fp0,call_-1
> 11: (b7) r1 = 0
> 12: (b7) r2 = 0
> 13: (b7) r4 = 4
> 14: (b7) r5 = 0
> 15: (85) call bpf_csum_diff#28
> invalid access to packet, off=0 size=4, R3(id=0,off=0,r=0)
> R3 offset is outside of the packet
>
> uname -sr
> Linux 5.0.0-1022-gke

You need to check pointer boundaries, try something like this:

SEC("test")
int intercept(struct xdp_md *ctx) {
    void * data = (void*)(long)ctx->data;
    void * data_end = (void*)(long)ctx->data_end;
    const int N = sizeof(__be32);

    if (data >= data_end)
        return XDP_ABORTED;

    if (data + N <= data_end) /* lets verifier to know that data[0,...,N-1] is valid */
        bpf_csum_diff(0, 0, data, N, 0);

    return XDP_PASS;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-12-09  1:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <BYAPR11MB26157ACA256993F0F15D65E7B45F0@BYAPR11MB2615.namprd11.prod.outlook.com>
2019-12-07  0:11 ` bpf_csum_diff - R3 offset is outside of the packet Francesco Ruta (fruta)
2019-12-07 13:15   ` Anton Protopopov
2019-12-09  1:22     ` Francesco Ruta (fruta)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.