8000 Add initial CO:RE support by grantseltzer · Pull Request #759 · aquasecurity/tracee · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add initial CO:RE support #759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/pr-ebpf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ jobs:
fi
- name: Build
run: make all DOCKER=1
- name: Build CO:RE
run: make all DOCKER=1 CORE=y
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make the examples/scripts use consistent config values: either 1 or y

- name: Test
run: make test DOCKER=1
6 changes: 6 additions & 0 deletions docs/install/ebpf-compilation 8000 .md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ If using Docker, the following `docker run` options demonstrate mounting a pre-c
```bash
docker run ... -v /path/in/host/tracee.bpf.123.o:/path/in/container/tracee.bpf.o -e TRACEE_BPF_FILE=/path/in/container/tracee.bpf.o aquasec/tracee
```

# eBPF CO:RE Compilation

Tracee also can utilize CO:RE (Compile once, run everywhere) technology enabled by libbpf. With this enabled, you can compile the tracee bpf object file on one system, and run it on any kernel with BTF (BPF type format) enabled. To check if your kernel has BTF enabled, check for the `CONFIG_DEBUG_INFO_BTF` in your kernel config.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for the CONFIG_DEBUG_INFO_BTF in your kernel config.

can we write the command to do that?
can we make sure Tracee-eBPF's main does that and prints a nice error?


Compiling with CO:RE enabled is as simple as running `make CORE=y`. This will produce a bpf object file called `dist/tracee.bpf.core.{version}`. You can ship this object file with your tracee go binary and point to it by path using the `TRACEE_BPF_FILE` environment variable.
6 changes: 3 additions & 3 deletions tracee-ebpf/Dockerfile.builder
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM golang:1.16-buster as builder
RUN echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-9 main" >> /etc/apt/sources.list && apt-key adv --keyserver hkps://keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 && \
DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get install -y --no-install-recommends libelf-dev llvm-9 clang-9 && \
(for tool in "clang" "llc" "llvm-strip"; do path=$(which $tool-9) && ln -s $path ${path%-*}; done)
RUN echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-12 main" >> /etc/apt/sources.list && apt-key adv --keyserver hkps://keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 && \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update the docs to reflect that llvm 12 is now required

DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get install -y --no-install-recommends gawk libelf-dev llvm-12 clang-12 && \
(for tool in "clang" "llc" "llvm-strip"; do path=$(which $tool-12) && ln -s $path ${path%-*}; done)
WORKDIR /tracee
30 changes: 27 additions & 3 deletions tracee-ebpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ VERSION ?= $(if $(RELEASE_TAG),$(RELEASE_TAG),$(shell $(CMD_GIT) describe --tags
OUT_DIR ?= dist
GO_SRC := $(shell find . -type f -name '*.go')
OUT_BIN := $(OUT_DIR)/tracee-ebpf
BPF_SRC := tracee/tracee.bpf.c
BPF_SRC := tracee/tracee.bpf.c

ifndef CORE
OUT_BPF := $(OUT_DIR)/tracee.bpf.$(subst .,_,$(KERN_RELEASE)).$(subst .,_,$(VERSION)).o
else
OUT_BPF := $(OUT_DIR)/tracee.bpf.core.$(subst .,_,$(VERSION)).o
endif
BPF_HEADERS := 3rdparty/include
BPF_BUNDLE := $(OUT_DIR)/tracee.bpf.tar.gz
LIBBPF_SRC := 3rdparty/libbpf/src
Expand All @@ -32,6 +37,7 @@ DOCKER_BUILDER_KERN_BLD ?= $(if $(shell readlink $(KERN_BLD_PATH)),$(shell readl
DOCKER_BUILDER_KERN_SRC ?= $(if $(shell readlink $(KERN_SRC_PATH)),$(shell readlink $(KERN_SRC_PATH)),$(KERN_SRC_PATH))
# DOCKER_BUILDER_KERN_SRC_MNT is the kernel headers directory to mount into the docker builder container. DOCKER_BUILDER_KERN_SRC should usually be a descendent of this path.
DOCKER_BUILDER_KERN_SRC_MNT ?= $(dir $(DOCKER_BUILDER_KERN_SRC))
LINUX_VERSION_CODE := $(shell uname -r | awk '{split($$0,a,"."); split(a[3], b, "-"); print lshift(a[1], 16) + lshift(a[2],8) + b[1];}')

$(OUT_DIR):
mkdir -p $@
Expand All @@ -43,7 +49,7 @@ go_env := GOOS=linux GOARCH=$(ARCH:x86_64=amd64) CC=$(CMD_CLANG) CGO_CFLAGS="-I
ifndef DOCKER
$(OUT_BIN): $(LIBBPF_HEADERS) $(LIBBPF_OBJ) $(filter-out *_test.go,$(GO_SRC)) $(BPF_BUNDLE) | $(OUT_DIR)
$(go_env) go build -v -o $(OUT_BIN) \
-ldflags "-X main.version=$(VERSION)"
-ldflags "-X main.version=$(VERSION) -X main.bpf_core=$(CORE)"
else
$(OUT_BIN): $(DOCKER_BUILDER) | $(OUT_DIR)
$(call docker_builder_make,$@ VERSION=$(VERSION))
Expand Down Expand Up @@ -72,6 +78,7 @@ bpf: $(OUT_BPF)

linux_arch := $(ARCH:x86_64=x86)
ifndef DOCKER
ifndef CORE
$(OUT_DIR)/tracee.bpf.%.o: $(BPF_SRC) $(LIBBPF_HEADERS) | $(OUT_DIR) $(bpf_compile_tools)
@v=$$($(CMD_CLANG) --version); test $$(echo $${v#*version} | head -n1 | cut -d '.' -f1) -ge '9' || (echo 'required minimum clang version: 9' ; false)
$(CMD_CLANG) -S \
Expand Down Expand Up @@ -111,6 +118,23 @@ $(OUT_DIR)/tracee.bpf.%.o: $(BPF_SRC) $(LIBBPF_HEADERS) | $(OUT_DIR) $(bpf_compi
-$(CMD_LLVM_STRIP) -g $@
rm $(@:.o=.ll)
else
#docker no, CO:RE yes
$(OUT_DIR)/tracee.bpf.core.%.o: $(BPF_SRC) $(LIBBPF_HEADERS) $(CMD_CLANG)
$(CMD_CLANG) \
-I $(LIBBPF_HEADERS)/bpf \
-I $(BPF_HEADERS) \
-I tracee/$(ARCH) \
-DCORE \
-D__TARGET_ARCH_$(linux_arch) \
-D__BPF_TRACING__ \
-D__VM_LINUX_H__ \
-D__KERNEL__ \
-DLINUX_VERSION_CODE=$(LINUX_VERSION_CODE) \
-target bpf \
-O2 -c -g -o $@ $<
endif
else
#docker yes
$(OUT_BPF): $(DOCKER_BUILDER) | $(OUT_DIR)
$(call docker_builder_make,$@)
endif
Expand Down Expand Up @@ -140,7 +164,7 @@ define docker_builder_make
-v $(abspath $(DOCKER_BUILDER_KERN_SRC_MNT)):$(DOCKER_BUILDER_KERN_SRC_MNT) \
-v $(abspath .):/tracee/tracee-ebpf \
-w /tracee/tracee-ebpf \
--entrypoint make $(DOCKER_BUILDER) KERN_BLD_PATH=$(DOCKER_BUILDER_KERN_BLD) KERN_SRC_PATH=$(DOCKER_BUILDER_KERN_SRC) $(1)
--entrypoint make $(DOCKER_BUILDER) KERN_BLD_PATH=$(DOCKER_BUILDER_KERN_BLD) CORE="$(CORE)" KERN_SRC_PATH=$(DOCKER_BUILDER_KERN_SRC) $(1)
endef

.PHONY: mostlyclean
Expand Down
6 changes: 6 additions & 0 deletions tracee-ebpf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var buildPolicy string
//go:embed "dist/tracee.bpf/*"
var bpfBundleInjected embed.FS
var version string
var bpf_core string

func main() {
app := &cli.App{
Expand Down Expand Up @@ -1028,7 +1029,12 @@ func getBPFObject() (string, error) {
}
return bpfPath, nil
}

bpfObjFileName := fmt.Sprintf("tracee.bpf.%s.%s.o", strings.ReplaceAll(tracee.UnameRelease(), ".", "_"), strings.ReplaceAll(version, ".", "_"))
if bpf_core != "" {
bpfObjFileName = fmt.Sprintf("tracee.bpf.core.%s.o", strings.ReplaceAll(version, ".", "_"))
}

exePath, err := os.Executable()
if err != nil {
return "", err
Expand Down
142 changes: 142 additions & 0 deletions tracee-ebpf/tracee/co_re_missing_definitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* The purpose of this file is to define macros
* that tracee.bpf.c relies on which are defined
* in linux kernel headers but not in vmlinux.h
*
* vmlinux.h is generated from BTF information
* in vmlinux but this does not include macros.
*
*/

#ifndef __TRACEE_MISSING_MACROS_H__
#define __TRACEE_MISSING_MACROS_H__

#define ULLONG_MAX (~0ULL)

#define inet_daddr sk.__sk_common.skc_daddr
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
#define inet_dport sk.__sk_common.skc_dport
#define inet_num sk.__sk_common.skc_num

#define sk_node __sk_common.skc_node
#define sk_nulls_node __sk_common.skc_nulls_node
#define sk_refcnt __sk_common.skc_refcnt
#define sk_tx_queue_mapping __sk_common.skc_tx_queue_mapping

#define sk_dontcopy_begin __sk_common.skc_dontcopy_begin
#define sk_dontcopy_end __sk_common.skc_dontcopy_end
#define sk_hash __sk_common.skc_hash
#define sk_portpair __sk_common.skc_portpair
#define sk_num __sk_common.skc_num
#define sk_dport __sk_common.skc_dport
#define sk_addrpair __sk_common.skc_addrpair
#define sk_daddr __sk_common.skc_daddr
#define sk_rcv_saddr __sk_common.skc_rcv_saddr
#define sk_family __sk_common.skc_family
#define sk_state __sk_common.skc_state
#define sk_reuse __sk_common.skc_reuse
#define sk_reuseport __sk_common.skc_reuseport
#define sk_ipv6only __sk_common.skc_ipv6only
#define sk_net_refcnt __sk_common.skc_net_refcnt
#define sk_bound_dev_if __sk_common.skc_bound_dev_if
#define sk_bind_node __sk_common.skc_bind_node
#define sk_prot __sk_common.skc_prot
#define sk_net __sk_common.skc_net
#define sk_v6_daddr __sk_common.skc_v6_daddr
#define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr
#define sk_cookie __sk_common.skc_cookie
#define sk_incoming_cpu __sk_common.skc_incoming_cpu
#define sk_flags __sk_common.skc_flags
#define sk_rxhash __sk_common.skc_rxhash

#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/

#define TASK_COMM_LEN 16

#define THREAD_SIZE_ORDER 1

#define THREAD_SIZE (2*PAGE_SIZE)

#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))

#define _AC(X,Y) X

#ifdef CONFIG_X86_32
# ifdef CONFIG_VM86
# define TOP_OF_KERNEL_STACK_PADDING 16
# else
# define TOP_OF_KERNEL_STACK_PADDING 8
# endif
#else
# define TOP_OF_KERNEL_STACK_PADDING 0
#endif

/* Supported address families. */
#define AF_UNSPEC 0
#define AF_UNIX 1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX */
#define AF_APPLETALK 5 /* AppleTalk DDP */
#define AF_NETROM 6 /* Amateur Radio NET/ROM */
#define AF_BRIDGE 7 /* Multiprotocol bridge */
#define AF_ATMPVC 8 /* ATM PVCs */
#define AF_X25 9 /* Reserved for X.25 project */
#define AF_INET6 10 /* IP version 6 */
#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
#define AF_DECnet 12 /* Reserved for DECnet project */
#define AF_NETBEUI 13 /* Reserved for 802.2LLC project */
#define AF_SECURITY 14 /* Security callback pseudo AF */
#define AF_KEY 15 /* PF_KEY key management API */
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET 17 /* Packet family */
#define AF_ASH 18 /* Ash */
#define AF_ECONET 19 /* Acorn Econet */
#define AF_ATMSVC 20 /* ATM SVCs */
#define AF_RDS 21 /* RDS sockets */
#define AF_SNA 22 /* Linux SNA Project (nutters!) */
#define AF_IRDA 23 /* IRDA sockets */
#define AF_PPPOX 24 /* PPPoX sockets */
#define AF_WANPIPE 25 /* Wanpipe API Sockets */
#define AF_LLC 26 /* Linux LLC */
#define AF_IB 27 /* Native InfiniBand address */
#define AF_MPLS 28 /* MPLS */
#define AF_CAN 29 /* Controller Area Network */
#define AF_TIPC 30 /* TIPC sockets */
#define AF_BLUETOOTH 31 /* Bluetooth sockets */
#define AF_IUCV 32 /* IUCV sockets */
#define AF_RXRPC 33 /* RxRPC sockets */
#define AF_ISDN 34 /* mISDN sockets */
#define AF_PHONET 35 /* Phonet sockets */
#define AF_IEEE802154 36 /* IEEE802154 sockets */
#define AF_CAIF 37 /* CAIF sockets */
#define AF_ALG 38 /* Algorithm sockets */
#define AF_NFC 39 /* NFC sockets */
#define AF_VSOCK 40 /* vSockets */
#define AF_KCM 41 /* Kernel Connection Multiplexor */
#define AF_QIPCRTR 42 /* Qualcomm IPC Router */
#define AF_SMC 43 /* smc sockets: reserve number for PF_SMC protocol family that reuses AF_INET address family */

#define VM_NONE 0x00000000
#define VM_READ 0x00000001
#define VM_WRITE 0x00000002
#define VM_EXEC 0x00000004
#define VM_SHARED 0x00000008

#define __user

static inline bool ipv6_addr_any(const struct in6_addr *a)
{
return (a->in6_u.u6_addr32[0] | a->in6_u.u6_addr32[1] | a->in6_u.u6_addr32[2] | a->in6_u.u6_addr32[3]) == 0;
}

static inline struct inet_sock *inet_sk(const struct sock *sk)
{
return (struct inet_sock *)sk;
}

#endif
Loading
0