0

I'm trying to load a BPF program with a queue map. It seems I get an error related to the null key.

libbpf: -- BEGIN DUMP LOG ---
libbpf: 
0: (b7) r1 = 123
1: (63) *(u32 *)(r10 -4) = r1
2: (bf) r3 = r10
3: (07) r3 += -4
4: (18) r1 = 0xffff9df655207800
6: (b7) r2 = 0
7: (b7) r4 = 0
8: (85) call bpf_map_update_elem#2
R2 type=inv expected=fp
processed 8 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

libbpf: -- END LOG --

BPF program

#include <bpf/bpf.h>
#include <string.h>

struct bpf_map SEC("maps") queue_map = {
  .type = BPF_MAP_TYPE_QUEUE,
  .key_size = 0,
  .value_size = sizeof(int),
  .max_entries = 100,
  .map_flags = 0,
};

SEC("tracepoint/syscalls/sys_enter_execve")
int bpf_prog(void *ctx) {

  int value;
  value = 123;
  bpf_map_update_elem(&queue_map, NULL, &value, BPF_ANY);

  return 0;
}

char _license[] SEC("license") = "GPL";

However, if I switch the queue map to an array map by updating .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(int), and provide a valid key to the bpf_map_update_elem function, the bpf program loads and works. I'm loading the program with libbpf.

int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
                       struct bpf_object **pobj, int *prog_fd)
{
  struct bpf_prog_load_attr attr;

  memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
  attr.file = file;
  attr.prog_type = type;
  attr.expected_attach_type = 0;

  return bpf_prog_load_xattr(&attr, pobj, prog_fd);
}
  1. What is causing the error?
  2. I'm using header files from /tools/perf. Should I be using different header files?
  3. Do I need to load queue maps differently than array maps?
  4. Are there map flags I need to add for a queue map?
steepestascent
  • 153
  • 2
  • 7
  • I'm surprised this works for an array map. Is the only thing you changed this line: `.type = BPF_MAP_TYPE_QUEUE,`? Also note that `bpf_map_update_elem` is not a valid helper for queue maps; it will do nothing and return a non-zero error code. – pchaigno May 22 '20 at 07:46
  • @pchaigno in addition to `.type = BPF_MAP_TYPE_QUEUE` I did update the `.key_size = sizeof(int)` and provided a valid `key` to the `bpf_map_update_elem` function. I'll update the question to be more clear. I updated the program to use `bpf_map_push_elem` and the program loads and works as expected! – steepestascent May 23 '20 at 00:08

1 Answers1

1

The verifier complains because it expects a pointer for the second argument to bpf_map_update_elem() (fp for frame pointer, when you have a NULL instead). But as pchaigno mentioned, it's not valid for queue maps; I don't think it would do nothing, I believe it would not pass the verifier (rejected by check_map_func_compatibility() if you could pass this pointer error somehow).

For queues (or stacks) you want to use the bpf_map_(push|pull|peek)_elem() helpers.

For your other questions:

  1. Not sure what headers you use in particular. Depends on what definitions you need I suppose.

  2. You create maps the same way, but update them differently (different helpers, as explained above) - this is the point of having a queue instead of e.g. an array.

  3. No I don't think you need particular flags to create your map.

Qeole
  • 8,284
  • 1
  • 24
  • 52
  • 1
    Thanks for the help. I was referencing an outdated queue map example. I was able to load the program by updating `bpf_map_update_elem(&queue_map, NULL, &value, BPF_ANY);` to `bpf_map_push_elem(&queue_map, &value, BPF_ANY);` and adding this prototype to the file `static int (*bpf_map_push_elem)(void *map, const void *value, unsigned long long flags) = (void *) BPF_FUNC_map_push_elem;` – steepestascent May 23 '20 at 00:23