Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Error when using bpf_strncmp #5137

Open
BrianBaboch opened this issue Nov 7, 2024 · 3 comments
Open

Error when using bpf_strncmp #5137

BrianBaboch opened this issue Nov 7, 2024 · 3 comments

Comments

@BrianBaboch
Copy link

BrianBaboch commented Nov 7, 2024

Hello,

I'm having problems when using bpf_strncmp, I have a simple ebpf program using BCC, that program uses bpf_strncmp to compare the task name to a string.
So I do the following:

    char my_com[] = "cat";
    struct task_struct *task = (struct task_struct *)bpf_get_current_task_btf();
    if (bpf_strncmp(comm, sizeof(my_com), my_com) == 0){
        bpf_trace_printk("Cat");
    }

If I use this I get a permission denied error that I can't seem to understand while, if I use strncmp it works as expected

    char my_com[] = "cat";
    struct task_struct *task = (struct task_struct *)bpf_get_current_task_btf();
    if (strncmp(comm, my_com, sizeof(my_com) -1) == 0){
        bpf_trace_printk("Cat");
    }

The error:

    b.attach_raw_tracepoint(tp="sys_enter", fn_name="hello")
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 1061, in attach_raw_tracepoint
    fn = self.load_func(fn_name, BPF.RAW_TRACEPOINT)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 526, in load_func
    raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'hello': Permission denied

In the ebpf compiled code I have the following:

R3 type=fp expected=map_value

However, the bpf_strncmp takes char * as mentioned in the doc so I don't understand the problem

@yonghong-song
Copy link
Collaborator

yonghong-song commented Nov 9, 2024

See error

   R3 type=fp expected=map_value

Here,

  char my_com[] = "cat";

has my_com in stack (fp) and verifier does not like it.

The kernel specification:

static const struct bpf_func_proto bpf_strncmp_proto = {
        .func           = bpf_strncmp,
        .gpl_only       = false,
        .ret_type       = RET_INTEGER,
        .arg1_type      = ARG_PTR_TO_MEM | MEM_RDONLY,
        .arg2_type      = ARG_CONST_SIZE,
        .arg3_type      = ARG_PTR_TO_CONST_STR,
};

The third argument needs to be a ptr to const str.

Try

    char my_com = "cat";

to see whether it works or not.

@kirbyzhou
Copy link

See error
Try

    char my_com = "cat";

to see whether it works or not.

It does not work for me:

Ubuntu 24.04
linux-image-6.8.0-54-generic
python3-bpfcc-0.29.1+ds-1ubuntu7

int hook_getcwd_ret(struct pt_regs *ctx) {
    char comm[COMM_SIZE];
    bpf_get_current_comm(&comm, sizeof(comm));
    const char* comm_pattern = "pwd";
    bpf_strncmp(comm, COMM_SIZE, comm_pattern);
}

bpf: Failed to load program: Permission denied
0: R1=ctx() R10=fp0
; int hook_getcwd_ret(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
; bpf_strncmp(comm, COMM_SIZE, comm_pattern);
5: (bf) r1 = r6                       ; R1_w=fp-32 R6_w=fp-32
6: (b7) r2 = 20                       ; R2_w=20
7: (18) r3 = 0xb                      ; R3_w=11
9: (85) call bpf_strncmp#182
R3 type=scalar expected=map_value
processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
int hook_getcwd_ret(struct pt_regs *ctx) {
    char comm[COMM_SIZE];
    bpf_get_current_comm(&comm, sizeof(comm));
    const char comm_pattern[] = "pwd";
    bpf_strncmp(comm, COMM_SIZE, comm_pattern);
}


bpf: Failed to load program: Permission denied
0: R1=ctx() R10=fp0
; int hook_getcwd_ret(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
; bpf_strncmp(comm, COMM_SIZE, comm_pattern);
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

@wenjianhn
Copy link
Contributor

arg3 of bpf_strncmp is expected to be a value of a read-only map value.

bpf: Add a ARG_PTR_TO_CONST_STR argument type

This type provides the guarantee that an argument is going to be a const
pointer to somewhere in a read-only map value. It also checks that this
pointer is followed by a zero character before the end of the map value.

@yonghong-song could bcc create a read-only map value for static const char comm_pattern[] = "bash"; and then use it to call bpf_strncmp?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants