https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110657
Bug ID: 110657 Summary: BPF verifier rejects generated code due to invalid stack access Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: kris.van.hees at oracle dot com Target Milestone: --- Created attachment 55535 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55535&action=edit C source code file for BPF function The attached BPF program compiles into code that the BPF kernel verifier rejects because of invalid stack access. Code is compiled with: bpf-gcc -gbtf -D__amd64 -Ilibdtrace -Iinclude -I/scratch/dtrace-bpf-user/build/include -O2 -Wall -Wno-unknown-pragmas -MP -MMD -MF /scratch/dtrace-bpf-user/build/bpf--inet_ntoa6.o.deps -MT /scratch/dtrace-bpf-user/build/bpf--inet_ntoa6.o -c -o /scratch/dtrace-bpf-user/build/bpf--inet_ntoa6.o bpf/inet_ntoa6.c The bpf/inet_ntoa6.c code is attached (incomplete implementation of the function but exhibiting the issue). The function gets included in a larger program so instruction numbers are much higher than in e.g. objdump output. Function entry point is at instruction 2432. The BPF verifier output is: BPF: 2432: (7b) *(u64 *)(r10 -32) = r1 ; frame2: R1_w=map_value(off=0,ks=4,vs=528,umin=8,umax=263,var_off=(0x0; 0x1ff),s32_min=0,s32_max=511,u32_max=511) R10=fp0 fp-32_w=map_value BPF: 2433: (bf) r6 = r2 ; frame2: R2_w=map_value(off=2208,ks=4,vs=3529,imm=0) R6_w=map_value(off=2208,ks=4,vs=3529,imm=0) BPF: 2434: (bf) r3 = r1 ; frame2: R1_w=map_value(off=0,ks=4,vs=528,umin=8,umax=263,var_off=(0x0; 0x1ff),s32_min=0,s32_max=511,u32_max=511) R3_w=map_value(off=0,ks=4,vs=528,umin=8,umax=263,var_off=(0x0; 0x1ff),s32_min=0,s32_max=511,u32_max=511) BPF: 2435: (b7) r2 = 16 ; frame2: R2_w=P16 BPF: 2436: (bf) r1 = r10 ; frame2: R1_w=fp0 R10=fp0 BPF: 2437: (07) r1 += -16 ; frame2: R1_w=fp-16 BPF: 2438: (85) call bpf_probe_read#4 ; frame2: R0=Pscalar() fp-8=mmmmmmmm fp-16=mmmmmmmm BPF: 2439: (71) r0 = *(u8 *)(r10 -14) ; frame2: R0_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2440: (67) r0 <<= 8 ; frame2: R0_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2441: (71) r1 = *(u8 *)(r10 -13) ; frame2: R1_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2442: (4f) r0 |= r1 ; frame2: R0_w=Pscalar() R1_w=Pscalar(umax=255,var_off=(0x0; 0xff)) BPF: 2443: (71) r8 = *(u8 *)(r10 -12) ; frame2: R8_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2444: (67) r8 <<= 8 ; frame2: R8_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2445: (71) r2 = *(u8 *)(r10 -11) ; frame2: R2_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2446: (4f) r8 |= r2 ; frame2: R2_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R8_w=Pscalar() BPF: 2447: (71) r7 = *(u8 *)(r10 -10) ; frame2: R7_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2448: (67) r7 <<= 8 ; frame2: R7_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2449: (71) r3 = *(u8 *)(r10 -9) ; frame2: R3_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2450: (4f) r7 |= r3 ; frame2: R3_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R7_w=Pscalar() BPF: 2451: (7b) *(u64 *)(r10 -40) = r7 ; frame2: R7_w=Pscalar() R10=fp0 fp-40_w=mmmmmmmm BPF: 2452: (71) r1 = *(u8 *)(r10 -8) ; frame2: R1_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2453: (67) r1 <<= 8 ; frame2: R1_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2454: (71) r4 = *(u8 *)(r10 -7) ; frame2: R4_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2455: (4f) r1 |= r4 ; frame2: R1_w=Pscalar() R4_w=Pscalar(umax=255,var_off=(0x0; 0xff)) BPF: 2456: (71) r3 = *(u8 *)(r10 -6) ; frame2: R3_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2457: (67) r3 <<= 8 ; frame2: R3_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2458: (71) r5 = *(u8 *)(r10 -5) ; frame2: R5_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2459: (4f) r3 |= r5 ; frame2: R3_w=Pscalar() R5_w=Pscalar(umax=255,var_off=(0x0; 0xff)) BPF: 2460: (71) r4 = *(u8 *)(r10 -4) ; frame2: R4_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2461: (67) r4 <<= 8 ; frame2: R4_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2462: (71) r2 = *(u8 *)(r10 -3) ; frame2: R2_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2463: (4f) r4 |= r2 ; frame2: R2_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R4_w=Pscalar() BPF: 2464: (71) r5 = *(u8 *)(r10 -2) ; frame2: R5_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2465: (67) r5 <<= 8 ; frame2: R5_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2466: (71) r7 = *(u8 *)(r10 -1) ; frame2: R7_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2467: (4f) r5 |= r7 ; frame2: R5_w=Pscalar() R7_w=Pscalar(umax=255,var_off=(0x0; 0xff)) BPF: 2468: (71) r2 = *(u8 *)(r10 -16) ; frame2: R2_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2469: (64) w2 <<= 8 ; frame2: R2_w=Pscalar(umax=65280,var_off=(0x0; 0xff00)) BPF: 2470: (71) r7 = *(u8 *)(r10 -15) ; frame2: R7_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 BPF: 2471: (73) *(u8 *)(r10 -20) = r7 ; frame2: R7_w=Pscalar(umax=255,var_off=(0x0; 0xff)) R10=fp0 fp-24=???m???? BPF: 2472: (61) r7 = *(u32 *)(r10 -20) BPF: invalid read from stack off -20+1 size 4 BPF: verification time 75240 usec BPF: stack depth 96+16+0+0+96+0+0+40+0+0 BPF: processed 27048 insns (limit 1000000) max_states_per_insn 33 total_states 2418 peak_states 2318 mark_read 131 The core issue is seen in instructions 2471 and 2472, where an 8-bit value is stored on the stack but we try to read a 32-bit value from the stack. That is flagged as a BPF verifier error because we end up reading uninitialized data from the stack which is a no-no in BPF land.