clang-21and the accompanying LLVM toolchain (v21)asm/linux header files (if they are installed but not detected by clang, create a symbolic link from/usr/include/x86_64-linux-gnu/asmto/usr/include/asm)sudo apt install pkg-config libbpf-devbpftool(compiled from kernel source since the correct version is not available via Ubuntu repositories)
mkdir build && cd build
cmake -DLLVM_DIR=$(llvm-config-21 --cmakedir) ..
makelibLLVMPass.soThe LLVM 21 Pass Plugin (build/llvm-pass/libLLMVPass.so)KernelSpaceMonitor.bpf.oCompiled Kernel Space BPF Object (build/ebpf-monitor/KernelSpaceMonitor.bpf.o)KernelSpaceMonitor.skel.hBPF Object Skeleton extracted bybpftool(build/ebpf-monitor/KernelSpaceMonitor.skel.h)eBPFLoaderUser Space BPF Object Skeleton loader (build/ebpf-monitor/eBPFLoader)
Convenience environment variable to set the required compiler flags
LCS_FLAGS="-flto=full -fuse-ld=lld -Wl,--load-pass-plugin=path/to/libLLVMPass.so -Wl,--lto-newpm-passes=null-call-instrumentation-pass"clang-21 $LCS_FLAG [targets]# Save temporary files generated at different stages of LTO
clang-21 $LCS_FLAGS -Wl,--plugin-opt=save-temps [targets]
llvm-dis a.out.0.5.precodegen.bc- Before compiling a target with instrumentation, create a directory
./outputwhere the compiler is being invoked - Run the compiler with flags as given above, the instrumented executable binary as well as DOT files for indivudal
functions, the entire program and a serialized policy file will be created in the
./outputfolder.
The eBPF monitor matches a program being executed to a policy file by the name of the executable. Hence, copy the
generated policy file to a standard policy directory (i.e., /home/vboxuser/.config/LibCallSandboxing/policies) and give it the
same name as of the executable file.
sudo ./eBPFmonitor /home/vboxuser/.config/LibCallSandboxing/policies- To view logs produced by the monitor, run
sudo bpftool prog traceNow run any instrumented executable with name matching that of a policy
- The instrumentation and monitor cannot handle indirect function calls. Such a function call will most likely result in the process being killed.
- Due to restrictions on BPF code, the maximum number of frontier states and the maximum number of edges from a state is limited to a small number (
16for now ininclude/ebpf-monitor/Common.h) - The syscall number has been arbitrarily chosen (
467for now) based on availability in the v6.14 kernel source - It is hardcoded into the LLVM pass for inserting instrumentation
The benchmark file is available in the mbedtls-3.6.5 branch
- Run the default compilation process to generate all library object files using
make - Go to the
programs/testdirectory where thebenchmark.cfile is located - Create the directory for policy output
./output - Provide the
benchmark.csource file for instrumentation and compiled library objects directly
LCS_FLAGS="-flto=full -fuse-ld=lld -Wl,--load-pass-plugin=path/to/libLLVMPass.so -Wl,--lto-newpm-passes=null-call-instrumentation-pass"
clang-21 $(LCS_FLAGS) benchmark.c ../../library/*.o -o benchmark_instrumented- Copy the generated policy file to the policy folder
cp ./output/policy /home/vboxuser/.config/LibCallSandboxing/policies/benchmark_instrumented- Run the instrumented executable
./benchmark_instrumentedNOTE: The benchmark fails right now because it utilizes indirect function calls
- Syscall defined in
LibCallSandboxing/nullcall.cusing theSYSCALL_DEFINE1macro
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE0(hello) {
pr_info("Hello World\n");
return 0;
}- Create
/LibCallSandboxing/Makefilewithobj-y := nullcall.o - Add
asmlinkage long sys_nullcall(long label);in/include/linux/syscalls.h - Add entry to syscall table
arch/x86/entry/syscalls/syscall_64.tbl
467 common nullcall sys_nullcallsudo apt install build-essential vim git cscope libncurses-dev libssl-dev bison flex \
libelf-dev elfutils libdw-dev pahole- Compile with
CONFIG_DEBUG_INFO_BTF=yso that kernel provides/sys/kernel/btf/vmlinuxwhich can be used for BTF CO-RE