Skip to content

A super lightweight flexible eBPF loader neither using bcc nor libbpf; supports writing and using eBPF filters on different hosts.

Notifications You must be signed in to change notification settings

Abracax/ebpf_bytecode_loader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

An eBPF Loader without Libbpf and bcc

This is a super lightweight eBPF loader that separates filter-writing and filter-using. It uses neither libbpf nor bcc, thus using no heavy object files.

The main feature of this loader is that it treats writing filters and inserting filters as independent processes, allowing them to be completed on different machines (e.g. local and server), which is not supported by libbpf or bcc.

This loader extracts bytecode instruction streams from eBPF filters written in C that can be directly inserted into the kernel using the bpf syscall.

The current example is an ICMP filter, logging information of ICMP packets to trace pipe. Use sudo cat /sys/kernel/debug/tracing/trace_pipe to see printk logging.

Installation Requirements

  • Linux Kernel Headers with BPF support
  • libelf

Usage

sh build.sh <ebpf source code path> <ebpf main section name>

Example Output:

sh build.sh example_filters/ebpf_filter.c section_name

object file name: example_filters/ebpf_filter
section name: section_name

instruction stream:
{
    {0xb7, 0x0, 0x0, 0x2}, 
    {0x1261, 0x50, 0x0, 0x0}, 
    {0x1161, 0x4c, 0x0, 0x0}, 
    {0x107, 0x0, 0x0, 0xe}, 
    {0x212d, 0xe, 0x0, 0x0}, 
    {0x1b7, 0x0, 0x0, 0xa}, 
    {0x1a6b, 0xf0, 0xff, 0x0}, 
    {0x118, 0x0, 0x0, 0x75206e61}, 
    {0x0, 0x0, 0x0, 0x75253a70}, 
    {0x1a7b, 0xe8, 0xff, 0x0}, 
    {0x118, 0x0, 0x0, 0x74736554}, 
    {0x0, 0x0, 0x0, 0x656c6320}, 
    {0x1a7b, 0xe0, 0xff, 0x0}, 
    {0xa1bf, 0x0, 0x0, 0x0}, 
    {0x107, 0x0, 0x0, 0xffffffe0}, 
    {0x2b7, 0x0, 0x0, 0x12}, 
    {0x3b7, 0x0, 0x0, 0x8}, 
    {0x85, 0x0, 0x0, 0x6}, 
    {0xb7, 0x0, 0x0, 0x0}, 
    {0x95, 0x0, 0x0, 0x0}, 
};

number of instructions: 20

Then use Syscall bpf to load output bytecode filter to kernel, copy the output instruction stream and filter length to struct bpfinstr filter[].

struct bpfinstr
{
    uint16_t code;
    uint8_t jt;
    uint8_t jf;
    uint32_t k;
};

int main()
{
    char license[ELF_MAX_LICENSE_LEN] = "GPL";
    int filter_len = 20;
    struct bpfinstr filter[] = {
		{0xb7, 0x0, 0x0, 0x2},
		{0x1261, 0x50, 0x0, 0x0},
		{0x1161, 0x4c, 0x0, 0x0},
		{0x107, 0x0, 0x0, 0xe},
		{0x212d, 0xe, 0x0, 0x0},
		{0x1b7, 0x0, 0x0, 0xa},
		{0x1a6b, 0xf0, 0xff, 0x0},
		{0x118, 0x0, 0x0, 0x75206e61},
		{0x0, 0x0, 0x0, 0x75253a70},
		{0x1a7b, 0xe8, 0xff, 0x0},
		{0x118, 0x0, 0x0, 0x74736554},
		{0x0, 0x0, 0x0, 0x656c6320},
		{0x1a7b, 0xe0, 0xff, 0x0},
		{0xa1bf, 0x0, 0x0, 0x0},
		{0x107, 0x0, 0x0, 0xffffffe0},
		{0x2b7, 0x0, 0x0, 0x12},
		{0x3b7, 0x0, 0x0, 0x8},
		{0x85, 0x0, 0x0, 0x6},
		{0xb7, 0x0, 0x0, 0x0},
		{0x95, 0x0, 0x0, 0x0},
    };

    union bpf_attr attr = {
        .prog_type = 3,
        .insns = (uintptr_t)filter,
        .insn_cnt = filter_len,
        .license = (uintptr_t)license
    };

    int fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
    
    if (fd > 0) {
        printf("eBPF filter loaded, fd=%d", %d);
        return 0;
    }
    
	return fd;
}

Limitations

No BPF map support!

About

A super lightweight flexible eBPF loader neither using bcc nor libbpf; supports writing and using eBPF filters on different hosts.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages