Push initial working version

This commit is contained in:
Harshavardhan Musanalli
2025-08-18 08:15:33 +02:00
parent 912a283f7c
commit ad4f459de5
18 changed files with 158470 additions and 2536 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
fim-ebpf
tracepoint_bpfeb.o
tracepoint_bpfel.o

2
README.md Normal file
View File

@@ -0,0 +1,2 @@
# fim-ebpf
This is a POC of FIM based on EBPF.

12
config.yaml Normal file
View File

@@ -0,0 +1,12 @@
monitored_files:
- /tmp/testfile
- /etc/passwd
- /etc/shadow
ignore_actions:
- read
- stat
ignore_users:
- backupuser
- harsha

BIN
fim-ebpf

Binary file not shown.

4
gen.go
View File

@@ -1,5 +1,5 @@
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g -Wall" tracepoint tracepoint.c -- -target bpf
package main package main
import "C" import "C"
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -tags linux tracepoint tracepoint.c

5
go.mod
View File

@@ -4,4 +4,7 @@ go 1.24.2
require github.com/cilium/ebpf v0.19.0 require github.com/cilium/ebpf v0.19.0
require golang.org/x/sys v0.31.0 // indirect require (
golang.org/x/sys v0.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

3
go.sum
View File

@@ -24,3 +24,6 @@ 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/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 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

167
main.go
View File

@@ -4,65 +4,123 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"log" "log"
"os" "os"
"os/signal" "os/signal"
"os/user"
"syscall" "syscall"
"unsafe"
"github.com/cilium/ebpf/link" "github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/perf" "github.com/cilium/ebpf/perf"
"github.com/cilium/ebpf/rlimit" "github.com/cilium/ebpf/rlimit"
"gopkg.in/yaml.v3"
) )
// event matches the C struct in your BPF program type Config struct {
MonitoredFiles []string `yaml:"monitored_files"`
IgnoreActions []string `yaml:"ignore_actions"`
IgnoreUsers []string `yaml:"ignore_users"`
}
type event struct { type event struct {
Pid uint32 Pid uint32
Uid uint32 Uid uint32
Euid uint32
Loginuid uint32
FilenameHash uint32
Comm [16]byte Comm [16]byte
Filename [256]byte Filename [256]byte
Flags uint32
}
// simpleHash implements the same DJB2-like hash as the eBPF C code.
func simpleHash(filename string) uint32 {
hash := uint32(5381)
for _, c := range []byte(filename) {
hash = ((hash << 5) + hash) + uint32(c) // hash * 33 + c
}
return hash
}
func loadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading config file: %w", err)
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("parsing config: %w", err)
}
return &cfg, nil
}
func parseUint32(s string) (uint32, error) {
var n uint32
_, err := fmt.Sscanf(s, "%d", &n)
return n, err
}
func isReadOperation(flags uint32) bool {
return (flags & (syscall.O_WRONLY | syscall.O_RDWR)) == 0
} }
func main() { func main() {
// Allow the current process to lock memory for eBPF resources cfg, err := loadConfig("config.yaml")
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
if err := rlimit.RemoveMemlock(); err != nil { if err := rlimit.RemoveMemlock(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
// Load the pre-compiled BPF program
objs := tracepointObjects{} objs := tracepointObjects{}
if err := loadTracepointObjects(&objs, nil); err != nil { if err := loadTracepointObjects(&objs, nil); err != nil {
log.Fatalf("loading objects: %v", err) log.Fatalf("Loading objects: %v", err)
} }
defer objs.Close() defer objs.Close()
// Populate the target filename map (critical part) // Populate filename hashes
targetFilename := "/tmp/testfile\x00" // Null-terminated for _, file := range cfg.MonitoredFiles {
var filenameBuf [256]byte hash := simpleHash(file)
copy(filenameBuf[:], targetFilename) val := uint32(1) // Just a marker
if err := objs.TargetHashesMap.Put(hash, val); err != nil {
key := uint32(0) log.Fatalf("Failed to add hash for %s: %v", file, err)
if err := objs.TargetFilenameMap.Put(key, filenameBuf); err != nil { }
log.Fatalf("putting target filename in map: %v", err) }
// Populate ignored UIDs
for _, username := range cfg.IgnoreUsers {
u, err := user.Lookup(username)
if err != nil {
log.Printf("Warning: user %s not found", username)
continue
}
uid, err := parseUint32(u.Uid)
if err != nil {
log.Fatalf("Failed to parse UID for %s: %v", u.Uid, err)
}
if err := objs.IgnoreUidsMap.Put(uid, uint32(1)); err != nil {
log.Printf("Failed to ignore UID %d: %v", uid, err)
}
} }
// Attach the tracepoint
tp, err := link.Tracepoint("syscalls", "sys_enter_openat", objs.TraceOpenat, nil) tp, err := link.Tracepoint("syscalls", "sys_enter_openat", objs.TraceOpenat, nil)
if err != nil { if err != nil {
log.Fatalf("attaching tracepoint: %v", err) log.Fatal(err)
} }
defer tp.Close() defer tp.Close()
// Set up perf event reader
rd, err := perf.NewReader(objs.Events, os.Getpagesize()) rd, err := perf.NewReader(objs.Events, os.Getpagesize())
if err != nil { if err != nil {
log.Fatalf("creating perf event reader: %v", err) log.Fatal(err)
} }
defer rd.Close() defer rd.Close()
log.Println("Monitoring for openat() syscalls to /tmp/testfile...")
// Graceful shutdown
sig := make(chan os.Signal, 1) sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
@@ -73,30 +131,75 @@ func main() {
if errors.Is(err, perf.ErrClosed) { if errors.Is(err, perf.ErrClosed) {
return return
} }
log.Printf("reading from perf reader: %v", err) log.Printf("Reading event: %v", err)
continue
}
if len(record.RawSample) < int(unsafe.Sizeof(event{})) {
log.Printf("invalid sample size: %d", len(record.RawSample))
continue continue
} }
var e event var e event
if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &e); err != nil { if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &e); err != nil {
log.Printf("parsing event: %v", err) log.Printf("Decoding event: %v", err)
continue continue
} }
// Convert byte arrays to strings // Final verification in userspace
comm := string(bytes.TrimRight(e.Comm[:], "\x00")) matched := false
filename := string(bytes.TrimRight(e.Filename[:], "\x00")) currentFile := string(bytes.TrimRight(e.Filename[:], "\x00"))
for _, file := range cfg.MonitoredFiles {
if currentFile == file {
matched = true
break
}
}
if !matched {
continue
}
log.Printf("PID: %d, UID: %d, CMD: %s, FILE: %s", // Skip ignored actions
e.Pid, e.Uid, comm, filename) if isReadOperation(e.Flags) && contains(cfg.IgnoreActions, "read") {
continue
}
// Get username from UID
currentUsername := "unknown"
if e.Uid == 0 {
currentUsername = "root"
} else if user, err := user.LookupId(fmt.Sprintf("%d", e.Uid)); err == nil {
currentUsername = user.Username
}
// With this more robust version:
userInfo := fmt.Sprintf("%d (%s)", e.Uid, currentUsername)
if e.Loginuid != 0 && e.Uid != e.Loginuid {
loginUser, err := user.LookupId(fmt.Sprintf("%d", e.Loginuid))
loginUsername := "unknown"
if err == nil {
loginUsername = loginUser.Username
}
userInfo = fmt.Sprintf("%d (%s) [Login: %d (%s)]",
e.Uid, currentUsername, e.Loginuid, loginUsername)
}
log.Printf("Event: PID=%d UID=%d (%s) CMD=%s FILE=%s FLAGS=%08x",
e.Pid,
e.Uid,
userInfo,
string(bytes.TrimRight(e.Comm[:], "\x00")),
string(bytes.TrimRight(e.Filename[:], "\x00")),
e.Flags,
)
} }
}() }()
log.Println("Monitoring started. Ctrl+C to exit.")
<-sig <-sig
log.Println("Shutting down...") log.Println("Shutting down...")
} }
func contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}

View File

@@ -1,122 +0,0 @@
//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)
}
}

2290
probe.out

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,10 @@
#include <linux/bpf.h> #include "vmlinux.h"
//#include <linux/bpf.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h> #include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
//#include <linux/sched.h>
struct sys_enter_args { struct sys_enter_args {
unsigned long long unused; unsigned long long unused;
@@ -11,59 +15,94 @@ struct sys_enter_args {
struct event { struct event {
__u32 pid; __u32 pid;
__u32 uid; __u32 uid;
__u32 euid;
__u32 loginuid;
__u32 filename_hash; // Hash of filename for matching
char comm[16]; char comm[16];
char filename[256]; char filename[256]; // Full filename for userspace verification
__u32 flags;
}; };
struct { struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int)); __uint(key_size, sizeof(int));
__uint(value_size, sizeof(int)); __uint(value_size, sizeof(int));
__uint(max_entries, 1024);
} events SEC(".maps"); } events SEC(".maps");
struct { struct {
__uint(type, BPF_MAP_TYPE_HASH); __uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(int)); __uint(key_size, sizeof(__u32)); // Stores filename hashes
__uint(value_size, 256); // Max filename length __uint(value_size, sizeof(__u32));
__uint(max_entries, 1); __uint(max_entries, 32);
} target_filename_map SEC(".maps"); } target_hashes_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(__u32)); // UIDs to ignore
__uint(value_size, sizeof(__u32));
__uint(max_entries, 16);
} ignore_uids_map SEC(".maps");
// Simple hash function that the verifier can understand
static inline __u32 simple_hash(const char *str) {
__u32 hash = 5381;
for (int i = 0; i < 256 && str[i] != '\0'; i++) {
hash = ((hash << 5) + hash) + str[i]; // hash * 33 + c
}
return hash;
}
SEC("tracepoint/syscalls/sys_enter_openat") SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat(struct sys_enter_args *ctx) 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 = {}; struct event e = {};
long ret; long ret;
// Read filename safely // Read filename
ret = bpf_probe_read_user_str(e.filename, sizeof(e.filename), (void *)ctx->args[1]); ret = bpf_probe_read_user_str(e.filename, sizeof(e.filename), (void *)ctx->args[1]);
if (ret <= 0) { if (ret <= 0) return 0;
return 0;
// Debug: Print every filename accessed
bpf_printk("file accessed: %s", e.filename);
// Calculate filename hash
e.filename_hash = simple_hash(e.filename);
// Check if hash matches any monitored files
__u32 *match = bpf_map_lookup_elem(&target_hashes_map, &e.filename_hash);
if (!match) return 0;
// Get UID information
__u64 uid_gid = bpf_get_current_uid_gid();
e.uid = uid_gid;
e.euid = (uid_gid >> 32);
struct task_struct *task;
struct task_struct *parent;
task = (struct task_struct *)bpf_get_current_task();
ret = bpf_probe_read(&parent, sizeof(parent), &task->real_parent);
if (ret != 0 || !parent) {
// Handle the case where real_parent is not available (e.g., init process)
e.loginuid = 0; // or some other sensible default
} else {
// Only read loginuid if the parent pointer is valid
bpf_probe_read(&e.loginuid, sizeof(e.loginuid), &parent->loginuid);
} }
// Compare strings properly bpf_printk("BPF DEBUG: pid=%d uid=%d euid=%d loginuid=%d", e.pid, e.uid, e.euid, e.loginuid);
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 // Check ignored UIDs
__u32 *ignore = bpf_map_lookup_elem(&ignore_uids_map, &e.uid);
if (!ignore) {
ignore = bpf_map_lookup_elem(&ignore_uids_map, &e.loginuid);
}
if (ignore) return 0;
// Get process info
e.pid = bpf_get_current_pid_tgid() >> 32; 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_get_current_comm(&e.comm, sizeof(e.comm));
e.flags = ctx->args[2];
// Submit event
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e)); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e));
return 0; return 0;
} }

View File

@@ -1,40 +0,0 @@
//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;
}

Binary file not shown.

View File

@@ -1,5 +1,5 @@
// Code generated by bpf2go; DO NOT EDIT. // Code generated by bpf2go; DO NOT EDIT.
//go:build (mips || mips64 || ppc64 || s390x) && linux //go:build mips || mips64 || ppc64 || s390x
package main package main
@@ -62,7 +62,8 @@ type tracepointProgramSpecs struct {
// It can be passed ebpf.CollectionSpec.Assign. // It can be passed ebpf.CollectionSpec.Assign.
type tracepointMapSpecs struct { type tracepointMapSpecs struct {
Events *ebpf.MapSpec `ebpf:"events"` Events *ebpf.MapSpec `ebpf:"events"`
TargetFilenameMap *ebpf.MapSpec `ebpf:"target_filename_map"` IgnoreUidsMap *ebpf.MapSpec `ebpf:"ignore_uids_map"`
TargetHashesMap *ebpf.MapSpec `ebpf:"target_hashes_map"`
} }
// tracepointVariableSpecs contains global variables before they are loaded into the kernel. // tracepointVariableSpecs contains global variables before they are loaded into the kernel.
@@ -92,13 +93,15 @@ func (o *tracepointObjects) Close() error {
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign. // It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
type tracepointMaps struct { type tracepointMaps struct {
Events *ebpf.Map `ebpf:"events"` Events *ebpf.Map `ebpf:"events"`
TargetFilenameMap *ebpf.Map `ebpf:"target_filename_map"` IgnoreUidsMap *ebpf.Map `ebpf:"ignore_uids_map"`
TargetHashesMap *ebpf.Map `ebpf:"target_hashes_map"`
} }
func (m *tracepointMaps) Close() error { func (m *tracepointMaps) Close() error {
return _TracepointClose( return _TracepointClose(
m.Events, m.Events,
m.TargetFilenameMap, m.IgnoreUidsMap,
m.TargetHashesMap,
) )
} }

Binary file not shown.

View File

@@ -1,5 +1,5 @@
// Code generated by bpf2go; DO NOT EDIT. // Code generated by bpf2go; DO NOT EDIT.
//go:build (386 || amd64 || arm || arm64 || loong64 || mips64le || mipsle || ppc64le || riscv64 || wasm) && linux //go:build 386 || amd64 || arm || arm64 || loong64 || mips64le || mipsle || ppc64le || riscv64 || wasm
package main package main
@@ -62,7 +62,8 @@ type tracepointProgramSpecs struct {
// It can be passed ebpf.CollectionSpec.Assign. // It can be passed ebpf.CollectionSpec.Assign.
type tracepointMapSpecs struct { type tracepointMapSpecs struct {
Events *ebpf.MapSpec `ebpf:"events"` Events *ebpf.MapSpec `ebpf:"events"`
TargetFilenameMap *ebpf.MapSpec `ebpf:"target_filename_map"` IgnoreUidsMap *ebpf.MapSpec `ebpf:"ignore_uids_map"`
TargetHashesMap *ebpf.MapSpec `ebpf:"target_hashes_map"`
} }
// tracepointVariableSpecs contains global variables before they are loaded into the kernel. // tracepointVariableSpecs contains global variables before they are loaded into the kernel.
@@ -92,13 +93,15 @@ func (o *tracepointObjects) Close() error {
// It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign. // It can be passed to loadTracepointObjects or ebpf.CollectionSpec.LoadAndAssign.
type tracepointMaps struct { type tracepointMaps struct {
Events *ebpf.Map `ebpf:"events"` Events *ebpf.Map `ebpf:"events"`
TargetFilenameMap *ebpf.Map `ebpf:"target_filename_map"` IgnoreUidsMap *ebpf.Map `ebpf:"ignore_uids_map"`
TargetHashesMap *ebpf.Map `ebpf:"target_hashes_map"`
} }
func (m *tracepointMaps) Close() error { func (m *tracepointMaps) Close() error {
return _TracepointClose( return _TracepointClose(
m.Events, m.Events,
m.TargetFilenameMap, m.IgnoreUidsMap,
m.TargetHashesMap,
) )
} }

Binary file not shown.

158215
vmlinux.h Normal file

File diff suppressed because it is too large Load Diff