diff --git a/eBPFVerifier/1.BackgroundofeBPF.md b/eBPFVerifier/1.BackgroundofeBPF.md new file mode 100644 index 0000000..8289082 --- /dev/null +++ b/eBPFVerifier/1.BackgroundofeBPF.md @@ -0,0 +1,273 @@ +# Background of eBPF + +BPF is a programmable tracer which allows user-defined programs to be executed on events. + +This document is based on analysis of Linux 5.15. + +Linux kernel supports 3 eBPF instruction sets, differs in impact on program size and performance. Set mcpu=probe to use the newest supported version. + +- v1 only supports greater-than jumps. +- v2 only supports both greater-than jumps and lower-than jumps. +- v3, adds 32-bit variants of the existing conditional 64-bit jumps. + +## Register in eBPF ASM + +There are r0-r10 11 registers in eBPF ASM, all registers are 64-bit. It is defined as a struct bpf_insn and struct bpf_insn_aux_data. + +The details are defined in `./linux/include/uapi/linux/bpf.h`, where: + +``` + * All registers are 64-bit. + * R0 (rax) - return register + * R1-R5 argument passing registers + * R6-R9 callee saved registers + * R10 - frame pointer read-only + +R0 (rax): return register +R1 (rdi): arg1 +R2 (rsi): arg2 +R3 (rdx): arg3 +R4 (rcx): arg4 +R5 (r8): arg5 +R6 (rbx): callee saved registers +R7 (r13): callee saved registers +R8 (r14): callee saved registers +R9 (r15): callee saved registers +R10 (rbp): frame pointer read-only +``` + + +## bpf_opcode_in_insntable +``` +bool bpf_opcode_in_insntable(u8 code){#define BPF_INSN_2_TBL(x, y) [BPF_##x | BPF_##y] = true#define BPF_INSN_3_TBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = true + static const bool public_insntable[256] = { + [0 ... 255] = false, + /* Now overwrite non-defaults ... */ + BPF_INSN_MAP(BPF_INSN_2_TBL, BPF_INSN_3_TBL), + /* UAPI exposed, but rewritten opcodes. cBPF carry-over. */ + [BPF_LD | BPF_ABS | BPF_B] = true, + [BPF_LD | BPF_ABS | BPF_H] = true, + [BPF_LD | BPF_ABS | BPF_W] = true, + [BPF_LD | BPF_IND | BPF_B] = true, + [BPF_LD | BPF_IND | BPF_H] = true, + [BPF_LD | BPF_IND | BPF_W] = true, + };#undef BPF_INSN_3_TBL#undef BPF_INSN_2_TBL + return public_insntable[code];} +``` + +## UAPI available opcodes + +``` +#define BPF_INSN_MAP(INSN_2, INSN_3) \ +/* 32 bit ALU operations. */ \ +/* Register based. */ \ +INSN_3(ALU, ADD, X), \ +INSN_3(ALU, SUB, X), \ +INSN_3(ALU, AND, X), \ +INSN_3(ALU, OR, X), \ +INSN_3(ALU, LSH, X), \ +INSN_3(ALU, RSH, X), \ +INSN_3(ALU, XOR, X), \ I +NSN_3(ALU, MUL, X), \ +INSN_3(ALU, MOV, X), \ +INSN_3(ALU, ARSH, X), \ +INSN_3(ALU, DIV, X), \ +INSN_3(ALU, MOD, X), \ +INSN_2(ALU, NEG), \ +INSN_3(ALU, END, TO_BE), \ +INSN_3(ALU, END, TO_LE), \ +/* Immediate based. */ \ +INSN_3(ALU, ADD, K), \ +INSN_3(ALU, SUB, K), \ +INSN_3(ALU, AND, K), \ +INSN_3(ALU, OR, K), \ +INSN_3(ALU, LSH, K), \ +INSN_3(ALU, RSH, K), \ +INSN_3(ALU, XOR, K), \ +INSN_3(ALU, MUL, K), \ +INSN_3(ALU, MOV, K), \ +INSN_3(ALU, ARSH, K), \ +INSN_3(ALU, DIV, K), \ +INSN_3(ALU, MOD, K), \ +/* 64 bit ALU operations. */ \ +/* Register based. */ \ +INSN_3(ALU64, ADD, X), \ +INSN_3(ALU64, SUB, X), \ +INSN_3(ALU64, AND, X), \ +INSN_3(ALU64, OR, X), \ +INSN_3(ALU64, LSH, X), \ +INSN_3(ALU64, RSH, X), \ +INSN_3(ALU64, XOR, X), \ +INSN_3(ALU64, MUL, X), \ +INSN_3(ALU64, MOV, X), \ +INSN_3(ALU64, ARSH, X), \ +INSN_3(ALU64, DIV, X), \ +INSN_3(ALU64, MOD, X), \ +INSN_2(ALU64, NEG), \ +/* Immediate based. */ \ +INSN_3(ALU64, ADD, K), \ +INSN_3(ALU64, SUB, K), \ +INSN_3(ALU64, AND, K), \ +INSN_3(ALU64, OR, K), \ +INSN_3(ALU64, LSH, K), \ +INSN_3(ALU64, RSH, K), \ +INSN_3(ALU64, XOR, K), \ +INSN_3(ALU64, MUL, K), \ +INSN_3(ALU64, MOV, K), \ +INSN_3(ALU64, ARSH, K), \ +INSN_3(ALU64, DIV, K), \ +INSN_3(ALU64, MOD, K), \ +/* Call instruction. */ \ +INSN_2(JMP, CALL), \ +/* Exit instruction. */ \ +INSN_2(JMP, EXIT), \ +/* 32-bit Jump instructions. */ \ +/* Register based. */ \ +INSN_3(JMP32, JEQ, X), \ +INSN_3(JMP32, JNE, X), \ +INSN_3(JMP32, JGT, X), \ +INSN_3(JMP32, JLT, X), \ +INSN_3(JMP32, JGE, X), \ +INSN_3(JMP32, JLE, X), \ +INSN_3(JMP32, JSGT, X), \ +INSN_3(JMP32, JSLT, X), \ +INSN_3(JMP32, JSGE, X), \ +INSN_3(JMP32, JSLE, X), \ +INSN_3(JMP32, JSET, X), \ +/* Immediate based. */ \ +INSN_3(JMP32, JEQ, K), \ +INSN_3(JMP32, JNE, K), \ +INSN_3(JMP32, JGT, K), \ +INSN_3(JMP32, JLT, K), \ +INSN_3(JMP32, JGE, K), \ +INSN_3(JMP32, JLE, K), \ +INSN_3(JMP32, JSGT, K), \ +INSN_3(JMP32, JSLT, K), \ +INSN_3(JMP32, JSGE, K), \ +INSN_3(JMP32, JSLE, K), \ +INSN_3(JMP32, JSET, K), \ +/* Jump instructions. */ \ +/* Register based. */ \ +INSN_3(JMP, JEQ, X), \ +INSN_3(JMP, JNE, X), \ +INSN_3(JMP, JGT, X), \ +INSN_3(JMP, JLT, X), \ +INSN_3(JMP, JGE, X), \ +INSN_3(JMP, JLE, X), \ +INSN_3(JMP, JSGT, X), \ +INSN_3(JMP, JSLT, X), \ +INSN_3(JMP, JSGE, X), \ +INSN_3(JMP, JSLE, X), \ +INSN_3(JMP, JSET, X), \ +/* Immediate based. */ \ +INSN_3(JMP, JEQ, K), \ +INSN_3(JMP, JNE, K), \ +INSN_3(JMP, JGT, K), \ +INSN_3(JMP, JLT, K), \ +INSN_3(JMP, JGE, K), \ +INSN_3(JMP, JLE, K), \ +INSN_3(JMP, JSGT, K), \ +INSN_3(JMP, JSLT, K), \ +INSN_3(JMP, JSGE, K), \ +INSN_3(JMP, JSLE, K), \ +INSN_3(JMP, JSET, K), \ +INSN_2(JMP, JA), \ +/* Store instructions. */ \ +/* Register based. */ \ +INSN_3(STX, MEM, B), \ +INSN_3(STX, MEM, H), \ +INSN_3(STX, MEM, W), \ +INSN_3(STX, MEM, DW), \ +INSN_3(STX, ATOMIC, W), \ +INSN_3(STX, ATOMIC, DW), \ +/* Immediate based. */ \ +INSN_3(ST, MEM, B), \ +INSN_3(ST, MEM, H), \ +INSN_3(ST, MEM, W), \ +INSN_3(ST, MEM, DW), \ +/* Load instructions. */ \ +/* Register based. */ \ +INSN_3(LDX, MEM, B), \ +INSN_3(LDX, MEM, H), \ +INSN_3(LDX, MEM, W), \ +INSN_3(LDX, MEM, DW), \ +/* Immediate based. */ \ +INSN_3(LD, IMM, DW) +``` + +## eBPF prog + +eBPF prog is defined as `struct bpf_prog` in +https://elixir.bootlin.com/linux/v5.16/source/include/linux/filter.h#L562 + +## Workflow of eBPF + +1. eBPF is compiled to eBPF ASM, and in form of "struct bpf_insn" mentioned in previous section. +2. bpf_prog_load then load, compile and execute the eBPF ASM. + 1. attrs and permission checks + 2. allocates program in kernel space bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER) bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER) + 3. LSM hook check. security_bpf_prog_alloc(prog->aux) + 4. assign length of instructions, prog->len = attr->insn_cnt + 5. copy instructions from userpace to kernel space + copy_from_bpfptr(prog->insns, + make_bpfptr(attr->insns, uattr.is_kernel), + bpf_prog_insn_size(prog)) + 6. fills ops with eBPF program's type find_prog_type(type, prog) + 7. call eBPF verifier bpf_check(&prog, attr, uattr) + 8. select runtime bpf_prog_select_runtime(prog, &err) + 9. assign id to compiled eBPF verifier, which will be used in bpftools later. bpf_prog_alloc_id(prog) + 10. invoke audit logs and cleaning + +## Functions supported by eBPF: +``` +enum bpf_cmd { + BPF_MAP_CREATE, + BPF_MAP_LOOKUP_ELEM, + BPF_MAP_UPDATE_ELEM, + BPF_MAP_DELETE_ELEM, + BPF_MAP_GET_NEXT_KEY, + BPF_PROG_LOAD, + BPF_OBJ_PIN, + BPF_OBJ_GET, + BPF_PROG_ATTACH, + BPF_PROG_DETACH, + BPF_PROG_TEST_RUN, + BPF_PROG_RUN = BPF_PROG_TEST_RUN, + BPF_PROG_GET_NEXT_ID, + BPF_MAP_GET_NEXT_ID, + BPF_PROG_GET_FD_BY_ID, + BPF_MAP_GET_FD_BY_ID, + BPF_OBJ_GET_INFO_BY_FD, + BPF_PROG_QUERY, + BPF_RAW_TRACEPOINT_OPEN, + BPF_BTF_LOAD, + BPF_BTF_GET_FD_BY_ID, + BPF_TASK_FD_QUERY, + BPF_MAP_LOOKUP_AND_DELETE_ELEM, + BPF_MAP_FREEZE, + BPF_BTF_GET_NEXT_ID, + BPF_MAP_LOOKUP_BATCH, + BPF_MAP_LOOKUP_AND_DELETE_BATCH, + BPF_MAP_UPDATE_BATCH, + BPF_MAP_DELETE_BATCH, + BPF_LINK_CREATE, + BPF_LINK_UPDATE, + BPF_LINK_GET_FD_BY_ID, + BPF_LINK_GET_NEXT_ID, + BPF_ENABLE_STATS, + BPF_ITER_CREATE, + BPF_LINK_DETACH, + BPF_PROG_BIND_MAP, +}; +``` +### bpf_prog_load + +Verify and load an eBPF program, returning a new file descriptor associated with the program. Return a new file descriptor (a nonnegative integer), or -1 if an error occurred (in which case, *errno* is set appropriately), the details could be find in https://elixir.bootlin.com/linux/v5.16/source/kernel/bpf/syscall.c#L2203 + +### bpf_prog_select_runtime +bpf_prog_select_runtime selects exec runtime for BPF program. It JIT eBPF program, if JIT is not available, use an interpreter. Return value, the &fp argument along with &err set to 0 for success or * a negative errno code on failure. + +### bpf_check +https://elixir.bootlin.com/linux/v5.16/source/kernel/bpf/verifier.c#L13916 +bpf_check verifies correctness of eBPF program. + diff --git a/eBPFVerifier/2.QuickStarteBPF.md b/eBPFVerifier/2.QuickStarteBPF.md new file mode 100644 index 0000000..fcafaf4 --- /dev/null +++ b/eBPFVerifier/2.QuickStarteBPF.md @@ -0,0 +1,344 @@ +# Quick Start for eBPF + +This document is based on analysis of Linux 5.15. + +Linux kernel supports 3 eBPF instruction sets, differs in impact on program size and performance. Set mcpu=probe to use the newest supported version. +- v1 only supports greater-than jumps. +- v2 only supports both greater-than jumps and lower-than jumps. +- v3, adds 32-bit variants of the existing conditional 64-bit jumps. + + +This document is for LLVM 10.0.1 +``` +$ llc -march=bpf -mcpu=help +Available CPUs for this target: + + generic - Select the generic processor. + probe - Select the probe processor. + v1 - Select the v1 processor. + v2 - Select the v2 processor. + v3 - Select the v3 processor. + +Available features for this target: + + alu32 - Enable ALU32 instructions. + dummy - unused feature. + dwarfris - Disable MCAsmInfo DwarfUsesRelocationsAcrossSections. + +Use +feature to enable a feature, or -feature to disable it. +For example, llc -mcpu=mycpu -mattr=+feature1,-feature2 + +``` + +## 1. Install Dependencies + +### 0. 1. Update Linux Kernel + +``` +sudo apt-get install make cmake libncurses5-dev flex bison libssl-dev dkms libelf-dev git + +git clone https://github.com/torvalds/linux.git +cd linux/ +git tag +git checkout v5.15 +make config +make -j4 +sudo make modules_install +sudo make install +sudo update-grub2 +sudo reboot +``` + +### 1. install cmake +``` +sudo apt-get install libssl-dev +git clone https://github.com/Kitware/CMake.git +cd CMake/ +git checkout release +./bootstrap && make && sudo make install +``` +### 2. install python3 +``` +wget https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tgz +tar -xvf Python-3.10.2.tgz +cd Python-3.10.2/ +./configure +make +make test +sudo make install +python3 --version +which python3 +``` + +## 2. Install LLVM + +``` +sudo apt-get install cmake ninja-build gcc +sudo apt install clang-11 --install-suggests + + +git clone https://github.com/llvm/llvm-project.git +cd llvm-project +git checkout llvmorg-10.0.1 +mkdir build +cd build +cmake -DLLVM_ENABLE_PROJECTS=clang "Unix Makefiles" ../llvm +cmake -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ../llvm +make -j4 +sudo cmake --build . --target install +ls ./llvm-project/build/bin/ +``` +The binaries are located in `./llvm-project/build/bin/` + + +## 3. Compile BPF Program + +To use LLVM LLC to compile your BPF program. +``` +clang -O2 -Wall -target bpf -emit-llvm -c example.c -o example.bc +lli example.bc +llc example.bc -march=bpf -mcpu=probe -filetype=obj -o example.o +readelf -x .text example.o +``` +-mcpu parameter defaults to generic, an alias for v1, the oldest instruction set. probe will select the newest instruction set your kernel supports. + +## 4. Load BPF Program + +To load userpace programs to kernel space, you can use bpftool based on libbpf. + +The source code for bpftool can be found in the Linux kernel repository, under tools/bpf/bpftool + +1. Install bpftool binary +``` +sudo apt install linux-tools-common linux-tools-generic +sudo apt-get install libz-dev +``` +2. Install bpftool from source + +``` +sudo apt-get install libz-dev +git clone https://github.com/torvalds/linux.git +cd linux +git checkout v5.15 +cd tools/bpf/bpftool +make +make install +make doc doc-install +``` + +## 5. Load Program +``` +bpftool -V +bpftool version -p + +bpftool prog show +bpftool prog list + +bpftool prog load example.o /sys/fs/bpf/example + +bpftool prog show --json id 3 +bpftool prog dump xlated id 3 +bpftool prog dump jited pinned /sys/fs/bpf/example + +bpftool prog show --bpffs +bpftool -f map + +bpftool map show + +bpftool prog pin id 27 /sys/fs/bpf/example_prog +rm /sys/fs/bpf/example_prog + +bpftool prog tracelog +cat /sys/kernel/debug/tracing/trace_pipe +``` + +Once loaded, programs of the relevant types can be attached to sockets with: +``` +# bpftool prog attach +``` + + +For attaching programs to cgroup, the command differs: +``` +# bpftool cgroup attach [flags] +``` + +And like ip link, bpftool can attach programs to the XDP hook (and later detach them): +``` +# bpftool net attach xdp id 42 dev eth0 +# bpftool net detach xdp dev eth0 +``` +The xdpgeneric/xdpdrv/xdpoffload variants for generic XDP (a.k.a SKB XDP), driver XDP (a.k.a native XDP), or XDP hardware offload, are also supported. + + +## 6. Reusing Maps +Load a program, but reuse for example two existing maps (instead of automatically creating new ones): +``` +# bpftool prog load example.o /sys/fs/bpf/example_prog \ + map idx 0 id 27 \ + map name stats pinned /sys/fs/bpf/stats_map +``` +where idx 0 is the index of the map in the ELF program file. + + +## 7. Loading Several Programs +For object files with more than one program, bpftool can load all of them at once: +``` +# bpftool prog loadall example_flow.o /sys/fs/bpf/flow type flow_dissector +``` +This is especially useful when working with tail calls. Maps can be pinned by adding pinmaps ``. + + +## 8. Test Runs + +`BPF_PROG_TEST_RUN` is a command for the bpf() system call. + +It is used to manually trigger a “test” run for a program loaded in the kernel, with specific input data (for example: packet data) and context (for example: struct __sk_buff). + +It returns the output data and context, the return value of the program, and the duration of the execution. + +Although this feature is not available to all program types, bpftool can use it to test-run programs: +``` +# bpftool prog run PROG data_in data_out +``` + +## 9. Profiling Programs + +Recent bpftool versions can attach programs (of types “fentry” or “fexit”) to the entry or exit of other eBPF programs and use perf events to collect statistics on them. + +``` +# bpftool prog profile +``` + +This requires that the kernel running on the system has been compiled with BTF information, and bpftool with the use of a “skeleton”. +Here is another example, featuring two metrics that were more recently added: ITLB and DTLB misses for a running eBPF program. + +``` +# bpftool prog profile itlb_misses dtlb_misses +``` + + +## 10. Program Stat + +Linux 5.1 introduced statistics for attached eBPF programs: it can collect the total run time and the run count for each program. + +When available, this information is displayed by bpftool when listing the programs: +``` +# bpftool prog show +``` +Gathering statistics impacts performance of program execution by ~10 to 30 nanoseconds per run, so it is disabled by default. + +Activate it with: +``` +# sysctl -w kernel.bpf_stats_enabled=1 +``` + +## 11. Managing with libbpf + +libbpf: https://github.com/libbpf/libbpf + +``` +git clone https://github.com/libbpf/libbpf.git +cd libbpf +cd src +mkdir build root +BUILD_STATIC_ONLY=y OBJDIR=build DESTDIR=root make install +PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make install +``` + +## 12. Edit BPF Bytecode + +Instead of compiling an eBPF program from C to an ELF object file, we could compile it to an assembly language, edit it accordingly, then assemble this version as the final object file.  + +1. Source Code + +``` +$ cat example.c +int func() +{ + return 0; +} +``` + +2. Compiling from C to eBPF Assembly +``` +$ clang -target example -S -o example.s example.c +$ cat example.s + .text + .globl func # -- Begin function func + .p2align 3 +func: # @func +# %bb.0: + r1 = 0 + *(u32 *)(r10 - 4) = r1 + r0 = r1 + exit + +``` + +3. Modify +``` +$ sed -i '$a \\tr0 = 3' example.s +$ cat example.s + .text + .globl func # -- Begin function func + .p2align 3 +func: # @func +# %bb.0: + r1 = 0 + *(u32 *)(r10 - 4) = r1 + r0 = r1 + exit + # -- End function + + r0 = 3 +# Assembling to an ELF Object File + llvm-mc -triple example -filetype=obj -o example.o example.s +# dump the bytecode +$ readelf -x .text example.o + +Hex dump of section '.text': + 0x00000000 b7010000 00000000 631afcff 00000000 ........c....... + 0x00000010 bf100000 00000000 95000000 00000000 ................ + 0x00000020 b7000000 03000000 b7000000 03000000 ................ +$ llvm-objdump -d example.o +$ llvm-objdump -S example.o # add C code, if -g was passed to clang + +bpf.o: file format ELF64-BPF + +Disassembly of section .text: +func: + 0: b7 01 00 00 00 00 00 00 r1 = 0 + 1: 63 1a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r1 + 2: bf 10 00 00 00 00 00 00 r0 = r1 + 3: 95 00 00 00 00 00 00 00 exit + 4: b7 00 00 00 03 00 00 00 r0 = 3 +``` + + +## 13. Add Debug Symbols +``` +$ clang -target example -g -S -o example.s example.c +$ llvm-mc -triple example -filetype=obj -o example.o example.s +$ llvm-objdump -S example.o +``` + +## 14. Install BCC + +``` +sudo apt-get install arping bison clang-format cmake dh-python dpkg-dev pkg-kde-tools ethtool flex inetutils-ping iperf   libbpf-dev libclang-dev libedit-dev libelf-dev libfl-dev libzip-dev linux-libc-dev llvm-dev libluajit-5.1-dev   luajit python3-netaddr python3-pyroute2 +sudo apt install -y bison build-essential cmake flex git libedit-dev   libllvm11 llvm-11-dev libclang-11-dev python zlib1g-dev libelf-dev libfl-dev +sudo apt install clang-11 --install-suggests +sudo apt-get -y install luajit luajit-5.1-dev + +git clone https://github.com/iovisor/bcc.git +mkdir bcc/build; cd bcc/build +cmake .. +make +sudo make instal +``` +## 15. Reference + +1. An assembler for eBPF programs written in Intel-like assembly syntax. https://github.com/Xilinx-CNS/ebpf_asm + +3. BPF commands https://qmonnet.github.io/whirl-offload/2021/09/23/bpftool-features-thread/ diff --git a/eBPFVerifier/README.md b/eBPFVerifier/README.md new file mode 100644 index 0000000..0f4aa04 --- /dev/null +++ b/eBPFVerifier/README.md @@ -0,0 +1,97 @@ +# eBPF Verifier Introduction + v +This documentation is based on Linux v5.17 and it is also applicable to v5.15, the LTS version. + +The Berkeley Packet Filter (eBPF) enables user space programs to execute in the Linux kernel. + +Before eBPF, kernel code was mainly released as kernel patches and kernel modules. The eBPF enables program to be loaded from user space and run in kernel space. Some insecure programs might be introduced by these eBPF programs during this process. + +Thus, an eBPF verifier is needed to conduct static analysis to reject and disapprove the insecure programs executing in kernel address space. + +eBPF verifier is an event driven framework, where the events are triggered by kernel hooks. +Hooks monitors: +(1) syscalls, +(2) function entry and exit, +(3) network events and +(4) kprobes and uprobes. + +The current set of eBPF program types supported by the kernel is as following, Linux 5.16 source code: + +``` +- BPF_PROG_TYPE_SOCKET_FILTER: a network packet filter +- BPF_PROG_TYPE_KPROBE: determine whether a kprobe should fire or not +- BPF_PROG_TYPE_SCHED_CLS: a network traffic-control classifier +- BPF_PROG_TYPE_SCHED_ACT: a network traffic-control action +- BPF_PROG_TYPE_TRACEPOINT: determine whether a tracepoint should fire or not +- BPF_PROG_TYPE_XDP: a network packet filter run from the device-driver receive path +- BPF_PROG_TYPE_PERF_EVENT: determine whether a perf event handler should fire or not +- BPF_PROG_TYPE_CGROUP_SKB: a network packet filter for control groups +- BPF_PROG_TYPE_CGROUP_SOCK: a network packet filter for control groups that is allowed to modify socket options +- BPF_PROG_TYPE_LWT_*: a network packet filter for lightweight tunnels +- BPF_PROG_TYPE_SOCK_OPS: a program for setting socket parameters +- BPF_PROG_TYPE_SK_SKB: a network packet filter for forwarding packets between sockets +- BPF_PROG_CGROUP_DEVICE: determine if a device operation should be permitted or not +``` + + +## eBPF Passes + +Currently the eBPF verifier is focusing on verifying/validating "function entry and exit". + + +There are two passes in eBPF verifier: + +- 1. DAG checks, uses depth first search to check if the bytecode of eBPF program could be parsed into a DAG, and check DAG for unreachable instructions and worst execution time. + +- 2. FSM checks, creates finite state machines, explore all execution paths from the entry instruction of eBPF program, verifies and monitors if states present valid/correct behaviors. + +eBPF verifier builds and checks the control flow graph (i.e. a Directed Acyclic Graph) of programs, and verifies/validates the function calls. + +It also simulates instruction execution and monitors state change of registers and stack. + +The calls to unknown functions and unresolved function calls will be rejected. + +For example, eBPF confirms program ends with BPF_EXIT, and confirms all branch instructions, except for BPF_EXIT and BPF_CALL, are within program bounds. + +The current eBPF verifier performs: +- checking performance bug: + - if a program execution ends (e.g. bounded loops) + - checking depth of execution path +- checking memory safety: + - if memory address addresses are within memorn boundary + - invalid accessing uninitilized contents in registers +- type checking, type checking of load/store instructions of registers with valid typed +- ownership checking, eBPF programs may read data if the program wrote it + + +## Issues with eBPF + +Some Issues with eBPF programs: +1. cannot perform dynamic allocation +2. cannot access kernel data structures +3. cannot call in-kernel APIs +4. run in single-threaded mode +5. execution time is bounded +6. do not have indirect jumps . Each jump instruction in eBPF program points to a fixed location in the code +7. Heavily uses pointers and pointer arithemetic +8. reliance on register spilling +9. manipulates a fixed number for exclusively owned memory regions + + + +## References + +1. BPF: the universal in-kernel virtual machine https://lwn.net/Articles/599755/ +2. eBPF - extended Berkeley Packet Filter: https://prototype-kernel.readthedocs.io/en/latest/bpf/ +3. (PLDI'19) Simple and Precise Static Analysis of Untrusted Linux Kernel extensions https://vbpf.github.io/assets/prevail-paper.pdf , https://github.com/vbpf/ebpf-verifier +4. eBPF verifier code in Linux v5.14.14, https://github.com/torvalds/linux/blob/master/kernel/bpf/verifier.c +5. Rust for Linux, https://github.com/Rust-for-Linux +6. Bounded loops in BPF for the 5.3 kernel , https://lwn.net/Articles/794934/ +7. eBPF config in Linux v5.15.11, https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/bpf_common.h +8. Interactive Map for DataStructure, https://makelinux.github.io/kernel/map/ + + + + + +