R2 min value is negative, either use unsigned or 'var &= const'
- Dominant language
- C
- Stars
- 22.7k
- Forks
- 4.1k
- Avg merge
- 10d 4h
- Merged PRs (30d)
- 3
Description
I am on 6.1 kernel. I am trying to log full path of file which mean I need to concatenate every parent directory into string.
```c
#include "vmlinux.h"
#include
#include
char LICENSE[] SEC("license") = "GPL";
#define EPERM 1
SEC("lsm/path_unlink")
int BPF_PROG(prevent_delete, struct path *dir, struct dentry *dentry)
{
struct dentry *current_dentry = dir->dentry;
char full_path[256] = {};
char temp[64];
unsigned int idx = 0; // Start appending at the beginning of the buffer
#pragma unroll
for (int i = 0; i < 20; i++) { // Limit traversal depth for verifier compliance
if (!current_dentry)
break;
// Read directory name
int len = bpf_probe_read_str(temp, sizeof(temp), current_dentry->d_name.name);
if (len <= 0 || len >= sizeof(temp)) // Ensure len is valid
break;
// Check if there's enough space in the buffer
if (idx + len + 1 >= sizeof(full_path)) // +1 for '/'
break;
// Append '/' separator if not the first element
if (idx > 0) {
full_path[idx] = '/';
idx++;
}
// Copy the name into the path buffer
bpf_probe_read_str(&full_path[idx & 0xFF], len & 0xFF, temp);
idx += len;
// Move to the parent directory
if (bpf_probe_read(¤t_dentry, sizeof(current_dentry), ¤t_dentry->d_parent) < 0)
break;
}
// Null-terminate the path
if (idx < sizeof(full_path))
full_path[idx] = '\0';
// Print the constructed path
bpf_printk("prevent_delete: Full path - %s", full_path);
return -EPERM; // Deny unlink operation
}
```
I get error R2 min value is negative, either use unsigned or 'var &= const' which doesn't want to go away, no matter what I try.
```
INFO [faerie::elf] strtab: 0xd4c symtab 0xd88 relocs 0xdd0 sh_offset 0xdd0
libbpf: prog 'prevent_delete': BPF program load failed: Permission denied
libbpf: prog 'prevent_delete': -- BEGIN PROG LOAD LOG --
reg type unsupported for arg#0 function prevent_delete#5
0: R1=ctx(off=0,imm=0) R10=fp0
; int BPF_PROG(prevent_delete, struct path *dir, struct dentry *dentry)
0: (79) r1 = *(u64 *)(r1 +0)
func 'bpf_lsm_path_unlink' arg0 has btf_id 1006 type STRUCT 'path'
1: R1_w=ptr_path(off=0,imm=0)
; struct dentry *current_dentry = dir->dentry;
1: (79) r1 = *(u64 *)(r1 +8) ; R1_w=ptr_dentry(off=0,imm=0)
; struct dentry *current_dentry = dir->dentry;
2: (7b) *(u64 *)(r10 -8) = r1 ; R1_w=ptr_dentry(off=0,imm=0) R10=fp0 fp-8_w=ptr_
3: (b7) r9 = 0 ; R9_w=0
; char full_path[256] = {};
4: (7b) *(u64 *)(r10 -16) = r9 ; R9_w=0 R10=fp0 fp-16_w=00000000
5: (7b) *(u64 *)(r10 -24) = r9 ; R9_w=0 R10=fp0 fp-24_w=00000000
6: (7b) *(u64 *)(r10 -32) = r9 ; R9_w=0 R10=fp0 fp-32_w=00000000
7: (7b) *(u64 *)(r10 -40) = r9 ; R9_w=0 R10=fp0 fp-40_w=00000000
8: (7b) *(u64 *)(r10 -48) = r9 ; R9_w=0 R10=fp0 fp-48_w=00000000
9: (7b) *(u64 *)(r10 -56) = r9 ; R9_w=0 R10=fp0 fp-56_w=00000000
10: (7b) *(u64 *)(r10 -64) = r9 ; R9_w=0 R10=fp0 fp-64_w=00000000
11: (7b) *(u64 *)(r10 -72) = r9 ; R9_w=0 R10=fp0 fp-72_w=00000000
12: (7b) *(u64 *)(r10 -80) = r9 ; R9_w=0 R10=fp0 fp-80_w=00000000
13: (7b) *(u64 *)(r10 -88) = r9 ; R9_w=0 R10=fp0 fp-88_w=00000000
14: (7b) *(u64 *)(r10 -96) = r9 ; R9_w=0 R10=fp0 fp-96_w=00000000
15: (7b) *(u64 *)(r10 -104) = r9 ; R9_w=0 R10=fp0 fp-104_w=00000000
16: (7b) *(u64 *)(r10 -112) = r9 ; R9_w=0 R10=fp0 fp-112_w=00000000
17: (7b) *(u64 *)(r10 -120) = r9 ; R9_w=0 R10=fp0 fp-120_w=00000000
18: (7b) *(u64 *)(r10 -128) = r9 ; R9_w=0 R10=fp0 fp-128_w=00000000
19: (7b) *(u64 *)(r10 -136) = r9 ; R9_w=0 R10=fp0 fp-136_w=00000000
20: (7b) *(u64 *)(r10 -144) = r9 ; R9_w=0 R10=fp0 fp-144_w=00000000
21: (7b) *(u64 *)(r10 -152) = r9 ; R9_w=0 R10=fp0 fp-152_w=00000000
22: (7b) *(u64 *)(r10 -160) = r9 ; R9_w=0 R10=fp0 fp-160_w=00000000
23: (7b) *(u64 *)(r10 -168) = r9 ; R9_w=0 R10=fp0 fp-168_w=00000000
24: (7b) *(u64 *)(r10 -176) = r9 ; R9_w=0 R10=fp0 fp-176_w=00000000
25: (7b) *(u64 *)(r10 -184) = r9 ; R9_w=0 R10=fp0 fp-184_w=00000000
26: (7b) *(u64 *)(r10 -192) = r9 ; R9_w=0 R10=fp0 fp-192_w=00000000
27: (7b) *(u64 *)(r10 -200) = r9 ; R9_w=0 R10=fp0 fp-200_w=00000000
28: (7b) *(u64 *)(r10 -208) = r9 ; R9_w=0 R10=fp0 fp-208_w=00000000
29: (7b) *(u64 *)(r10 -216) = r9 ; R9_w=0 R10=fp0 fp-216_w=00000000
30: (7b) *(u64 *)(r10 -224) = r9 ; R9_w=0 R10=fp0 fp-224_w=00000000
31: (7b) *(u64 *)(r10 -232) = r9 ; R9_w=0 R10=fp0 fp-232_w=00000000
32: (7b) *(u64 *)(r10 -240) = r9 ; R9_w=0 R10=fp0 fp-240_w=00000000
33: (7b) *(u64 *)(r10 -248) = r9 ; R9_w=0 R10=fp0 fp-248_w=00000000
34: (7b) *(u64 *)(r10 -256) = r9 ; R9_w=0 R10=fp0 fp-256_w=00000000
35: (7b) *(u64 *)(r10 -264) = r9 ; R9_w=0 R10=fp0 fp-264_w=00000000
36: (b7) r3 = 0 ; R3_w=0
; if (!current_dentry)
37: (15) if r1 == 0x0 goto pc+43 ; R1_w=ptr_dentry(off=0,imm=0)
; int len = bpf_probe_read_str(temp, sizeof(temp), current_dentry->d_name.name);
38: (79) r3 = *(u64 *)(r1 +40) ; R1_w=ptr_dentry(off=0,imm=0) R3_w=scalar()
39: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
40: (07) r1 += -328 ; R1_w=fp-328
; int len = bpf_probe_read_str(temp, sizeof(temp), current_dentry->d_name.name);
41: (b7) r2 = 64 ; R2_w=64
42: (85) call bpf_probe_read_str#45 ; R0=scalar(smin=-4095,smax=64) fp-272=mmmmmmmm fp-280=mmmmmmmm fp-288=mmmmmmmm fp-296=mmmmmmmm fp-304=mmmmmmmm fp-312=mmmmmmmm fp-320=mmmmmmmm fp-328=mmmmmmmm
43: (bf) r6 = r0 ; R0=scalar(id=1,smin=-4095,smax=64) R6_w=scalar(id=1,smin=-4095,smax=64)
44: (bf) r1 = r6 ; R1_w=scalar(id=1,smin=-4095,smax=64) R6_w=scalar(id=1,smin=-4095,smax=64)
45: (67) r1 <<= 32 ; R1_w=scalar(smax=274877906944,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32_max=0)
46: (c7) r1 s>>= 32 ; R1_w=scalar(smin=-2147483648,smax=64)
47: (b7) r2 = 1 ; R2_w=1
48: (b7) r3 = 0 ; R3_w=0
; if (len <= 0 || len >= sizeof(temp)) // Ensure len is valid
49: (6d) if r2 s> r1 goto pc+31 ; R1_w=scalar(umin=1,umax=64,var_off=(0x0; 0x7f)) R2_w=1
50: (18) r1 = 0xffffffc0 ; R1_w=4294967232
52: (bf) r2 = r6 ; R2_w=scalar(id=1,smin=-4095,smax=64) R6_w=scalar(id=1,smin=-4095,smax=64)
53: (5f) r2 &= r1 ; R1_w=4294967232 R2_w=scalar(umax=4294967232,var_off=(0x0; 0xffffffc0),s32_max=2147483584)
54: (b7) r3 = 0 ; R3_w=0
55: (55) if r2 != 0x0 goto pc+25 ; R2_w=0
; if (idx + len + 1 >= sizeof(full_path)) // +1 for '/'
56: (bf) r7 = r6 ; R6_w=scalar(id=1,smin=-4095,smax=64) R7_w=scalar(id=1,smin=-4095,smax=64)
57: (07) r7 += -255 ; R7_w=scalar(umin=18446744073709547266,umax=18446744073709551425,var_off=(0xffffffffffffe000; 0x1fff),u32_min=-4350,u32_max=-191)
58: (bf) r1 = r7 ; R1_w=scalar(id=2,umin=18446744073709547266,umax=18446744073709551425,var_off=(0xffffffffffffe000; 0x1fff),u32_min=-4350,u32_max=-191) R7_w=scalar(id=2,umin=18446744073709547266,umax=18446744073709551425,var_off=(0xffffffffffffe000; 0x1fff),u32_min=-4350,u32_max=-191)
59: (67) r1 <<= 32 ; R1_w=scalar(umin=18446708889337462784,umax=18446744069414584320,var_off=(0xffffe00000000000; 0x1fff00000000),s32_min=0,s32_max=0,u32_max=0)
60: (77) r1 >>= 32 ; R1_w=scalar(umin=4294959104,umax=4294967295,var_off=(0xffffe000; 0x1fff),s32_min=-8192,s32_max=-1)
61: (18) r2 = 0xffffff00 ; R2_w=4294967040
63: (b7) r3 = 0 ; R3=0
; if (idx + len + 1 >= sizeof(full_path)) // +1 for '/'
64: (2d) if r2 > r1 goto pc+16 ; R1=scalar(umin=4294967040,umax=4294967295,var_off=(0xffffff00; 0xff),s32_min=-256,s32_max=-1) R2=4294967040
;
65: (bf) r8 = r6 ; R6=scalar(id=1,smin=-4095,smax=64) R8_w=scalar(id=1,smin=-4095,smax=64)
66: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
67: (07) r1 += -264 ; R1_w=fp-264
68: (bf) r3 = r10 ; R3_w=fp0 R10=fp0
69: (07) r3 += -328 ; R3_w=fp-328
; bpf_probe_read_str(&full_path[idx & 0xFF], len & 0xFF, temp);
70: (bf) r2 = r8 ; R2_w=scalar(id=1,smin=-4095,smax=64) R8_w=scalar(id=1,smin=-4095,smax=64)
71: (85) call bpf_probe_read_str#45
R2 min value is negative, either use unsigned or 'var &= const'
processed 70 insns (limit 1000000) max_states_per_insn 0 total_states 2 peak_states 2 mark_read 1
```
Is this some bug or is my own code wrong?
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the SEC("lsm/path_unlink") entry point and the verifier log around the bpf_probe_read_str calls, using the reported Linux 6.1 environment. Reproduce the load failure and determine whether the rejection is caused by the shown signed length handling or by verifier behavior; done means the cause and a supported correction are documented and verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux
- Domain
- operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100