this repo has no description

Initial commit

Patrick Ferris 30dcc2f4

+4
.gitignore
···
···
+
_build
+
vmlinux.h
+
*.o
+
arch
+1
.ocamlformat
···
···
+
version=0.27.0
+4
README.md
···
···
+
opentrace
+
---------
+
+
Tracing open-like syscalls using eBPF via OCaml.
+26
dune
···
···
+
(executable
+
(name opentrace)
+
(libraries unix libbpf libbpf_maps))
+
+
(rule
+
(mode
+
(promote (until-clean)))
+
(targets opentrace.bpf.o)
+
(deps arch opentrace.bpf.c)
+
(action
+
(system
+
"NIX_HARDENING_ENABLE=\"\" clang -g -O2 -target bpf -I/usr/include/%{architecture}-linux-gnu/ -c opentrace.bpf.c -D__TARGET_ARCH_%{read:arch}")))
+
+
(rule
+
(mode
+
(promote (until-clean)))
+
(targets vmlinux.h arch)
+
(action
+
(progn
+
(with-stdout-to
+
vmlinux.h
+
(run bpftool btf dump file /sys/kernel/btf/vmlinux format c))
+
(with-stdout-to
+
arch
+
(bash
+
"uname -m | sed 's/x86_64/x86/' | sed 's/arm.*/arm/' | sed 's/aarch64/arm64/' | sed 's/ppc64le/powerpc/' | sed 's/mips.*/mips/' | sed 's/riscv64/riscv/' | sed 's/loongarch64/loongarch/'")))))
+3
dune-project
···
···
+
(lang dune 3.14)
+
+
(name opentrace)
+49
opentrace.bpf.c
···
···
+
#include "vmlinux.h"
+
#include <bpf/bpf_helpers.h>
+
+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
+
+
const volatile int pid_target = 0;
+
+
struct {
+
__uint(type, BPF_MAP_TYPE_RINGBUF);
+
__uint(max_entries, 256 * 1024);
+
} rb SEC(".maps");
+
+
#define FILE_NAME_LEN 1024
+
+
// An open event
+
struct open_event
+
{
+
uint32_t e_pid;
+
int e_flags;
+
uint32_t e_mode;
+
char e_filename[FILE_NAME_LEN];
+
};
+
+
SEC("tracepoint/syscalls/sys_enter_openat")
+
int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx)
+
{
+
u64 id = bpf_get_current_pid_tgid();
+
u32 pid = id >> 32;
+
+
char filename[FILE_NAME_LEN];
+
struct open_event *oet;
+
+
oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0);
+
if (!oet)
+
return 0;
+
+
if (pid_target && pid_target != pid)
+
return false;
+
+
// Fill the open event
+
oet->e_pid = bpf_get_current_pid_tgid();
+
oet->e_flags = (int)ctx->args[2];
+
oet->e_mode = (__u32)ctx->args[3];
+
bpf_probe_read(oet->e_filename, sizeof(filename), (char *) ctx->args[1]);
+
+
bpf_ringbuf_submit(oet, 0);
+
return 0;
+
}
+
+65
opentrace.ml
···
···
+
open Libbpf
+
open Libbpf_maps
+
+
let obj_path = "opentrace.bpf.o"
+
let program_names = [ "tracepoint__syscalls__sys_enter_openat" ]
+
+
module Open_event = struct
+
open Ctypes
+
+
type t
+
+
let t : t structure typ = Ctypes.structure "event"
+
let ( -: ) ty label = Ctypes.field t label ty
+
let pid = int -: "e_pid"
+
let flags = int -: "e_flags"
+
let mode = int -: "e_mode"
+
let filename = array 256 char -: "e_filename"
+
let () = seal t
+
+
let char_array_as_string a =
+
let len = CArray.length a in
+
let b = Buffer.create len in
+
try
+
for i = 0 to len - 1 do
+
let c = CArray.get a i in
+
if c = '\x00' then raise Exit else Buffer.add_char b c
+
done;
+
Buffer.contents b
+
with Exit -> Buffer.contents b
+
+
let get_pid s = getf s pid
+
let get_flags s = getf s flags
+
let get_mode s = getf s mode
+
let get_fname s = getf s filename |> char_array_as_string
+
end
+
+
let () =
+
let bpf_callback obj _links =
+
(* Set signal handlers *)
+
let exitting = ref true in
+
let sig_handler = Sys.Signal_handle (fun _ -> exitting := false) in
+
Sys.(set_signal sigint sig_handler);
+
Sys.(set_signal sigterm sig_handler);
+
+
(* Print header *)
+
Format.printf "pid,flags,mode,filename\n";
+
+
let map = Libbpf.bpf_object_find_map_by_name obj "rb" in
+
let callback : RingBuffer.callback =
+
fun _ data _ ->
+
let event = Ctypes.(!@(from_voidp Open_event.t data)) in
+
Format.printf "%i,%i,%i,\"%s\"\n%!" (Open_event.get_pid event)
+
(Open_event.get_flags event)
+
(Open_event.get_mode event)
+
(Open_event.get_fname event);
+
0
+
in
+
RingBuffer.init map ~callback @@ fun rb ->
+
while !exitting do
+
Unix.sleepf 1.0;
+
let _ : int = RingBuffer.poll rb ~timeout:1 in
+
()
+
done
+
in
+
with_bpf_object_open_load_link ~obj_path ~program_names bpf_callback
+29
opentrace.opam
···
···
+
opam-version: "2.0"
+
synopsis: "Trace the opening of files"
+
description: "A linux tool using eBPF for tracing calls to open files"
+
maintainer: ["Patrick Ferris <patrick@sirref.org>"]
+
authors: ["Patrick Ferris <patrick@sirref.org>"]
+
license: "MIT"
+
homepage: "https://tangled.sh/@patrick.sirref.org/opentrace"
+
depends: [
+
"dune" {>= "3.17"}
+
"ocaml"
+
"libbpf"
+
"libbpg_map"
+
"odoc" {with-doc}
+
]
+
build: [
+
["dune" "subst"] {dev}
+
[
+
"dune"
+
"build"
+
"-p"
+
name
+
"-j"
+
jobs
+
"@install"
+
"@runtest" {with-test}
+
"@doc" {with-doc}
+
]
+
]
+
homepage: "https://tangled.sh/@patrick.sirref.org/opentrace"