Re: Packet pointers with 32-bit assignments

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 2/2/22 12:59 PM, Paul Chaignon wrote:
Hi,

We're hitting the following verifier error in Cilium, on bpf-next
(86c7ecad3bf8) with LLVM 10.0.0 and mcpu=v3.

     ; return (void *)(unsigned long)ctx->data;
     2: (61) r9 = *(u32 *)(r7 +76)
     ; R7_w=ctx(id=0,off=0,imm=0) R9_w=pkt(id=0,off=0,r=0,imm=0)
     ; return (void *)(unsigned long)ctx->data;
     3: (bc) w6 = w9
     ; R6_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R9_w=pkt(id=0,off=0,r=0,imm=0)
     ; if (data + tot_len > data_end)
     4: (bf) r2 = r6
     ; R2_w=inv(id=1,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R6_w=inv(id=1,umax_value=4294967295,var_off=(0x0; 0xffffffff))
     5: (07) r2 += 54
     ; R2_w=inv(id=0,umin_value=54,umax_value=4294967349,var_off=(0x0; 0x1ffffffff))
     ; if (data + tot_len > data_end)
     6: (2d) if r2 > r1 goto pc+466
     ; R1_w=pkt_end(id=0,off=0,imm=0) R2_w=inv(id=0,umin_value=54,umax_value=4294967349,var_off=(0x0; 0x1ffffffff))
     ; tmp = a->d1 - b->d1;
     7: (71) r2 = *(u8 *)(r6 +22)
     R6 invalid mem access 'inv'

As seen above, the verifier loses track of the packet pointer at
instruction 3, which then leads to an invalid memory access. Since
ctx->data is on 32 bits, LLVM generated a 32-bit assignment at
instruction 3.

We're usually able to avoid this by removing all 32-bit comparisons and
additions with the 64-bit variables for data and data_end. But in this
case, all variables are already on 64 bits.

Is there maybe a compiler patch we're missing which prevents such
assignments? If not, could we teach the verifier to track and convert
such assignments?

We kind of tackled this problem sometimes back. For example, the
following is a proposed llvm builtin for this purpose:
  https://reviews.llvm.org/D81479
  https://reviews.llvm.org/D81480
the builtin looks like
  void *ptr = __builtin_bpf_load_u32_to_ptr(void *base,
                  int const_offset);

The patches are abandoned since the functionality can be
achieved with bpf asm code. Something likes below
   asm("%0 = *(u32 *)(%1 + %2)" : "=r"(ptr) : "r"(ctx), "i"(76));
We could define the above asm insn as a macro and put it
in bpf_helpers.h.

Could you give a try?


Regards,
Paul



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux