This is a weird bug I ran into while working on the ebpf. A call to the built-in function ‘memset’ is not supported, and the confusing part was that I was using __builtin_memset. Here is the code.

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>

#define PATH_MAX 1024

struct path_key {
 char container_path[PATH_MAX];  // 1024 bytes
 char directory_path[PATH_MAX];  // 1024 bytes
};

struct {
 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
 __uint(max_entries, 1);
 __type(key, u32);
 __type(value, struct path_key);
} temp_map SEC(".maps");

SEC("kprobe/vfs_open_broken")
int broken_no_barrier(struct pt_regs *ctx)
{
 u32 idx = 0;
 struct path_key *out = bpf_map_lookup_elem(&temp_map, &idx);
 if (!out)
  return 0;

 __builtin_memset(out->container_path, 0, sizeof(out->container_path));
 __builtin_memset(out->directory_path, 0, sizeof(out->directory_path));

 const char *path = "/some/path";
 bpf_probe_read_kernel_str(out->directory_path,
      sizeof(out->directory_path), path);

 return 0;
}

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

And when I commented out one of __builtin_memset it worked, and so it had to be how LLVM was compiling the code, which is most likely the reason for this.

call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(2048) %3, i8 0, i64 2048, i1 false), !dbg !131

LLVM merged my two 1K memsets into a single 2K operation.

Fix

I had to insert an asm volatile memory barrier after each memset asm volatile("" ::: "memory"); https://docs.ebpf.io/ebpf-library/libbpf/ebpf/barrier/ and this prevents the LLVM optimizer from merging the two memsets into one.