iovisor / iovisor/bcc

Both bpf_strncmp and user defined strncmp not work

Open
#5,225 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
22.7k
Forks
4.1k
Avg merge
10d 4h
Merged PRs (30d)
3

Description

# The bug
I want to do some string compare in bpfcc uprobe functions.
But both the built-in bpf_strncmp function and my strncmp can not work.

bpf_strncmp will always meet Permission denied.

my_strncmp seems to have encountered some compiler problems,
which can be bypassed by using -O0, but "-O0" may also fail under complicated circumstances.
another kind of workaround is to force the array to be on the stack by modifying the contents of the array.

ubuntu 24.04 with kernel 6.8.0-54-generic
# deb version of bcc
python3-bpfcc = 0.29.1+ds-1ubuntu7
llvm-18-runtime = 1:18.1.3-1

# git version of bcc
bcc = 0.33.0+c8515f71-py3.12
compiled with llvm-toolchain-19 = 1:19.1.1-1ubuntu1~24.04.2

# The code
```
# buggy.py
import sys, os, os.path
try:
from bpfcc import BPF
except:
from bcc import BPF

# bpf 程序
bpf_program = """
#include

#define NAMEBUF_SIZE 32
#define COMM_SIZE 20

static __always_inline int k_strncmp(const char *cs, int size, const char *ct)
{
int len = 0;
unsigned char c1, c2;
for (len=0; len>= 32 ; R3_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))
20: (55) if r3 != 0x647770 goto pc+26 ; R3_w=0x647770
; char *retval = (char *)PT_REGS_RC(ctx);
21: (79) r3 = *(u64 *)(r6 +80) ; R3=scalar() R6=ctx()
; if (retval != NULL) {
22: (15) if r3 == 0x0 goto pc+24 ; R3=scalar(umin=1)
23: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
24: (07) r1 += -64 ; R1_w=fp-64
; bpf_probe_read_str(&ret_name_buf, sizeof(ret_name_buf), retval);
25: (b7) r2 = 32 ; R2_w=32
26: (85) call bpf_probe_read_str#45 ; R0_w=scalar(smin=smin32=-4095,smax=smax32=32) fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm
27: (b7) r1 = 0 ; R1_w=0
; c1 = *cs++;
28: (18) r3 = 0x0 ; R3_w=0
30: (0f) r3 += r1 ; R1_w=0 R3_w=0
31: (bf) r2 = r10 ; R2_w=fp0 R10=fp0
32: (07) r2 += -64 ; R2_w=fp-64
33: (0f) r2 += r1 ; R1_w=0 R2_w=fp-64
34: (71) r2 = *(u8 *)(r2 +0) ; R2_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff)) fp-64=mmmmmmmm
; c2 = *ct++;
35: (71) r3 = *(u8 *)(r3 +0)
R3 invalid mem access 'scalar'
processed 35 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1

Failed to load BPF program b'hook_getcwd_ret1': Permission denied
bpf: Failed to load program: Permission denied
0: R1=ctx() R10=fp0
; int hook_getcwd_ret2(struct pt_regs *ctx) {
0: (bf) r6 = r10 ; R6_w=fp0 R10=fp0
1: (07) r6 += -32 ; R6_w=fp-32
; bpf_get_current_comm(&comm, sizeof(comm));
2: (bf) r1 = r6 ; R1_w=fp-32 R6_w=fp-32
3: (b7) r2 = 20 ; R2_w=20
4: (85) call bpf_get_current_comm#16 ; R0_w=scalar() fp-16=????mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm
5: (b7) r1 = 6584176 ; R1_w=0x647770
; const char comm_pattern[] = "pwd";
6: (63) *(u32 *)(r10 -36) = r1 ; R1_w=0x647770 R10=fp0 fp-40=mmmm????
7: (bf) r3 = r10 ; R3_w=fp0 R10=fp0
8: (07) r3 += -36 ; R3_w=fp-36
; if (bpf_strncmp(comm, COMM_SIZE, comm_pattern) == 0 ) {
9: (bf) r1 = r6 ; R1_w=fp-32 R6_w=fp-32
10: (b7) r2 = 20 ; R2_w=20
11: (85) call bpf_strncmp#182
R3 type=fp expected=map_value
processed 12 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

Failed to load BPF program b'hook_getcwd_ret2': Permission denied
```

# My opinion
I have no idea with hook_getcwd_ret2 / bpf_strncmp, maybe my usage is wrong.
But hook_getcwd_ret1 looks very much like a compiler problem, which is obviously a null pointer dereference.

···
27: (b7) r1 = 0 ; R1_w=0
28: (18) r3 = 0x0 ; R3_w=0
30: (0f) r3 += r1 ; R1_w=0 R3_w=0
35: (71) r3 = *(u8 *)(r3 +0)
···

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with buggy.py and the hook_getcwd_ret1 and hook_getcwd_ret2 entry points, then compare the verifier logs for the custom k_strncmp and bpf_strncmp cases. Reproduce with the stated Ubuntu, kernel, BCC, and LLVM versions; done means both programs load successfully and the comparison behavior is confirmed without relying on the reported workarounds.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux, python
Domain
compilers, devtools, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.