invalid access to map value, R3 min value is outside of the allowed memory range
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 22.7k
- Forks
- 4.1k
- Avg merge
- 5d 13h
- Merged PRs (30d)
- 3
Description
Hello,
I am getting verifier failure despite of using suggested workarounds to make verifier happy. Here is the fragment of the code triggering verifier failure:
#define MAX_PACKET_LENGTH 1024
// Use per CPU array map to be able to store 1k data buffer
__u32 packet_data_map_id = 0;
void *packet_data_buffer = NULL;
packet_data_buffer = bpf_map_lookup_elem(&packet_data_map, &packet_data_map_id);
if (!packet_data_buffer)
{
return;
}
// Calculate actual length of L4+data portion
__u32 data_length = (__u32)(data_end - (data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr)));
// To make verifier happy Start block
data_length &= 1023;
int tmp = MAX_PACKET_LENGTH - data_length;
if (tmp < 0)
{
return;
}
if (data_length <= 0)
{
return;
}
// To make verifier happy End block
ret = bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct ipv6hdr), (void *)&packet_data_buffer[0], data_length);
if (ret < 0)
{
return;
}
Verifier error:
; ret = bpf_skb_load_bytes(skb, 0, ð_copy, sizeof(eth_copy));
174: (bf) r1 = r6
175: (b4) w2 = 0
176: (b4) w4 = 14
177: (85) call bpf_skb_load_bytes#26
last_idx 177 first_idx 171
regs=10 stack=0 before 176: (b4) w4 = 14
; if (ret < 0)
178: (c6) if w0 s< 0x0 goto pc+56
R0_w=inv(id=0,smax_value=9223372034707292159,umax_value=18446744071562067967,var_off=(0x0; 0xffffffff7fffffff),s32_min_value=0,u32_max_value=2147483647) R6=ctx(id=0,off=0,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8=map_value(id=0,off=0,ks=19,vs=256,imm=0) R9=pkt(id=0,off=54,r=54,imm=0) R10=fp0 fp-144=?????mmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-176=???????m fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200=????mmmm
; __u32 packet_data_map_id = 0;
179: (b4) w1 = 0
180: (63) *(u32 *)(r10 -4) = r1
last_idx 180 first_idx 171
regs=2 stack=0 before 179: (b4) w1 = 0
181: (bf) r2 = r10
;
182: (07) r2 += -4
; packet_data_buffer = bpf_map_lookup_elem(&packet_data_map, &packet_data_map_id);
183: (18) r1 = 0xffff9c5bf6bc4a00
185: (85) call bpf_map_lookup_elem#1
186: (7b) *(u64 *)(r10 -200) = r0
; if (!packet_data_buffer)
187: (15) if r0 == 0x0 goto pc+47
R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R6=ctx(id=0,off=0,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8=map_value(id=0,off=0,ks=19,vs=256,imm=0) R9=pkt(id=0,off=54,r=54,imm=0) R10=fp0 fp-8=mmmm???? fp-144=?????mmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-176=???????m fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200_w=map_value
; __u32 data_length = (__u32)(data_end - (data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr)));
!
188: (1c) w7 -= w9 < ---- data_length is treated as a pointer
!
; data_length &= 1023;
189: (54) w7 &= 1023
; ret = bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct ipv6hdr), packet_data_buffer, data_length);
190: (bf) r1 = r6
191: (b4) w2 = 54
192: (79) r3 = *(u64 *)(r10 -200)
!
193: (bc) w4 = w7 < --- If I read it right then it should contain the u32 data length
!
194: (85) call bpf_skb_load_bytes#26
R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1_w=ctx(id=0,off=0,imm=0) R2_w=inv54 R3_w=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R4_w=inv(id=0,umax_value=1023,var_off=(0x0; 0x3ff)) R6=ctx(id=0,off=0,imm=0) R7_w=inv(id=0,umax_value=1023,var_off=(0x0; 0x3ff)) R8=map_value(id=0,off=0,ks=19,vs=256,imm=0) R9=pkt(id=0,off=54,r=54,imm=0) R10=fp0 fp-8=mmmm???? fp-144=?????mmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-176=???????m fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200_w=map_value
invalid access to map value, value_size=1024 off=0 size=0
R3 min value is outside of the allowed memory range
processed 183 insns (limit 1000000) max_states_per_insn 0 total_states 12 peak_states 12 mark_read 10
When I use a constant instead of a data_length variable verifier passes:
; packet_data_buffer = bpf_map_lookup_elem(&packet_data_map, &packet_data_map_id);
183: (18) r1 = 0xffff9c59c3a34800
185: (85) call bpf_map_lookup_elem#1
186: (7b) *(u64 *)(r10 -200) = r0
; if (!packet_data_buffer)
187: (15) if r0 == 0x0 goto pc+50
R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R6=ctx(id=0,off=0,imm=0) R7=pkt(id=0,off=54,r=54,imm=0) R8=map_value(id=0,off=0,ks=19,vs=256,imm=0) R9=pkt_end(id=0,off=0,imm=0) R10=fp0 fp-8=mmmm???? fp-144=?????mmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-176=???????m fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200_w=map_value
; ret = bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct ipv6hdr), packet_data_buffer, dl);
188: (bf) r1 = r6
189: (b4) w2 = 54
190: (79) r3 = *(u64 *)(r10 -200)
191: (b4) w4 = 64 < ----- parameter passed as length
192: (85) call bpf_skb_load_bytes#26
R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1_w=ctx(id=0,off=0,imm=0) R2_w=inv54 R3_w=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R4_w=inv64 R6=ctx(id=0,off=0,imm=0) R7=pkt(id=0,off=54,r=54,imm=0) R8=map_value(id=0,off=0,ks=19,vs=256,imm=0) R9=pkt_end(id=0,off=0,imm=0) R10=fp0 fp-8=mmmm???? fp-144=?????mmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-176=???????m fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200_w=map_value
last_idx 192 first_idx 186
regs=10 stack=0 before 191: (b4) w4 = 64
; if (ret < 0)
193: (c6) if w0 s< 0x0 goto pc+44
In both working and non working cases R3 looks exactly the same: R3_w=map_value(id=0,off=0,ks=4,vs=1024,imm=0) the difference is how length parameter is viewed:
- non working case R4_w get value from
R7=invP(id=0,umax_value=1023,var_off=(0x0; 0x3ff))which make sense and - working case
R4_w=inv64
I would appreciate if somebody could suggest what else can be done to make verifier happy.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the verifier log around the bpf_map_lookup_elem and bpf_skb_load_bytes calls, comparing the variable-length and constant-length cases shown in the issue. No source file or test is identified, and done would require determining whether BCC or the underlying verifier needs a change and demonstrating the corrected verifier behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- networking, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100