Skip to content

Commit

Permalink
edriver-rust: just for fun
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskaliX committed Feb 5, 2024
1 parent a16fe4d commit a867941
Show file tree
Hide file tree
Showing 63 changed files with 40,751 additions and 3 deletions.
21 changes: 21 additions & 0 deletions plugins/edrivers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "edrivers"
version = "0.1.0"
edition = "2021"
authors = ["chriskali <chriskalix@protonmail.com>"]
description = "Rust version of hades edriver"

[features]
debug = ["sdk/debug"]
static = ["libbpf-rs/static"]

[dependencies]
anyhow = "1.0"
log = { version = "0.4", features = ["std"] }
libc = "0.2.0"
libbpf-rs = {version = "0.22.1", features=["static"]}
libbpf-sys = { version = "1.2.1" }
sdk = { path = "../../SDK/rust" }

[build-dependencies]
libbpf-cargo = "0.22.1"
38 changes: 38 additions & 0 deletions plugins/edrivers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
CMD_CLANG ?= clang

LIB_PATH := ../libs
LIBBPF_CFLAGS = "-fPIC"
LIBBPF_LDLAGS =
LIBBPF_SRC = $(LIB_PATH)/libbpf/src

headers/libbpf/libbpf.a: \
$(LIBBPF_SRC) \
$(wildcard $(LIBBPF_SRC)/*.[ch]) \

CC="$(CMD_CLANG)" \
CFLAGS="$(LIBBPF_CFLAGS)" \
LD_FLAGS="$(LIBBPF_LDFLAGS)" \
$(MAKE) \
-C $(LIBBPF_SRC) \
BUILD_STATIC_ONLY=1 \
DESTDIR=$(abspath ./src/bpf/headers/libbpf/) \
OBJDIR=$(abspath ./src/bpf/headers/libbpf/obj) \
INCLUDEDIR= LIBDIR= UAPIDIR= prefix= libdir= \
install install_uapi_headers
install -m 0640 ./src/bpf/headers/libbpf/bpf/*.h ./src/bpf/headers/

build: \
headers/libbpf/libbpf.a

cargo fmt
RUSTFLAGS="-C target-feature=+crt-static -L /usr/lib/x86_64-linux-gnu/" cargo build --release --target x86_64-unknown-linux-gnu --features=static

debug: \
headers/libbpf/libbpf.a

cargo fmt
RUST_BACKTRACE=1 RUSTFLAGS="-C target-feature=+crt-static -L /usr/lib/x86_64-linux-gnu/" cargo build --release --target x86_64-unknown-linux-gnu --features=static,debug

test:
cargo fmt
RUSTFLAGS="-C target-feature=+crt-static -L /usr/lib/x86_64-linux-gnu/" cargo test --target x86_64-unknown-linux-gnu --features=debug,static
2 changes: 2 additions & 0 deletions plugins/edrivers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
THE RUST VERSION IS NOT AVAILABLE
USE EDRIVER INSTEAD
26 changes: 26 additions & 0 deletions plugins/edrivers/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use libbpf_cargo::SkeletonBuilder;
use std::path::Path;

const SRC: &str = "src/bpf/hades.bpf.c";

fn main() {
let out = Path::new("./src/bpf/hades.skel.rs");

SkeletonBuilder::new()
.source(SRC)
.clang_args(
"-c
-D__BPF_TRACING__
-DCORE
-I src/bpf/headers/
-I../libs/core/
-I../libs/bpfheaders/
-I src/bpf/
-target bpf
-O2 -g
-march=bpf -mcpu=v2",
)
.debug(false)
.build_and_generate(&out)
.unwrap();
}
215 changes: 215 additions & 0 deletions plugins/edrivers/src/bpf/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
# Precheck for tools and their versions.
CMD_TR ?= tr
CMD_CUT ?= cut
CMD_LLC ?= llc
CMD_CLANG ?= clang
CMD_GO ?= go
CMD_AWK ?= awk
CMD_SED ?= sed
CMD_CUT ?= cut
CMD_GIT ?= git
CMD_MD5 ?= md5

OPT ?= opt
LLVM_DIS ?= llvm-dis
CMD_LLVM_STRIP ?= llvm-strip
EXECUTABLES = $(CMD_TR) $(CMD_CUT) $(CMD_LLC) $(CMD_CLANG) $(CMD_LLVM_STRIP)
CHECK_TOOLS_EXSITS := $(foreach exec,$(EXECUTABLES),\
$(if $(shell command -v $(exec) 2> /dev/null), ,then $(error "No $(exec) in PATH")) )
CLANG_VERSION := $(shell $(CMD_CLANG) --version 2>/dev/null | \
head -1 | $(CMD_TR) -d '[:alpha:]' | $(CMD_TR) -d '[:space:]' | $(CMD_CUT) -d'.' -f1)
GO_VERSION := $(shell $(CMD_GO) version 2>/dev/null | $(CMD_AWK) '{print $$3}' | $(CMD_SED) 's:go::g' | $(CMD_CUT) -d. -f1,2)
TAG_COMMIT := $(shell git rev-list --abbrev-commit --tags --max-count=1)
TAG := $(shell git describe --abbrev=0 --tags ${TAG_COMMIT} 2>/dev/null || true)
COMMIT := $(shell git rev-parse --short HEAD)
DATE := $(shell git log -1 --format=%cd --date=format:"%Y%m%d")
LAST_GIT_TAG := $(TAG:v%=%)-$(DATE)-$(COMMIT)

UNAME_M := $(shell uname -m)
UNAME_R := $(shell uname -r)

# envs
KERN_RELEASE ?= $(shell uname -r)
ARCH_UNAME := $(shell uname -m)
ARCH ?= $(ARCH_UNAME:aarch64=arm64)
linux_arch := $(ARCH:x86_64=x86)
# some different with tracee. Need to check for this
KERN_BLD_PATH := $(if $(KERN_HEADERS),$(KERN_HEADERS),/lib/modules/$(KERN_RELEASE)/build)
KERN_SRC_PATH := $(if $(KERN_HEADERS),$(KERN_HEADERS),$(if $(wildcard /lib/modules/$(KERN_RELEASE)/source),/lib/modules/$(KERN_RELEASE)/source,$(KERN_BLD_PATH)))

BPF_HEADERS := headers
INCLUDE_PATH := include
LIB_PATH := ../../libs
HADES_SRC := src/hades.c

# colors
INFO_COLOR = \033[34m[*]\033[0m
SUCC_COLOR = \033[32m[+]\033[0m
FAIL_COLOR = \033[31m[-]\033[0m
HIGHLIGHT_COLOR = \033[35mHades\033[0m

nocore: \
pre_show
@printf "$(INFO_COLOR) Compile driver from kernel headers\n"
$(MAKE) hades_ebpf_driver.bpf.o -s --no-print-directory

core: \
pre_show \
env_show
@printf "$(INFO_COLOR) Compile CO-RE driver\n"
$(MAKE) bpf-core -s --no-print-directory

.PHONY: pre_show
pre_show:
@echo "┌──────────────────────────────┐"
@printf "$(HIGHLIGHT_COLOR) eBPF Kernel Driver │\n"
@echo "│ based on Tracee/Elkeid │"
@echo "│ @chriskaliX │"
@echo "└──────────────────────────────┘"
@printf "$(INFO_COLOR) Start to build hades_ebpf_driver\n"
@printf "$(INFO_COLOR) Pre-check for compile tools exists\n"
$(CHECK_TOOLS_EXSITS)
@printf "$(SUCC_COLOR) Tools all exist\n"
@printf "$(INFO_COLOR) Pre-check for clang version\n"
@if [ $(CLANG_VERSION) -lt 12 ]; \
then echo "$(FAIL_COLOR) clang mininum version 12 is required" && exit 1;\
fi;
@printf "$(SUCC_COLOR) Clang version pass\n"
@printf "$(INFO_COLOR) Clean for the old driver...\n"
$(MAKE) clean -s --no-print-directory

# env print from ecapture
.PHONY: env_show
env_show:
@echo ---------------------------------------
@echo "Hades Makefile Environment:"
@echo ---------------------------------------
@echo "CLANG_VERSION $(CLANG_VERSION)"
@echo "GO_VERSION $(GO_VERSION)"
@echo ---------------------------------------
@echo "CMD_CLANG $(CMD_CLANG)"
@echo "CMD_GIT $(CMD_GIT)"
@echo "CMD_GO $(CMD_GO)"
@echo "CMD_INSTALL $(CMD_INSTALL)"
@echo "CMD_LLC $(CMD_LLC)"
@echo "CMD_MD5 $(CMD_MD5)"
@echo "CMD_PKGCONFIG $(CMD_PKGCONFIG)"
@echo "CMD_STRIP $(CMD_STRIP)"
@echo "VERSION $(VERSION)"
@echo "LAST_GIT_TAG $(LAST_GIT_TAG)"
@echo ---------------------------------------
@echo "UNAME_M $(UNAME_M)"
@echo "UNAME_R $(UNAME_R)"
@echo "ARCH $(ARCH)"
@echo ---------------------------------------
@echo "KERN_RELEASE $(KERN_RELEASE)"
@echo "KERN_BLD_PATH $(KERN_BLD_PATH)"
@echo "KERN_SRC_PATH $(KERN_SRC_PATH)"

# libbpf
# Build libbpf to get the common headers for both core and no-core
# some helpers, defs and macros
LIBBPF_CFLAGS = "-fPIC"
LIBBPF_LDLAGS =
LIBBPF_SRC = $(LIB_PATH)/libbpf/src
headers/libbpf/libbpf.a: \
$(LIBBPF_SRC) \
$(wildcard $(LIBBPF_SRC)/*.[ch]) \

CC="$(CMD_CLANG)" \
CFLAGS="$(LIBBPF_CFLAGS)" \
LD_FLAGS="$(LIBBPF_LDFLAGS)" \
$(MAKE) \
-C $(LIBBPF_SRC) \
BUILD_STATIC_ONLY=1 \
DESTDIR=$(abspath ./headers/libbpf/) \
OBJDIR=$(abspath ./headers/libbpf/obj) \
INCLUDEDIR= LIBDIR= UAPIDIR= prefix= libdir= \
install install_uapi_headers
install -m 0640 ./headers/libbpf/bpf/*.h ./headers/

# NOT CO-RE
# KBUILD_NAME: https://github.com/iovisor/bpftrace/pull/1352
hades_ebpf_driver.bpf.o: \
headers/libbpf/libbpf.a \
$(HADES_SRC)

$(CMD_CLANG) -S \
-D__BPF_TRACING__ \
-D__KERNEL__ \
-D__TARGET_ARCH_$(linux_arch) \
-DKBUILD_MODNAME=\"hades\" \
-include $(KERN_SRC_PATH)/include/linux/kconfig.h \
-I $(KERN_SRC_PATH)/arch/$(linux_arch)/include \
-I $(KERN_SRC_PATH)/arch/$(linux_arch)/include/uapi \
-I $(KERN_BLD_PATH)/arch/$(linux_arch)/include/generated \
-I $(KERN_BLD_PATH)/arch/$(linux_arch)/include/generated/uapi \
-I $(KERN_SRC_PATH)/include \
-I $(KERN_BLD_PATH)/include \
-I $(KERN_SRC_PATH)/include/uapi \
-I $(KERN_BLD_PATH)/include/generated \
-I $(KERN_BLD_PATH)/include/generated/uapi \
-I $(BPF_HEADERS)/libbpf \
-I $(BPF_HEADERS) \
-I $(INCLUDE_PATH) \
-I $(LIB_PATH)/bpfheaders/ \
-Wunused \
-Wall \
-Wno-frame-address \
-Wno-unused-value \
-Wno-unknown-warning-option \
-Wno-pragma-once-outside-header \
-Wno-pointer-sign \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-deprecated-declarations \
-Wno-compare-distinct-pointer-types \
-Wno-address-of-packed-member \
-fno-stack-protector \
-fno-jump-tables \
-fno-unwind-tables \
-fno-asynchronous-unwind-tables \
-xc \
-nostdinc \
-c $(HADES_SRC) \
-O2 -emit-llvm -c -g -o $(@:.o=.ll)
$(CMD_LLC) -march=bpf -filetype=obj -o $@ $(@:.o=.ll)
rm $(@:.o=.ll)

# CO-RE
# Since CO-RE needs the BTF embeded on the kernel. Portable can only be archieved in
# some lastest kernel version. But, thanks to libbpf and btfhub, we can make bpf prog
# CO-RE in lower kernel version since external raw BTF files is supported in libbpf
# and here is the commit:
# https://github.com/libbpf/libbpf/commit/4920031c8809696debf43f7b0c8f95ea24b8f61c
# It's a great idea and it's been done is Tracee v0.7.0
# But still, BTFhub is used for portable. Distribution like CentOS 7 based on kernel
# version 3.x get very limited eBPF features. For the HIDS programs like Tracee or
# Hades, it would be limited by eBPF features and it's nothing to do with CO-RE.
# Again, we need to know that the mininum kernel version of Hades is 4.18.
# And we use BTFhub to support CO-RE in some distribution that NOT support BTF.
# BTFhub helps us to backport CO-RE in some kernel versions.
.PHONY: bpf-core
bpf-core: hades_ebpf_driver.bpf.core.o
hades_ebpf_driver.bpf.core.o: \
$(HADES_SRC) \
headers/libbpf/libbpf.a

$(CMD_CLANG) \
-D__TARGET_ARCH_$(linux_arch) \
-D__BPF_TRACING__ \
-DCORE \
-I $(BPF_HEADERS)/libbpf \
-I $(BPF_HEADERS) \
-I $(INCLUDE_PATH) \
-I $(LIB_PATH)/core/ \
-I $(LIB_PATH)/bpfheaders/ \
-target bpf \
-O2 -g \
-march=bpf -mcpu=v2 \
-c $(HADES_SRC) \
-o $@

.PHONY:clean
clean:
rm -f hades_ebpf_driver.bpf.o
rm -f hades_ebpf_driver.bpf.core.o
Loading

0 comments on commit a867941

Please sign in to comment.