Skip to content

Commit

Permalink
daemon: add trace for close
Browse files Browse the repository at this point in the history
  • Loading branch information
Littlefisher619 committed Oct 20, 2023
1 parent c7876f7 commit 8a0375f
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 146 deletions.
6 changes: 3 additions & 3 deletions runtime/daemon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ add_bpf_skel_generating_target(bpftime_daemon_ebpf_skel ${CMAKE_CURRENT_BINARY_D

add_dependencies(bpftime_daemon_ebpf_skel bpftime_daemon_ebpf_target)

add_executable(bpftime_daemon bpf-mocker.cpp handle_bpf_event.cpp)
add_dependencies(bpftime_daemon bpftime_daemon_ebpf_skel libbpf)
add_executable(bpftime_daemon main.cpp bpf-mocker.cpp handle_bpf_event.cpp)
add_dependencies(bpftime_daemon bpftime_daemon_ebpf_skel libbpf spdlog::spdlog)

target_include_directories(bpftime_daemon PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${LIBBPF_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(bpftime_daemon PRIVATE ${LIBBPF_LIBRARIES} elf z)
target_link_libraries(bpftime_daemon PRIVATE ${LIBBPF_LIBRARIES} elf z spdlog::spdlog)
set_property(TARGET bpftime_daemon PROPERTY CXX_STANDARD 20)
5 changes: 5 additions & 0 deletions runtime/daemon/bpf-mocker-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

enum event_type {
SYS_OPEN,
SYS_CLOSE,
SYS_BPF,
SYS_PERF_EVENT_OPEN,
BPF_PROG_LOAD_EVENT,
Expand Down Expand Up @@ -51,6 +52,10 @@ struct event {
char prog_name[BPF_OBJ_NAME_LEN];
unsigned int insns[MAX_INSN_SIZE];
} bpf_loaded_prog;

struct {
int fd;
} close_data;
};
};

Expand Down
57 changes: 57 additions & 0 deletions runtime/daemon/bpf-mocker.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct open_args_t {
int flags;
};

// track open syscall args
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
Expand Down Expand Up @@ -218,6 +219,30 @@ int tracepoint__syscalls__sys_enter_bpf(struct trace_event_raw_sys_enter *ctx)
return 0;
}

static int process_bpf_syscall_exit(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size, int ret,
struct trace_event_raw_sys_exit *ctx)
{
if (!attr || size < sizeof(*attr)) {
return 0;
}

switch (cmd) {
case BPF_PROG_LOAD:
set_bpf_fd_if_positive(ret);
break;
case BPF_MAP_CREATE:
set_bpf_fd_if_positive(ret);
break;
case BPF_LINK_CREATE:
set_bpf_fd_if_positive(ret);
break;
default:
break;
}
return 0;
}

SEC("tracepoint/syscalls/sys_exit_bpf")
int tracepoint__syscalls__sys_exit_bpf(struct trace_event_raw_sys_exit *ctx)
{
Expand All @@ -244,6 +269,10 @@ int tracepoint__syscalls__sys_exit_bpf(struct trace_event_raw_sys_exit *ctx)
event->bpf_data.bpf_cmd = ap->cmd;
event->bpf_data.ret = ctx->ret;

process_bpf_syscall_exit(event->bpf_data.bpf_cmd, &event->bpf_data.attr,
event->bpf_data.attr_size, event->bpf_data.ret,
ctx);

/* emit event */
bpf_ringbuf_submit(event, 0);
cleanup:
Expand Down Expand Up @@ -299,6 +328,32 @@ int tracepoint__syscalls__sys_enter_perf_event_open(
return 0;
}

SEC("tracepoint/syscalls/sys_enter_close")
int tracepoint__syscalls__sys_enter_close(struct trace_event_raw_sys_enter *ctx)
{
struct event *event = NULL;

if (!filter_target()) {
return 0;
}
int fd = (int)ctx->args[0];
if (!is_bpf_fd(fd)) {
return 0;
}
/* event data */
event = fill_basic_event_info();
if (!event) {
return 0;
}
event->type = SYS_CLOSE;

event->close_data.fd = fd;
/* emit event */
bpf_ringbuf_submit(event, 0);

return 0;
}

SEC("tracepoint/syscalls/sys_exit_perf_event_open")
int tracepoint__syscalls__sys_exit_perf_event_open(
struct trace_event_raw_sys_exit *ctx)
Expand All @@ -314,6 +369,8 @@ int tracepoint__syscalls__sys_exit_perf_event_open(
ap = bpf_map_lookup_elem(&perf_event_open_param_start, &pid);
if (!ap)
return 0; /* missed entry */

set_bpf_fd_if_positive(ctx->ret);

/* event data */
event = fill_basic_event_info();
Expand Down
109 changes: 15 additions & 94 deletions runtime/daemon/bpf-mocker.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2019 Facebook
// Copyright (c) 2020 Netflix
//
// Based on bpf_mocker(8) from BCC by Brendan Gregg and others.
// 14-Feb-2020 Brendan Gregg Created this.
// Description: bpf-mocker daemon
#include <argp.h>
#include <signal.h>
#include <stdio.h>
Expand All @@ -19,89 +14,20 @@
#include "bpf-mocker.skel.h"
#include "daemon_config.hpp"
#include "handle_bpf_event.hpp"

/* Tune the buffer size and wakeup rate. These settings cope with roughly
* 50k opens/sec.
*/
#define PERF_BUFFER_PAGES 64
#define PERF_BUFFER_TIME_MS 10

/* Set the poll timeout when no events occur. This can affect -d accuracy. */
#define PERF_POLL_TIMEOUT_MS 100
#include "daemon.hpp"

#define NSEC_PER_SEC 1000000000ULL

using namespace bpftime;

static volatile sig_atomic_t exiting = 0;

static struct env env = { .uid = INVALID_UID };
static bool verbose = false;
static bpf_event_handler handler({});

const char *argp_program_version = "bpftime-daemon 0.1";
const char *argp_program_bug_address = "https://github.com/eunomia-bpf/bpftime";
const char argp_program_doc[] = "Trace and modify bpf syscalls\n";

static const struct argp_option opts[] = {
{ "pid", 'p', "PID", 0, "Process ID to trace" },
{ "uid", 'u', "UID", 0, "User ID to trace" },
{ "open", 'o', "OPEN", 0, "Show open events" },
{ "verbose", 'v', NULL, 0, "Verbose debug output" },
{ "failed", 'x', NULL, 0, "Failed opens only" },
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state)
{
static int pos_args;
long int pid, uid;

switch (key) {
case 'v':
env.verbose = true;
break;
case 'x':
env.failed = true;
break;
case 'o':
env.show_open = true;
break;
case 'p':
errno = 0;
pid = strtol(arg, NULL, 10);
if (errno || pid <= 0) {
fprintf(stderr, "Invalid PID: %s\n", arg);
argp_usage(state);
}
env.pid = pid;
break;
case 'u':
errno = 0;
uid = strtol(arg, NULL, 10);
if (errno || uid < 0 || uid >= INVALID_UID) {
fprintf(stderr, "Invalid UID %s\n", arg);
argp_usage(state);
}
env.uid = uid;
break;
case ARGP_KEY_ARG:
if (pos_args++) {
fprintf(stderr,
"Unrecognized positional argument: %s\n", arg);
argp_usage(state);
}
errno = 0;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format,
va_list args)
{
if (level == LIBBPF_DEBUG && !env.verbose)
if (level == LIBBPF_DEBUG && !verbose)
return 0;
return vfprintf(stderr, format, args);
}
Expand All @@ -124,25 +50,25 @@ void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu);
}

int main(int argc, char **argv)
int bpftime::start_daemon(struct env env)
{
LIBBPF_OPTS(bpf_object_open_opts, open_opts);
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
};
struct ring_buffer *rb = NULL;
struct bpf_mocker_bpf *obj = NULL;
int err;

libbpf_set_print(libbpf_print_fn);
err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
if (err)
return err;

// update handler config
handler = bpf_event_handler(env);
verbose = env.verbose;

if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "can't set signal handler: %s\n",
strerror(errno));
err = 1;
goto cleanup;
}

obj = bpf_mocker_bpf__open();
if (!obj) {
Expand All @@ -153,6 +79,8 @@ int main(int argc, char **argv)
/* initialize global data (filtering options) */
obj->rodata->target_pid = env.pid;
obj->rodata->disable_modify = true;
obj->rodata->uprobe_perf_type = determine_uprobe_perf_type();
obj->rodata->kprobe_perf_type = determine_kprobe_perf_type();

err = bpf_mocker_bpf__load(obj);
if (err) {
Expand All @@ -175,13 +103,6 @@ int main(int argc, char **argv)
goto cleanup;
}

if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "can't set signal handler: %s\n",
strerror(errno));
err = 1;
goto cleanup;
}

/* main: poll */
while (!exiting) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
Expand Down
41 changes: 41 additions & 0 deletions runtime/daemon/bpf-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,52 @@ const volatile int current_pid = 0;
// disable modify bpf program
const volatile bool disable_modify = 0;

const volatile int uprobe_perf_type = 0;
const volatile int kprobe_perf_type = 0;

// print event to userspace
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

// pid & fd for all bpf related fds
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
__type(key, u64);
__type(value, u64);
} bpf_fd_map SEC(".maps");

#define PID_MASK_FOR_PFD 0xffffffff00000000
#define FD_MASK_FOR_PFD 0x00000000ffffffff
#define MAKE_PFD(pid, fd) (((u64)pid << 32) | fd)

static __always_inline bool is_bpf_fd(u32 fd) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 key = MAKE_PFD(pid, fd);
u64 *pfd = bpf_map_lookup_elem(&bpf_fd_map, &key);
if (!pfd) {
return false;
}
return true;
}

static __always_inline void set_bpf_fd_if_positive(u32 fd) {
if (fd < 0) {
return;
}
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 key = MAKE_PFD(pid, fd);
bpf_map_update_elem(&bpf_fd_map, &key, &key, 0);
}

static __always_inline void clear_bpf_fd(int fd) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 key = MAKE_PFD(pid, fd);
bpf_map_delete_elem(&bpf_fd_map, &key);
}

static __always_inline bool filter_target(void)
{
u64 pid = bpf_get_current_pid_tgid() >> 32;
Expand Down
11 changes: 11 additions & 0 deletions runtime/daemon/daemon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef BPFTIME_DAEMON_HPP
#define BPFTIME_DAEMON_HPP

#include "daemon_config.hpp"

namespace bpftime
{
int start_daemon(struct env env);
} // namespace bpftime

#endif // BPFTIME_DAEMON_HPP
Loading

0 comments on commit 8a0375f

Please sign in to comment.