From 3c30919c0d998564c7bb82f21d9344e6fa865685 Mon Sep 17 00:00:00 2001 From: Huang Huang Date: Fri, 7 Oct 2022 22:20:01 +0800 Subject: [PATCH] Move embedded C code to a header file (#257) * Move embedded C code to a header file (Handle #250) * add fmt-check and fmt-fix make targets for running clang-format --- .github/workflows/pr.yaml | 11 +++ Makefile | 33 +++++++++ libbpfgo.go | 147 +------------------------------------- libbpfgo.h | 138 +++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 146 deletions(-) create mode 100644 libbpfgo.h diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 973b8b39..747f470e 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -6,6 +6,17 @@ on: - main workflow_call: jobs: + analyze-code: + name: Analyze Code + runs-on: ubuntu-22.04 + steps: + - name: Checkout Code + uses: actions/checkout@v2 + - name: Install Dependencies + uses: ./.github/actions/build-dependencies + - name: Check Code Style + run: | + make fmt-check unit-tests: name: Unit Tests runs-on: ubuntu-22.04 diff --git a/Makefile b/Makefile index e22f62c3..1942dd29 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ + +.ONESHELL: +SHELL = /bin/bash + BASEDIR = $(abspath ./) OUTPUT = ./output @@ -8,6 +12,7 @@ CC = gcc CLANG = clang GO = go VAGRANT = vagrant +CLANG_FMT = clang-format HOSTOS = $(shell uname) ARCH ?= $(shell uname -m | sed 's/x86_64/amd64/g; s/aarch64/arm64/g') @@ -205,6 +210,34 @@ vagrant-ssh: .vagrant-ssh HOSTOS=$(HOSTOS) \ $(VAGRANT) $* +# fmt-check + +fmt-check: + @errors=0 + echo "Checking C and eBPF files and headers formatting..." + $(CLANG_FMT) --dry-run -i ./libbpfgo.h > /tmp/check-c-fmt 2>&1 + clangfmtamount=$$(cat /tmp/check-c-fmt | wc -l) + if [[ $$clangfmtamount -ne 0 ]]; then + head -n30 /tmp/check-c-fmt + errors=1 + fi + rm -f /tmp/check-c-fmt +# + if [[ $$errors -ne 0 ]]; then + echo + echo "Please fix formatting errors above!" + echo "Use: $(MAKE) fmt-fix target". + echo + exit 1 + fi + + +# fmt-fix + +fmt-fix: + @echo "Fixing C and eBPF files and headers formatting..." + $(CLANG_FMT) -i --verbose ./libbpfgo.h + # output $(OUTPUT): diff --git a/libbpfgo.go b/libbpfgo.go index 58bf0d6e..d7061578 100644 --- a/libbpfgo.go +++ b/libbpfgo.go @@ -2,152 +2,7 @@ package libbpfgo /* #cgo LDFLAGS: -lelf -lz - -#include -#include -#include -#include -#include -#include - -#include -#include - - -int libbpf_print_fn(enum libbpf_print_level level, - const char *format, - va_list args) -{ - if (level != LIBBPF_WARN) - return 0; - - // NOTE: va_list args is managed in libbpf caller - // however, these copies must be matched with va_end() in this function - va_list exclusivity_check, cgroup_check; - va_copy(exclusivity_check, args); - va_copy(cgroup_check, args); - - // BUG: https://github.com/aquasecurity/tracee/issues/1676 - - char *str = va_arg(exclusivity_check, char *); - if (strstr(str, "Exclusivity flag on") != NULL) { - va_end(exclusivity_check); - return 0; - } - va_end(exclusivity_check); - - // AttachCgroupLegacy() will first try AttachCgroup() and it - // might fail. This is not an error and is the best way of - // probing for eBPF cgroup attachment link existence. - - str = va_arg(cgroup_check, char *); - if (strstr(str, "cgroup") != NULL) { - str = va_arg(cgroup_check, char *); - if (strstr(str, "Invalid argument") != NULL) { - va_end(cgroup_check); - return 0; - } - } - va_end(cgroup_check); - - return vfprintf(stderr, format, args); -} - -void set_print_fn() -{ - libbpf_set_print(libbpf_print_fn); -} - -extern void perfCallback(void *ctx, int cpu, void *data, __u32 size); -extern void perfLostCallback(void *ctx, int cpu, __u64 cnt); -extern int ringbufferCallback(void *ctx, void *data, size_t size); - -struct ring_buffer * init_ring_buf(int map_fd, uintptr_t ctx) -{ - struct ring_buffer *rb = NULL; - - rb = ring_buffer__new(map_fd, ringbufferCallback, (void*)ctx, NULL); - if (!rb) { - int saved_errno = errno; - fprintf(stderr, "Failed to initialize ring buffer: %s\n", strerror(errno)); - errno = saved_errno; - return NULL; - } - - return rb; -} - -struct perf_buffer * init_perf_buf(int map_fd, int page_cnt, uintptr_t ctx) -{ - struct perf_buffer_opts pb_opts = {}; - struct perf_buffer *pb = NULL; - - pb_opts.sz = sizeof(struct perf_buffer_opts); - - pb = perf_buffer__new(map_fd, page_cnt, perfCallback, perfLostCallback, - (void *) ctx, &pb_opts); - if (!pb) { - int saved_errno = errno; - fprintf(stderr, "Failed to initialize perf buffer: %s\n", strerror(errno)); - errno = saved_errno; - return NULL; - } - - return pb; -} - -int bpf_prog_attach_cgroup_legacy( - int prog_fd, // eBPF program file descriptor - int target_fd, // cgroup directory file descriptor - int type) // BPF_CGROUP_INET_{INGRESS,EGRESS}, ... -{ - union bpf_attr attr; - memset(&attr, 0, sizeof(attr)); - attr.target_fd = target_fd; - attr.attach_bpf_fd = prog_fd; - attr.attach_type = type; - attr.attach_flags = BPF_F_ALLOW_MULTI; // or BPF_F_ALLOW_OVERRIDE - - return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr)); -} - -int bpf_prog_detach_cgroup_legacy( - int prog_fd, // eBPF program file descriptor - int target_fd, // cgroup directory file descriptor - int type) // BPF_CGROUP_INET_{INGRESS,EGRESS}, ... -{ - union bpf_attr attr; - memset(&attr, 0, sizeof(attr)); - attr.target_fd = target_fd; - attr.attach_bpf_fd = prog_fd; - attr.attach_type = type; - - return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr)); -} - -struct bpf_object * open_bpf_object( - char* btf_file_path, - char* kconfig_path, - char* bpf_obj_name, - const void* obj_buf, - size_t obj_buf_size) -{ - struct bpf_object_open_opts opts = {}; - opts.btf_custom_path = btf_file_path; - opts.kconfig = kconfig_path; - opts.object_name = bpf_obj_name; - opts.sz = sizeof(opts); - - struct bpf_object *obj = bpf_object__open_mem(obj_buf, obj_buf_size, &opts); - if (obj == NULL) { - int saved_errno = errno; - fprintf(stderr, "Failed to open bpf object: %s\n", strerror(errno)); - errno = saved_errno; - return NULL; - } - - return obj; -} +#include "libbpfgo.h" */ import "C" diff --git a/libbpfgo.h b/libbpfgo.h new file mode 100644 index 00000000..6b9abd27 --- /dev/null +++ b/libbpfgo.h @@ -0,0 +1,138 @@ +#ifndef __LIBBPF_GO_H__ +#define __LIBBPF_GO_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include + +int libbpf_print_fn(enum libbpf_print_level level, const char *format, + va_list args) { + if (level != LIBBPF_WARN) + return 0; + + // NOTE: va_list args is managed in libbpf caller + // however, these copies must be matched with va_end() in this function + va_list exclusivity_check, cgroup_check; + va_copy(exclusivity_check, args); + va_copy(cgroup_check, args); + + // BUG: https://github.com/aquasecurity/tracee/issues/1676 + + char *str = va_arg(exclusivity_check, char *); + if (strstr(str, "Exclusivity flag on") != NULL) { + va_end(exclusivity_check); + return 0; + } + va_end(exclusivity_check); + + // AttachCgroupLegacy() will first try AttachCgroup() and it + // might fail. This is not an error and is the best way of + // probing for eBPF cgroup attachment link existence. + + str = va_arg(cgroup_check, char *); + if (strstr(str, "cgroup") != NULL) { + str = va_arg(cgroup_check, char *); + if (strstr(str, "Invalid argument") != NULL) { + va_end(cgroup_check); + return 0; + } + } + va_end(cgroup_check); + + return vfprintf(stderr, format, args); +} + +void set_print_fn() { libbpf_set_print(libbpf_print_fn); } + +extern void perfCallback(void *ctx, int cpu, void *data, __u32 size); +extern void perfLostCallback(void *ctx, int cpu, __u64 cnt); +extern int ringbufferCallback(void *ctx, void *data, size_t size); + +struct ring_buffer *init_ring_buf(int map_fd, uintptr_t ctx) { + struct ring_buffer *rb = NULL; + + rb = ring_buffer__new(map_fd, ringbufferCallback, (void *)ctx, NULL); + if (!rb) { + int saved_errno = errno; + fprintf(stderr, "Failed to initialize ring buffer: %s\n", strerror(errno)); + errno = saved_errno; + return NULL; + } + + return rb; +} + +struct perf_buffer *init_perf_buf(int map_fd, int page_cnt, uintptr_t ctx) { + struct perf_buffer_opts pb_opts = {}; + struct perf_buffer *pb = NULL; + + pb_opts.sz = sizeof(struct perf_buffer_opts); + + pb = perf_buffer__new(map_fd, page_cnt, perfCallback, perfLostCallback, + (void *)ctx, &pb_opts); + if (!pb) { + int saved_errno = errno; + fprintf(stderr, "Failed to initialize perf buffer: %s\n", strerror(errno)); + errno = saved_errno; + return NULL; + } + + return pb; +} + +int bpf_prog_attach_cgroup_legacy( + int prog_fd, // eBPF program file descriptor + int target_fd, // cgroup directory file descriptor + int type) // BPF_CGROUP_INET_{INGRESS,EGRESS}, ... +{ + union bpf_attr attr; + memset(&attr, 0, sizeof(attr)); + attr.target_fd = target_fd; + attr.attach_bpf_fd = prog_fd; + attr.attach_type = type; + attr.attach_flags = BPF_F_ALLOW_MULTI; // or BPF_F_ALLOW_OVERRIDE + + return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr)); +} + +int bpf_prog_detach_cgroup_legacy( + int prog_fd, // eBPF program file descriptor + int target_fd, // cgroup directory file descriptor + int type) // BPF_CGROUP_INET_{INGRESS,EGRESS}, ... +{ + union bpf_attr attr; + memset(&attr, 0, sizeof(attr)); + attr.target_fd = target_fd; + attr.attach_bpf_fd = prog_fd; + attr.attach_type = type; + + return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr)); +} + +struct bpf_object *open_bpf_object(char *btf_file_path, char *kconfig_path, + char *bpf_obj_name, const void *obj_buf, + size_t obj_buf_size) { + struct bpf_object_open_opts opts = {}; + opts.btf_custom_path = btf_file_path; + opts.kconfig = kconfig_path; + opts.object_name = bpf_obj_name; + opts.sz = sizeof(opts); + + struct bpf_object *obj = bpf_object__open_mem(obj_buf, obj_buf_size, &opts); + if (obj == NULL) { + int saved_errno = errno; + fprintf(stderr, "Failed to open bpf object: %s\n", strerror(errno)); + errno = saved_errno; + return NULL; + } + + return obj; +} + +#endif