I'm rewrting my code for tc
program to csgroup_sbb/xxx
and I've noticed direct access to skb data is not possible here (skb-data), so bpf_skb_load_bytes[_relative]
is the only way(?) to get skb data.
It worked until I reached the wall.
Verifier at this code:
valp = bpf_ringbuf_reserve(&packets, sizeof(struct packet), ringbuffer_flags);
if (!valp) {
return 1;
}
void *pto = valp->data;
const __u32 dns_packet_len = skb->len;
if (dns_packet_len > 0 && dns_packet_len < ETH_FRAME_LEN) {
ok = bpf_skb_load_bytes(skb, 0, pto, dns_packet_len);
//...
}
yields this:
; valp = bpf_ringbuf_reserve(&packets, sizeof(struct packet), ringbuffer_flags);
234: (18) r1 = 0xffffc0df80407000 ; R1_w=map_value(off=0,ks=4,vs=8,imm=0)
236: (79) r3 = *(u64 *)(r1 +0) ; R1_w=map_value(off=0,ks=4,vs=8,imm=0) R3_w=scalar()
; valp = bpf_ringbuf_reserve(&packets, sizeof(struct packet), ringbuffer_flags);
237: (18) r1 = 0xffff9c54905d9400 ; R1_w=map_ptr(off=0,ks=0,vs=0,imm=0)
239: (b7) r2 = 1520 ; R2_w=1520
240: (85) call bpf_ringbuf_reserve#131 ; R0=ringbuf_mem_or_null(id=11,ref_obj_id=11,off=0,imm=0) refs=11
241: (bf) r8 = r0 ; R0=ringbuf_mem_or_null(id=11,ref_obj_id=11,off=0,imm=0) R8_w=ringbuf_mem_or_null(id=11,ref_obj_id=11,off=0,imm=0) refs=11
; if (!valp) {
242: (15) if r8 == 0x0 goto pc-211 ; R8_w=ringbuf_mem(ref_obj_id=11,off=0,imm=0) refs=11
; const __u32 dns_packet_len = skb->len;
243: (61) r9 = *(u32 *)(r6 +0) ; R6=ctx(off=0,imm=0) R9_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff)) refs=11
; if (dns_packet_len > 0 && dns_packet_len < ETH_FRAME_LEN) {
244: (bf) r1 = r9 ; R1_w=scalar(id=12,umax=4294967295,var_off=(0x0; 0xffffffff)) R9_w=scalar(id=12,umax=4294967295,var_off=(0x0; 0xffffffff)) refs=11
245: (07) r1 += -1 ; R1_w=scalar(smin=-1,smax=4294967294) refs=11
246: (67) r1 <<= 32 ; R1_w=scalar(smax=9223372032559808512,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32_max=0) refs=11
247: (77) r1 >>= 32 ; R1_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff)) refs=11
248: (25) if r1 > 0x5e8 goto pc+23 ; R1_w=scalar(umax=1512,var_off=(0x0; 0x7ff)) refs=11
;
249: (bf) r2 = r8 ; R2_w=ringbuf_mem(ref_obj_id=11,off=0,imm=0) R8_w=ringbuf_mem(ref_obj_id=11,off=0,imm=0) refs=11
250: (07) r2 += 4 ; R2_w=ringbuf_mem(ref_obj_id=11,off=4,imm=0) refs=11
; ok = bpf_skb_load_bytes(skb, offset, pto, dns_packet_len); //ok
251: (bf) r1 = r6 ; R1_w=ctx(off=0,imm=0) R6=ctx(off=0,imm=0) refs=11
252: (bf) r6 = r2 ; R2_w=ringbuf_mem(ref_obj_id=11,off=4,imm=0) R6_w=ringbuf_mem(ref_obj_id=11,off=4,imm=0) refs=11
253: (bf) r2 = r7 ; R2_w=28 R7=28 refs=11
254: (bf) r3 = r6 ; R3_w=ringbuf_mem(ref_obj_id=11,off=4,imm=0) R6_w=ringbuf_mem(ref_obj_id=11,off=4,imm=0) refs=11
255: (bf) r4 = r9 ; R4_w=scalar(id=12,umax=4294967295,var_off=(0x0; 0xffffffff)) R9_w=scalar(id=12,umax=4294967295,var_off=(0x0; 0xffffffff)) refs=11
256: (85) call bpf_skb_load_bytes#26
invalid access to memory, mem_size=1520 off=4 size=0
R3 min value is outside of the allowed memory range
If I understand it correctly verifier(1) checks lower bounds for len
(R4) and it could be 0 (size=0), so this error happens, but on the other hand I've put an additional check if-then
condition and it seems to be not enough. I guess it should be a common issue for arrays loading, so if yes how can it be resolve?
additional info:
kernel: 6.2