Skip to content

modules BTF loading fails when CAP_SYS_ADMIN is missing #1929

@Andreagit97

Description

@Andreagit97

Describe the bug

If during CO-RE relocations the library is not able to find the target type in the running kernel BTF, it searches for it in the modules' BTF. The downside of this approach is that loading modules' BTF requires CAP_SYS_ADMIN, and this prevents BPF applications from running with more granular capabilities (e.g. CAP_BPF) when they don't need to search types into modules' BTF.
It's valid to reference non-existent types when their use is guarded by something like if core_type_exists(...).

This is the same issue I faced in the past with libbpf libbpf/libbpf@3f33f9a. The fix there was to skip the modules' BTF loading phase in case of EPERM.

How to reproduce

This is a repro of the issue.

C part

// go:build ignore
#include "vmlinux.h"
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

char __license[] SEC("license") = "Dual MIT/GPL";

// this kfunc doesn't exist, it is a mocked name
extern int bpf_my_kfunc(int example) __ksym __weak;

SEC("fexit/do_mkdirat")
int BPF_PROG(cgroup_catcher, int dfd, struct filename *name, umode_t mode) {
	if(bpf_ksym_exists(bpf_my_kfunc)) {
		bpf_printk("bpf_my_kfunc is available");
	} else {
		bpf_printk("bpf_my_kfunc is not available");
	}
	return 0;
}

The userspace part

package main

import (
	"log"

	"github.com/cilium/ebpf/rlimit"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -tags linux bpf ./bpf/main.c -- -I/usr/include/ -I../

func main() {
	if err := rlimit.RemoveMemlock(); err != nil {
		log.Fatal(err)
	}

	// Load pre-compiled programs and maps into the kernel.
	objs := bpfObjects{}
	if err := loadBpfObjects(&objs, nil); err != nil {
		log.Fatalf("loading objects: %v", err)
	}

	objs.Close()

	log.Println("Ebpf configuration completed.")
}

If you compile the above program and use the setcap binary, you will see the following

sudo setcap cap_bpf+ep ./main

error:

2026/01/07 12:15:10 loading objects: field CgroupCatcher: program cgroup_catcher: fixing up kfuncs: finding kfunc in kernel: find target in modules: iterate modules: get next BTF ID: operation not permitted

Now, if we set the CAP_SYS_ADMIN capability

sudo setcap cap_sys_admin+ep ./main

We will see there is no errors

2026/01/07 12:15:42 Ebpf configuration completed.

Version information

github.com/cilium/ebpf v0.20.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrelease-blockerNeeds resolution before the next release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions