diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5fde600 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.git +_build diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8961554 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM ocaml/opam:alpine-ocaml-5.3 as build + +RUN sudo apk add --no-cache \ + build-base \ + git \ + pkgconf \ + clang \ + libffi-dev \ + libbpf-dev \ + musl-dev + +WORKDIR /src + +COPY opentrace.opam /src +RUN opam install . --deps-only + +COPY . /src +RUN git apply static.patch +RUN opam exec -- dune build --profile=release + +FROM alpine +COPY --from=build /src/_build/default/install/opentrace /opentrace + diff --git a/dune b/dune index a05bd60..59a2082 100644 --- a/dune +++ b/dune @@ -1,5 +1,7 @@ (executable (name opentrace) + (public_name opentrace) + (flags (:standard -cclib -static -cclib -no-pie)) (libraries unix libbpf libbpf_maps)) (rule diff --git a/opentrace.bpf.c b/opentrace.bpf.c index 003de16..748b7c5 100644 --- a/opentrace.bpf.c +++ b/opentrace.bpf.c @@ -12,10 +12,15 @@ struct { #define FILE_NAME_LEN 1024 +#define OPEN_KIND 0 +#define OPENAT_KIND 1 +#define OPENAT2_KIND 2 + // An open event struct open_event { uint32_t e_pid; + int e_kind; int e_flags; uint32_t e_mode; char e_filename[FILE_NAME_LEN]; @@ -38,7 +43,8 @@ int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx return false; // Fill the open event - oet->e_pid = bpf_get_current_pid_tgid(); + oet->e_pid = id; + oet->e_kind = OPENAT_KIND; 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]); @@ -47,3 +53,60 @@ int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx return 0; } +SEC("tracepoint/syscalls/sys_enter_openat2") +int tracepoint__syscalls__sys_enter_openat2(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; + + struct open_how how = {}; + bpf_probe_read_user(&how, sizeof(how), (void *)ctx->args[2]); + oet->e_flags = (int)how.flags; + oet->e_mode = (__u32)how.mode; + oet->e_kind = OPENAT2_KIND; + // Fill the open event + oet->e_pid = id; + + bpf_probe_read(oet->e_filename, sizeof(filename), (char *) ctx->args[1]); + + bpf_ringbuf_submit(oet, 0); + return 0; +} + +SEC("tracepoint/syscalls/sys_enter_open") +int tracepoint__syscalls__sys_enter_open(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; + + oet->e_flags = (int)ctx->args[2]; + oet->e_mode = (__u32)ctx->args[3]; + oet->e_kind = OPEN_KIND; + // Fill the open event + oet->e_pid = id; + + bpf_probe_read(oet->e_filename, sizeof(filename), (char *) ctx->args[1]); + + bpf_ringbuf_submit(oet, 0); + return 0; +} diff --git a/opentrace.ml b/opentrace.ml index 64a4f79..c991d85 100644 --- a/opentrace.ml +++ b/opentrace.ml @@ -2,18 +2,37 @@ open Libbpf open Libbpf_maps let obj_path = "opentrace.bpf.o" -let program_names = [ "tracepoint__syscalls__sys_enter_openat" ] + +let program_names = + [ + "tracepoint__syscalls__sys_enter_openat"; + "tracepoint__syscalls__sys_enter_openat2"; + "tracepoint__syscalls__sys_enter_open"; + ] module Open_event = struct open Ctypes type t + type kind = Open_ | Openat | Openat2 + + let kind_to_string = function + | Open_ -> "open" + | Openat -> "openat" + | Openat2 -> "openat2" + + let kind_of_int = function + | 0 -> Open_ + | 1 -> Openat + | 2 -> Openat2 + | n -> failwith ("Invalid kind of open syscall: " ^ string_of_int n) let t : t structure typ = Ctypes.structure "event" let ( -: ) ty label = Ctypes.field t label ty - let pid = int -: "e_pid" + let pid = uint32_t -: "e_pid" + let kind = int -: "e_kind" let flags = int -: "e_flags" - let mode = int -: "e_mode" + let mode = uint32_t -: "e_mode" let filename = array 256 char -: "e_filename" let () = seal t @@ -28,10 +47,11 @@ module Open_event = struct Buffer.contents b with Exit -> Buffer.contents b - let get_pid s = getf s pid + let get_pid s = getf s pid |> Unsigned.UInt32.to_int let get_flags s = getf s flags - let get_mode s = getf s mode + let get_mode s = getf s mode |> Unsigned.UInt32.to_int let get_fname s = getf s filename |> char_array_as_string + let get_kind s = getf s kind |> kind_of_int end let () = @@ -43,13 +63,14 @@ let () = Sys.(set_signal sigterm sig_handler); (* Print header *) - Format.printf "pid,flags,mode,filename\n"; + Format.printf "pid,kind,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) + Format.printf "%i,%s,%i,%i,\"%s\"\n%!" (Open_event.get_pid event) + (Open_event.get_kind event |> Open_event.kind_to_string) (Open_event.get_flags event) (Open_event.get_mode event) (Open_event.get_fname event); diff --git a/opentrace.opam b/opentrace.opam index e0d5a34..fd500ef 100644 --- a/opentrace.opam +++ b/opentrace.opam @@ -9,7 +9,7 @@ depends: [ "dune" {>= "3.17"} "ocaml" "libbpf" - "libbpg_map" + "libbpf_maps" "odoc" {with-doc} ] build: [ @@ -27,3 +27,7 @@ build: [ ] ] homepage: "https://tangled.sh/@patrick.sirref.org/opentrace" +pin-depends:[ + [ "libbpf.dev" "git+https://github.com/patricoferris/ocaml-libbpf#alpine" ] + [ "libbpf_maps.dev" "git+https://github.com/patricoferris/ocaml-libbpf#alpine" ] +]