Search code examples
bpfebpfbcc-bpf

Failure to compare strings with eBPF


When I run the following code I get an error.

#include <uapi/linux/utsname.h>
#include <linux/pid_namespace.h>

struct uts_namespace {
    struct kref kref;
    struct new_utsname name;
};

static __always_inline char * get_task_uts_name(struct task_struct *task){
    return task->nsproxy->uts_ns->name.nodename;
}

int cmpNamespace(void *ctx) {
  struct task_struct *task;
  task = (struct task_struct *)bpf_get_current_task();

  if (strcmp(get_task_uts_name(task),"namespace")==0){

      ...

  }
  return 0;
}

Error:

bpf: Failed to load program: Invalid argument
unknown opcode 00
processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

HINT: The 'unknown opcode' can happen if you reference a global or static variable, or data in read-only section. For example, 'char *p = "hello"' will result in p referencing a read-only section, and 'char p[] = "hello"' will have "hello" stored on the stack.

But this works just fine

int cmpNamespace(void *ctx) {
  char * test = "aaaa";

  if (strcmp(test,"namespace")==0){

      ...

  }
  return 0;
}

Can anyone tell me why this is happening and how I could go about correcting it ? I am using python bcc to hook the function.

Thanks!


Solution

  • The issue is that you are using strcmp. BPF programs cannot use functions from the libc.

    Your second example probably works because the compiler is able to optimize it and remove the call to strcmp. Since both arguments are known at compile-time, there's no need to use strcmp to know if they are equal.

    As pointed out by @Qeole in comments, you can use __builtin_memcmp() instead, since you know the size of one of your strings and are only trying to know if they are equal.