Initial Commit
This commit is contained in:
BIN
c-lang/loader
Executable file
BIN
c-lang/loader
Executable file
Binary file not shown.
77
c-lang/loader.c
Normal file
77
c-lang/loader.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <stdio.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
struct bpf_object *obj;
|
||||
struct bpf_program *prog;
|
||||
struct bpf_link *link;
|
||||
struct bpf_map *target_map;
|
||||
int err;
|
||||
const char *target_filename = "/tmp/testfile";
|
||||
int key = 0;
|
||||
char value[256] = {0};
|
||||
|
||||
strncpy(value, target_filename, sizeof(value) - 1);
|
||||
|
||||
obj = bpf_object__open_file("tracepoint.o", NULL);
|
||||
if (!obj) {
|
||||
fprintf(stderr, "Error opening BPF object\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Clean up any existing maps first
|
||||
bpf_object__unpin_maps(obj, "/sys/fs/bpf");
|
||||
|
||||
err = bpf_object__load(obj);
|
||||
if (err) {
|
||||
fprintf(stderr, "Error loading BPF object\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
target_map = bpf_object__find_map_by_name(obj, "target_filename_map");
|
||||
if (!target_map) {
|
||||
fprintf(stderr, "Error finding target_filename_map\n");
|
||||
bpf_object__close(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = bpf_map__update_elem(target_map, &key, sizeof(key), value, sizeof(value), BPF_ANY);
|
||||
if (err) {
|
||||
fprintf(stderr, "Error populating target_filename_map\n");
|
||||
bpf_object__close(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
prog = bpf_object__find_program_by_name(obj, "trace_openat");
|
||||
if (!prog) {
|
||||
fprintf(stderr, "Error finding BPF program\n");
|
||||
bpf_object__close(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
link = bpf_program__attach(prog);
|
||||
if (!link) {
|
||||
fprintf(stderr, "Error attaching BPF program\n");
|
||||
bpf_object__close(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = bpf_object__pin_maps(obj, "/sys/fs/bpf");
|
||||
if (err) {
|
||||
fprintf(stderr, "Error pinning BPF maps\n");
|
||||
bpf_link__destroy(link);
|
||||
bpf_object__close(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("BPF program loaded and maps pinned. Press Ctrl+C to exit.\n");
|
||||
|
||||
pause();
|
||||
|
||||
bpf_object__unpin_maps(obj, "/sys/fs/bpf");
|
||||
bpf_link__destroy(link);
|
||||
bpf_object__close(obj);
|
||||
return 0;
|
||||
}
|
||||
BIN
c-lang/monitor
Executable file
BIN
c-lang/monitor
Executable file
Binary file not shown.
45
c-lang/monitor.c
Normal file
45
c-lang/monitor.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <bpf/bpf.h>
|
||||
|
||||
struct event {
|
||||
__u32 pid;
|
||||
__u32 uid;
|
||||
char comm[16];
|
||||
char filename[256];
|
||||
};
|
||||
|
||||
// Simplified callback that actually works
|
||||
static void handle_event(void *ctx, int cpu, void *data, unsigned int size)
|
||||
{
|
||||
struct event *e = data;
|
||||
printf("PID: %d, UID: %d, CMD: %s, FILE: %s\n",
|
||||
e->pid, e->uid, e->comm, e->filename);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct perf_buffer *pb;
|
||||
int map_fd;
|
||||
|
||||
map_fd = bpf_obj_get("/sys/fs/bpf/events");
|
||||
if (map_fd < 0) {
|
||||
fprintf(stderr, "Failed to get BPF map\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This is the ONLY working syntax across all libbpf versions
|
||||
pb = perf_buffer__new(map_fd, 8, handle_event, NULL, NULL, NULL);
|
||||
if (!pb) {
|
||||
fprintf(stderr, "Failed to create perf buffer\n");
|
||||
close(map_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Monitoring started. Ctrl+C to exit.\n");
|
||||
while (perf_buffer__poll(pb, 1000) >= 0);
|
||||
|
||||
close(map_fd);
|
||||
return 0;
|
||||
}
|
||||
66
c-lang/tracepoint.c
Normal file
66
c-lang/tracepoint.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
struct sys_enter_args {
|
||||
unsigned long long unused;
|
||||
long syscall_nr;
|
||||
unsigned long args[6];
|
||||
};
|
||||
|
||||
struct event {
|
||||
__u32 pid;
|
||||
__u32 uid;
|
||||
char comm[16];
|
||||
char filename[256];
|
||||
};
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(__u32));
|
||||
} events SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, 256);
|
||||
__uint(max_entries, 1);
|
||||
__uint(map_flags, BPF_F_RDONLY_PROG); // Critical: Makes map read-only for BPF programs
|
||||
} target_filename_map SEC(".maps");
|
||||
|
||||
SEC("tracepoint/syscalls/sys_enter_openat")
|
||||
int trace_openat(struct sys_enter_args *ctx)
|
||||
{
|
||||
struct event e = {};
|
||||
char *target_filename;
|
||||
int key = 0;
|
||||
|
||||
// Read filename from syscall arguments
|
||||
bpf_probe_read_user_str(e.filename, sizeof(e.filename), (void *)ctx->args[1]);
|
||||
|
||||
// Get target filename from map
|
||||
target_filename = bpf_map_lookup_elem(&target_filename_map, &key);
|
||||
if (!target_filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare filenames - now safe because map is read-only
|
||||
for (int i = 0; i < sizeof(e.filename); i++) {
|
||||
if (e.filename[i] != target_filename[i]) {
|
||||
return 0; // No match
|
||||
}
|
||||
if (e.filename[i] == 0 || target_filename[i] == 0) {
|
||||
break; // End of string
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, filenames match
|
||||
e.pid = bpf_get_current_pid_tgid() >> 32;
|
||||
e.uid = bpf_get_current_uid_gid();
|
||||
bpf_get_current_comm(&e.comm, sizeof(e.comm));
|
||||
|
||||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e));
|
||||
return 0;
|
||||
}
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
BIN
c-lang/tracepoint.o
Normal file
BIN
c-lang/tracepoint.o
Normal file
Binary file not shown.
5
gen.go
Normal file
5
gen.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -tags linux tracepoint tracepoint.c
|
||||
7
go.mod
Normal file
7
go.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
module fim-ebpf
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require github.com/cilium/ebpf v0.19.0
|
||||
|
||||
require golang.org/x/sys v0.31.0 // indirect
|
||||
26
go.sum
Normal file
26
go.sum
Normal file
@@ -0,0 +1,26 @@
|
||||
github.com/cilium/ebpf v0.19.0 h1:Ro/rE64RmFBeA9FGjcTc+KmCeY6jXmryu6FfnzPRIao=
|
||||
github.com/cilium/ebpf v0.19.0/go.mod h1:fLCgMo3l8tZmAdM3B2XqdFzXBpwkcSTroaVqN08OWVY=
|
||||
github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s=
|
||||
github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
|
||||
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
102
main.go
Normal file
102
main.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf/link"
|
||||
"github.com/cilium/ebpf/perf"
|
||||
"github.com/cilium/ebpf/rlimit"
|
||||
)
|
||||
|
||||
// event matches the C struct in your BPF program
|
||||
type event struct {
|
||||
Pid uint32
|
||||
Uid uint32
|
||||
Comm [16]byte
|
||||
Filename [256]byte
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Allow the current process to lock memory for eBPF resources
|
||||
if err := rlimit.RemoveMemlock(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Load the pre-compiled BPF program
|
||||
objs := tracepointObjects{}
|
||||
if err := loadTracepointObjects(&objs, nil); err != nil {
|
||||
log.Fatalf("loading objects: %v", err)
|
||||
}
|
||||
defer objs.Close()
|
||||
|
||||
// Populate the target filename map (critical part)
|
||||
targetFilename := "/tmp/testfile\x00" // Null-terminated
|
||||
var filenameBuf [256]byte
|
||||
copy(filenameBuf[:], targetFilename)
|
||||
|
||||
key := uint32(0)
|
||||
if err := objs.TargetFilenameMap.Put(key, filenameBuf); err != nil {
|
||||
log.Fatalf("putting target filename in map: %v", err)
|
||||
}
|
||||
|
||||
// Attach the tracepoint
|
||||
tp, err := link.Tracepoint("syscalls", "sys_enter_openat", objs.TraceOpenat, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("attaching tracepoint: %v", err)
|
||||
}
|
||||
defer tp.Close()
|
||||
|
||||
// Set up perf event reader
|
||||
rd, err := perf.NewReader(objs.Events, os.Getpagesize())
|
||||
if err != nil {
|
||||
log.Fatalf("creating perf event reader: %v", err)
|
||||
}
|
||||
defer rd.Close()
|
||||
|
||||
log.Println("Monitoring for openat() syscalls to /tmp/testfile...")
|
||||
|
||||
// Graceful shutdown
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
record, err := rd.Read()
|
||||
if err != nil {
|
||||
if errors.Is(err, perf.ErrClosed) {
|
||||
return
|
||||
}
|
||||
log.Printf("reading from perf reader: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(record.RawSample) < int(unsafe.Sizeof(event{})) {
|
||||
log.Printf("invalid sample size: %d", len(record.RawSample))
|
||||
continue
|
||||
}
|
||||
|
||||
var e event
|
||||
if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &e); err != nil {
|
||||
log.Printf("parsing event: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert byte arrays to strings
|
||||
comm := string(bytes.TrimRight(e.Comm[:], "\x00"))
|
||||
filename := string(bytes.TrimRight(e.Filename[:], "\x00"))
|
||||
|
||||
log.Printf("PID: %d, UID: %d, CMD: %s, FILE: %s",
|
||||
e.Pid, e.Uid, comm, filename)
|
||||
}
|
||||
}()
|
||||
|
||||
<-sig
|
||||
log.Println("Shutting down...")
|
||||
}
|
||||
122
main.go.bkp
Normal file
122
main.go.bkp
Normal file
@@ -0,0 +1,122 @@
|
||||
//go:build linux
|
||||
|
||||
// This program demonstrates how to attach an eBPF program to a tracepoint.
|
||||
// The program is attached to the syscall/sys_enter_openat tracepoint and
|
||||
// prints out the integer 123 every time the syscall is entered.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/asm"
|
||||
"github.com/cilium/ebpf/link"
|
||||
"github.com/cilium/ebpf/perf"
|
||||
"github.com/cilium/ebpf/rlimit"
|
||||
)
|
||||
|
||||
// Metadata for the eBPF program used in this example.
|
||||
var progSpec = &ebpf.ProgramSpec{
|
||||
Name: "fim_monitoring", // non-unique name, will appear in `bpftool prog list` while attached
|
||||
Type: ebpf.TracePoint, // only TracePoint programs can be attached to trace events created by link.Tracepoint()
|
||||
License: "GPL", // license must be GPL for calling kernel helpers like perf_event_output
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// Subscribe to signals for terminating the program.
|
||||
stopper := make(chan os.Signal, 1)
|
||||
signal.Notify(stopper, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
// Allow the current process to lock memory for eBPF resources.
|
||||
if err := rlimit.RemoveMemlock(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a perf event array for the kernel to write perf records to.
|
||||
// These records will be read by userspace below.
|
||||
events, err := ebpf.NewMap(&ebpf.MapSpec{
|
||||
Type: ebpf.PerfEventArray,
|
||||
Name: "my_perf_array",
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("creating perf event array: %s", err)
|
||||
}
|
||||
defer events.Close()
|
||||
|
||||
// Open a perf reader from userspace into the perf event array
|
||||
// created earlier.
|
||||
rd, err := perf.NewReader(events, os.Getpagesize())
|
||||
if err != nil {
|
||||
log.Fatalf("creating event reader: %s", err)
|
||||
}
|
||||
defer rd.Close()
|
||||
|
||||
// Close the reader when the process receives a signal, which will exit
|
||||
// the read loop.
|
||||
go func() {
|
||||
<-stopper
|
||||
rd.Close()
|
||||
}()
|
||||
|
||||
// Minimal program that writes the static value '123' to the perf ring on
|
||||
// each event. Note that this program refers to the file descriptor of
|
||||
// the perf event array created above, which needs to be created prior to the
|
||||
// program being verified by and inserted into the kernel.
|
||||
progSpec.Instructions = asm.Instructions{
|
||||
// store the integer 123 at FP[-8]
|
||||
asm.Mov.Imm(asm.R2, 123),
|
||||
asm.StoreMem(asm.RFP, -8, asm.R2, asm.Word),
|
||||
|
||||
// load registers with arguments for call of FnPerfEventOutput
|
||||
asm.LoadMapPtr(asm.R2, events.FD()), // file descriptor of the perf event array
|
||||
asm.LoadImm(asm.R3, 0xffffffff, asm.DWord),
|
||||
asm.Mov.Reg(asm.R4, asm.RFP),
|
||||
asm.Add.Imm(asm.R4, -8),
|
||||
asm.Mov.Imm(asm.R5, 4),
|
||||
|
||||
// call FnPerfEventOutput, an eBPF kernel helper
|
||||
asm.FnPerfEventOutput.Call(),
|
||||
|
||||
// set exit code to 0
|
||||
asm.Mov.Imm(asm.R0, 0),
|
||||
asm.Return(),
|
||||
}
|
||||
|
||||
// Instantiate and insert the program into the kernel.
|
||||
prog, err := ebpf.NewProgram(progSpec)
|
||||
if err != nil {
|
||||
log.Fatalf("creating ebpf program: %s", err)
|
||||
}
|
||||
defer prog.Close()
|
||||
|
||||
// Open a trace event based on a pre-existing kernel hook (tracepoint).
|
||||
// Each time a userspace program uses the 'openat()' syscall, the eBPF
|
||||
// program specified above will be executed and a '123' value will appear
|
||||
// in the perf ring.
|
||||
tp, err := link.Tracepoint("syscalls", "sys_enter_openat", prog, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("opening tracepoint: %s", err)
|
||||
}
|
||||
defer tp.Close()
|
||||
|
||||
log.Println("Waiting for events..")
|
||||
|
||||
for {
|
||||
record, err := rd.Read()
|
||||
if err != nil {
|
||||
if errors.Is(err, perf.ErrClosed) {
|
||||
log.Println("Received signal, exiting..")
|
||||
return
|
||||
}
|
||||
log.Printf("reading from reader: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Println("Record:", record)
|
||||
}
|
||||
}
|
||||
71
tracepoint.c
Normal file
71
tracepoint.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
struct sys_enter_args {
|
||||
unsigned long long unused;
|
||||
long syscall_nr;
|
||||
unsigned long args[6];
|
||||
};
|
||||
|
||||
struct event {
|
||||
__u32 pid;
|
||||
__u32 uid;
|
||||
char comm[16];
|
||||
char filename[256];
|
||||
};
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__uint(max_entries, 1024);
|
||||
} events SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, 256); // Max filename length
|
||||
__uint(max_entries, 1);
|
||||
} target_filename_map SEC(".maps");
|
||||
|
||||
SEC("tracepoint/syscalls/sys_enter_openat")
|
||||
int trace_openat(struct sys_enter_args *ctx)
|
||||
{
|
||||
int zero = 0;
|
||||
char *target = bpf_map_lookup_elem(&target_filename_map, &zero);
|
||||
if (!target) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct event e = {};
|
||||
long ret;
|
||||
|
||||
// Read filename safely
|
||||
ret = bpf_probe_read_user_str(e.filename, sizeof(e.filename), (void *)ctx->args[1]);
|
||||
if (ret <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare strings properly
|
||||
for (int i = 0; i < sizeof(e.filename); i++) {
|
||||
if (e.filename[i] != target[i]) {
|
||||
return 0;
|
||||
}
|
||||
// Stop at null terminator
|
||||
if (e.filename[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill event data
|
||||
e.pid = bpf_get_current_pid_tgid() >> 32;
|
||||
e.uid = bpf_get_current_uid_gid();
|
||||
bpf_get_current_comm(&e.comm, sizeof(e.comm));
|
||||
|
||||
// Submit event
|
||||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e));
|
||||
return 0;
|
||||
}
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
40
tracepoint.c.bkp
Normal file
40
tracepoint.c.bkp
Normal file
@@ -0,0 +1,40 @@
|
||||
//go:build ignore
|
||||
|
||||
#include "common.h"
|
||||
|
||||
char __license[] SEC("license") = "Dual MIT/GPL";
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, u32);
|
||||
__type(value, u64);
|
||||
__uint(max_entries, 1);
|
||||
} counting_map SEC(".maps");
|
||||
|
||||
// This struct is defined according to the following format file:
|
||||
// /sys/kernel/tracing/events/kmem/mm_page_alloc/format
|
||||
struct alloc_info {
|
||||
/* The first 8 bytes is not allowed to read */
|
||||
unsigned long pad;
|
||||
|
||||
unsigned long pfn;
|
||||
unsigned int order;
|
||||
unsigned int gfp_flags;
|
||||
int migratetype;
|
||||
};
|
||||
|
||||
// This tracepoint is defined in mm/page_alloc.c:__alloc_pages_nodemask()
|
||||
// Userspace pathname: /sys/kernel/tracing/events/kmem/mm_page_alloc
|
||||
SEC("tracepoint/kmem/mm_page_alloc")
|
||||
int mm_page_alloc(struct alloc_info *info) {
|
||||
u32 key = 0;
|
||||
u64 initval = 1, *valp;
|
||||
|
||||
valp = bpf_map_lookup_elem(&counting_map, &key);
|
||||
if (!valp) {
|
||||
bpf_map_update_elem(&counting_map, &key, &initval, BPF_ANY);
|
||||
return 0;
|
||||
}
|
||||
__sync_fetch_and_add(valp, 1);
|
||||
return 0;
|
||||
}
|
||||
BIN
tracepoint.o
Normal file
BIN
tracepoint.o
Normal file
Binary file not shown.
136
tracepoint_bpfeb.go
Normal file
136
tracepoint_bpfeb.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// Code generated by bpf2go; DO NOT EDIT.
|
||||
//go:build (mips || mips64 || ppc64 || s390x) && linux
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
// loadTracepoint returns the embedded CollectionSpec for tracepoint.
|
||||
func loadTracepoint() (*ebpf.CollectionSpec, error) {
|
||||
reader := bytes.NewReader(_TracepointBytes)
|
||||
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't load tracepoint: %w", err)
|
||||
}
|
||||
|
||||
return spec, err
|
||||
}
|
||||
|
||||
// loadTracepointObjects loads tracepoint and converts it into a struct.
|
||||
//
|
||||
// The following types are suitable as obj argument:
|
||||
//
|
||||
// *tracepointObjects
|
||||
// *tracepointPrograms
|
||||
// *tracepointMaps
|
||||
//
|
||||
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||
func loadTracepointObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||
spec, err := loadTracepoint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return spec.LoadAndAssign(obj, opts)
|
||||
}
|
||||
|
||||
// tracepointSpecs contains maps and programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointSpecs struct {
|
||||
tracepointProgramSpecs
|
||||
tracepointMapSpecs
|
||||
tracepointVariableSpecs
|
||||
}
|
||||
|
||||
// tracepointProgramSpecs contains programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointProgramSpecs struct {
|
||||
TraceOpenat *ebpf.ProgramSpec `ebpf:"trace_openat"`
|
||||
}
|
||||
|
||||
// tracepointMapSpecs contains maps before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointMapSpecs struct {
|
||||
Events *ebpf.MapSpec `ebpf:"events"`
|
||||
TargetFilenameMap *ebpf.MapSpec `ebpf:"target_filename_map"`
|
||||
}
|
||||
|
||||
// tracepointVariableSpecs contains global variables before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointVariableSpecs struct {
|
||||
}
|
||||
|
||||
// tracepointObjects contains all objects after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointObjects struct {
|
||||
tracepointPrograms
|
||||
tracepointMaps
|
||||
tracepointVariables
|
||||
}
|
||||
|
||||
func (o *tracepointObjects) Close() error {
|
||||
return _TracepointClose(
|
||||
&o.tracepointPrograms,
|
||||
&o.tracepointMaps,
|
||||
)
|
||||
}
|
||||
|
||||
// tracepointMaps contains all maps after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointMaps struct {
|
||||
Events *ebpf.Map `ebpf:"events"`
|
||||
TargetFilenameMap *ebpf.Map `ebpf:"target_filename_map"`
|
||||
}
|
||||
|
||||
func (m *tracepointMaps) Close() error {
|
||||
return _TracepointClose(
|
||||
m.Events,
|
||||
m.TargetFilenameMap,
|
||||
)
|
||||
}
|
||||
|
||||
// tracepointVariables contains all global variables after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointVariables struct {
|
||||
}
|
||||
|
||||
// tracepointPrograms contains all programs after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointPrograms struct {
|
||||
TraceOpenat *ebpf.Program `ebpf:"trace_openat"`
|
||||
}
|
||||
|
||||
func (p *tracepointPrograms) Close() error {
|
||||
return _TracepointClose(
|
||||
p.TraceOpenat,
|
||||
)
|
||||
}
|
||||
|
||||
func _TracepointClose(closers ...io.Closer) error {
|
||||
for _, closer := range closers {
|
||||
if err := closer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do not access this directly.
|
||||
//
|
||||
//go:embed tracepoint_bpfeb.o
|
||||
var _TracepointBytes []byte
|
||||
BIN
tracepoint_bpfeb.o
Normal file
BIN
tracepoint_bpfeb.o
Normal file
Binary file not shown.
136
tracepoint_bpfel.go
Normal file
136
tracepoint_bpfel.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// Code generated by bpf2go; DO NOT EDIT.
|
||||
//go:build (386 || amd64 || arm || arm64 || loong64 || mips64le || mipsle || ppc64le || riscv64 || wasm) && linux
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
// loadTracepoint returns the embedded CollectionSpec for tracepoint.
|
||||
func loadTracepoint() (*ebpf.CollectionSpec, error) {
|
||||
reader := bytes.NewReader(_TracepointBytes)
|
||||
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't load tracepoint: %w", err)
|
||||
}
|
||||
|
||||
return spec, err
|
||||
}
|
||||
|
||||
// loadTracepointObjects loads tracepoint and converts it into a struct.
|
||||
//
|
||||
// The following types are suitable as obj argument:
|
||||
//
|
||||
// *tracepointObjects
|
||||
// *tracepointPrograms
|
||||
// *tracepointMaps
|
||||
//
|
||||
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||
func loadTracepointObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||
spec, err := loadTracepoint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return spec.LoadAndAssign(obj, opts)
|
||||
}
|
||||
|
||||
// tracepointSpecs contains maps and programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointSpecs struct {
|
||||
tracepointProgramSpecs
|
||||
tracepointMapSpecs
|
||||
tracepointVariableSpecs
|
||||
}
|
||||
|
||||
// tracepointProgramSpecs contains programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointProgramSpecs struct {
|
||||
TraceOpenat *ebpf.ProgramSpec `ebpf:"trace_openat"`
|
||||
}
|
||||
|
||||
// tracepointMapSpecs contains maps before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointMapSpecs struct {
|
||||
Events *ebpf.MapSpec `ebpf:"events"`
|
||||
TargetFilenameMap *ebpf.MapSpec `ebpf:"target_filename_map"`
|
||||
}
|
||||
|
||||
// tracepointVariableSpecs contains global variables before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tracepointVariableSpecs struct {
|
||||
}
|
||||
|
||||
// tracepointObjects contains all objects after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointObjects struct {
|
||||
tracepointPrograms
|
||||
tracepointMaps
|
||||
tracepointVariables
|
||||
}
|
||||
|
||||
func (o *tracepointObjects) Close() error {
|
||||
return _TracepointClose(
|
||||
&o.tracepointPrograms,
|
||||
&o.tracepointMaps,
|
||||
)
|
||||
}
|
||||
|
||||
// tracepointMaps contains all maps after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointMaps struct {
|
||||
Events *ebpf.Map `ebpf:"events"`
|
||||
TargetFilenameMap *ebpf.Map `ebpf:"target_filename_map"`
|
||||
}
|
||||
|
||||
func (m *tracepointMaps) Close() error {
|
||||
return _TracepointClose(
|
||||
m.Events,
|
||||
m.TargetFilenameMap,
|
||||
)
|
||||
}
|
||||
|
||||
// tracepointVariables contains all global variables after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointVariables struct {
|
||||
}
|
||||
|
||||
// tracepointPrograms contains all programs after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tracepointPrograms struct {
|
||||
TraceOpenat *ebpf.Program `ebpf:"trace_openat"`
|
||||
}
|
||||
|
||||
func (p *tracepointPrograms) Close() error {
|
||||
return _TracepointClose(
|
||||
p.TraceOpenat,
|
||||
)
|
||||
}
|
||||
|
||||
func _TracepointClose(closers ...io.Closer) error {
|
||||
for _, closer := range closers {
|
||||
if err := closer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do not access this directly.
|
||||
//
|
||||
//go:embed tracepoint_bpfel.o
|
||||
var _TracepointBytes []byte
|
||||
BIN
tracepoint_bpfel.o
Normal file
BIN
tracepoint_bpfel.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user