This repository implements logira, a Linux-only CLI auditor that records:
- process
execevents - file changes
- network activity
Each run is auto-saved under a per-run directory with JSONL + SQLite for auditing and fast search.
- Linux exec tracing MUST use eBPF tracepoint:
sched:sched_process_exec. - Collector MUST be OS-swappable:
collector/common.go: interfaces + event modelcollector/linux/collector.go: Linux implementationcollector/fallback_stub.go: non-Linux stub
- CLI MUST expose:
logira run -- <agent command...>(auto-saves run)logira runslogira view [last|<run-id>]logira query [filters...]logira explain [last|<run-id>]
- Logs MUST be JSONL with:
run_id,seq,ts(unix nanos),type,summary,data_jsontype:exec|file|net|detection
-
CLI:
cmd/logira/main.gointernal/cli/run.go,internal/cli/runs.go,internal/cli/view.go,internal/cli/query.go,internal/cli/explain.go
-
Run storage:
- base dir:
~/.logira(override:LOGIRA_HOME) - per-run dir:
~/.logira/runs/<run-id>/ - metadata:
internal/runs/
- base dir:
-
Storage/index:
- JSONL writer/reader:
internal/storage/jsonl.go,internal/storage/jsonl_read.go - SQLite (modernc, no CGO):
internal/storage/sqlite.go - Queries:
internal/storage/query.go
- JSONL writer/reader:
-
Detection (observe-only):
- rules engine:
internal/detect/engine.go
- rules engine:
-
Event model:
collector/common.godefinescollector.Eventandcollector.Collector.internal/model/events.godefines the JSON shapes used indetail.
-
Linux collector:
collector/linux/collector.gocomposes:- exec tracer:
collector/linux/exec/ - net tracer:
collector/linux/net/ - file watcher:
collector/linux/file/
- exec tracer:
- BPF C:
collector/linux/exec/_trace.bpf.c - Hooks:
tracepoint/sched/sched_process_exec(required)tracepoint/syscalls/sys_enter_execvetracepoint/syscalls/sys_enter_execveat
- Userspace loader:
collector/linux/exec/loader.go - Notes:
- PPID is best-effort enriched in userspace by reading
/proc/<pid>/stat. - CWD is best-effort enriched in userspace by reading
/proc/<pid>/cwd.
- PPID is best-effort enriched in userspace by reading
- BPF C:
collector/linux/net/_trace.bpf.c - Hooks:
- connect:
sys_enter_connect,sys_exit_connect - send:
sys_enter_sendto/sys_exit_sendto,sys_enter_sendmsg/sys_exit_sendmsg - recv:
sys_enter_recvfrom/sys_exit_recvfrom,sys_enter_recvmsg/sys_exit_recvmsg
- connect:
- Userspace loader:
collector/linux/net/loader.go - Notes:
- Destination is best-effort; for send/recv we cache
pid+fd -> dstfrom connect. protois currently best-effort and may beunknown.
- Destination is best-effort; for send/recv we cache
collector/linux/file/watcher.go- Strategy:
- fanotify first (captures PID via metadata), with
FAN_EVENT_ON_CHILDfor subtree. - inotify fallback (no PID attribution), recursively watches directories.
- fanotify first (captures PID via metadata), with
- Notes:
- Hashing is best-effort and capped by
--hash-max-bytes. hash_beforecomes from an in-memory cache and may be absent.
- Hashing is best-effort and capped by
The plan requires that generated BPF artifacts are committed so end users do not need clang.
- Generation entrypoints:
collector/linux/exec/generate.gocollector/linux/net/generate.goMakefiletargetgenerate
Expected generated outputs (commit them):
collector/linux/exec/trace_bpfel.o(and likelytrace_bpfeb.o)collector/linux/net/trace_bpfel.o(and likelytrace_bpfeb.o)trace_*.gofiles created bybpf2goin those directories
Runtime loader looks for (in this order):
collector/linux/*/trace_bpfel.ocollector/linux/*/trace.bpf.o
Override paths with:
LOGIRA_EXEC_BPF_OBJLOGIRA_NET_BPF_OBJ
- Always run on Linux for real validation.
- Run
gofmtover Go sources. - Keep event volume bounded (channels are bounded and may drop under pressure).
- Avoid changing JSONL schema casually; update
docs/jsonl.mdif you do.
go test ./...
- Generate BPF once (if missing):
make generate - Run integration tests:
go test -tags=integration ./collector/linux -v
- Build:
make build - Run:
sudo ./logirad./logira run -- bash -lc 'echo hi > x.txt; curl -s https://example.com >/dev/null'./logira view last./logira query --run last --type detection
- eBPF code currently focuses on correctness/best-effort data. Some fields can be
unknown. - Cross-kernel portability should be validated on kernel 5.8+ targets.
- If you change BPF event structs, keep userspace decoder in sync.