Skip to content

Commit

Permalink
Move embedded C code to a header file (#257)
Browse files Browse the repository at this point in the history
* Move embedded C code to a header file (Handle #250)

* add fmt-check and fmt-fix make targets for running clang-format
  • Loading branch information
mozillazg authored Oct 7, 2022
1 parent 9eb6002 commit 3c30919
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 146 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@

.ONESHELL:
SHELL = /bin/bash

BASEDIR = $(abspath ./)

OUTPUT = ./output
Expand All @@ -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')
Expand Down Expand Up @@ -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):
Expand Down
147 changes: 1 addition & 146 deletions libbpfgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,152 +2,7 @@ package libbpfgo

/*
#cgo LDFLAGS: -lelf -lz
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
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"

Expand Down
138 changes: 138 additions & 0 deletions libbpfgo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#ifndef __LIBBPF_GO_H__
#define __LIBBPF_GO_H__

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <unistd.h>

#include <bpf/bpf.h>
#include <bpf/libbpf.h>

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

0 comments on commit 3c30919

Please sign in to comment.