Unable to unload BPF program

Issue

I am unable to unload a BPF program from code. I am using the Cilium eBPF library to load the program and netlink to add the BPF function to an interface. Here’s what I’m doing:

type BpfObjects struct {
    CollectIpsProg *ebpf.Program        `ebpf:"collect_ips_prog"`
}

    var objects BpfObjects

    // Load the BPF program
    spec, err := ebpf.LoadCollectionSpec("collect_ips.o")

    if err != nil {
        log.Fatalln("ebpf.LoadCollectionSpec", err)
    }

    if err := spec.LoadAndAssign(objects, nil); err != nil {
        log.Fatalln("ebpf.LoadAndAssign", err)
    }

    // Load to XDP
    link, err := netlink.LinkByName("enp0s8")

    if err != nil {
        log.Fatalln("netlink.LinkByName", err)
    }

    err = netlink.LinkSetXdpFdWithFlags(link, objects.CollectIpsProg.FD(), 2)

    if err != nil {
        log.Fatalln("netlink.LinkSetXdpFdWithFlags:", err)
    }
    ...

    // Cleanup. This does not unload the BPF program
    objects.CollectIpsProg.Close()
    objects.CollectIpsProg.Unpin() 

Even though I am closing the program, bpftool prog and xdp-loader status still show the BPF program. I can unload the program using bpftool or xdp-loader.

Solution

eBPF programs only unload when there are no more references to it(File descriptors, pins), but network links also hold their own references. So to unload the program, you first have to detach it from your network link.

You can do so by setting the program fd to -1:

err = netlink.LinkSetXdpFd(link, -1)
if err != nil {
    log.Fatalln("netlink.LinkSetXdpFd:", err)
}

Answered By – Dylan Reimerink

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.