Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
f29acf6
chore(deps): Add cilium/ebpf dependency
mostafa Aug 5, 2026
c0f504a
chore(ebpf): Add feature probes and race-safe process reconciler
mostafa Aug 5, 2026
c24ea9d
chore(ebpf): Add CO-RE spike for exec and task iterator
mostafa Aug 5, 2026
5785ab0
docs(ebpf): Document Linux eBPF feasibility and build gating worklist
mostafa Aug 5, 2026
e054729
fix(ebpf): Harden spike reconciler ownership and shutdown paths
mostafa Aug 5, 2026
9b80f89
fix(ebpf): Restore cilium/ebpf module and rename import alias
mostafa Aug 7, 2026
d8592b3
refactor(bootstrap): Split bootstrap and CLI entrypoints for Linux
mostafa Aug 8, 2026
ef171b1
feat(event): Add Linux semantic event type identifiers
mostafa Aug 8, 2026
13f58b7
feat(config): Add Linux event source configuration
mostafa Aug 8, 2026
40f1d5f
refactor(ps): Introduce Resolver and Linux snapshotter
mostafa Aug 8, 2026
cebca20
fix(build): Gate remaining Windows-only packages for Linux builds
mostafa Aug 8, 2026
a3fdfce
fix(build): Gate Windows-only packages for Linux compilation
mostafa Aug 8, 2026
e119ecb
fix(build): Remove superseded Windows-gated catalog copies
mostafa Aug 8, 2026
9f6ca59
feat(event): Add Linux event helpers and parameter formatting
mostafa Aug 8, 2026
b8dcc6b
feat(ps): Implement LinuxSnapshotter and ProcessKey
mostafa Aug 8, 2026
a6acbf7
refactor(rules): Migrate shared consumers to ps.Resolver
mostafa Aug 8, 2026
0057502
chore(build): Attribute new Linux files to Mostafa Moradian
mostafa Aug 8, 2026
3c13e4f
chore(ebpf): Attribute eBPF spike files to Mostafa Moradian
mostafa Aug 9, 2026
e893121
refactor(cli): Share config/list/rules/stats commands across platforms
mostafa Aug 10, 2026
67c2666
fix(cap): Drop Handle and PE capture sections on Linux
mostafa Aug 10, 2026
5fbf265
refactor(ps): Prefer per-platform Snapshotter interfaces
mostafa Aug 10, 2026
a3afc8d
refactor(config): Split alertsender loading by platform
mostafa Aug 10, 2026
4e9edda
refactor(config): share platform-neutral configuration
mostafa Aug 10, 2026
32cb9e8
refactor(event): define Linux-native event semantics
mostafa Aug 10, 2026
88a2cfd
refactor(rules): adapt filtering to platform event models
mostafa Aug 10, 2026
2416794
refactor(ps): remove Windows concepts from Linux process state
mostafa Aug 10, 2026
52b9d4b
refactor(platform): align local transports and file layout
mostafa Aug 12, 2026
50bad3e
refactor(config): enforce Linux-native event settings
mostafa Aug 12, 2026
dafcc98
feat(ebpf): Add Linux process event source
mostafa Sep 14, 2026
546fd09
fix(ebpf): Skip optional fork and vfork attach failures
mostafa Sep 14, 2026
df8c389
fix(ebpf): Emit process exits from sched_process_exit
mostafa Sep 14, 2026
d845c7c
fix(ebpf): Preserve ring buffer order during startup replay
mostafa Sep 14, 2026
c52ed31
test(event): Cover the Linux sequencer
mostafa Sep 14, 2026
b80b1fa
refactor(bootstrap): Align Linux bootstrap with platform conventions
mostafa Sep 14, 2026
90ec3db
ci: Validate PR titles targeting linux-port
mostafa Sep 14, 2026
d3daa2c
refactor(ebpf): Simplify the ring buffer record model
mostafa Sep 14, 2026
f04626d
feat(event): Add Linux syscall telemetry types and parameters
mostafa Sep 15, 2026
e402a4d
feat(ebpf): Extend the shared syscall record and enabled-type map
mostafa Sep 15, 2026
151dca5
feat(ebpf): Capture file, network, memory, and process-control syscalls
mostafa Sep 15, 2026
e79d9d6
test(ebpf): Cover the MVP syscall event matrix
mostafa Sep 15, 2026
8f38145
refactor(ebpf): Capture process-control syscalls at exit
mostafa Sep 15, 2026
54978c0
feat(filter): Add Linux field catalog for the syscall event matrix
mostafa Sep 16, 2026
c687d0f
feat(filter): Evaluate Linux process, file, network, memory, and thre…
mostafa Sep 16, 2026
da70c08
test(filter): Cover Linux field compile, evaluation, defaults, and tr…
mostafa Sep 16, 2026
08d0f2e
refactor(filter): Align Linux field names with catalog conventions
mostafa Sep 16, 2026
d42955a
feat(build): Add Makefile for build targets
rabbitstack Sep 16, 2026
ef68c7e
fix(build): Point Makefile bpf targets at the generated package
mostafa Sep 21, 2026
78bb439
feat(rules): Signal kill after confirming process instance identity
mostafa Sep 21, 2026
c1d5e61
feat(rules): Add Linux macros and rules for execve, ptrace, kill, and…
mostafa Sep 21, 2026
630f855
test(rules): Cover Linux detection compile, matches, and sequences
mostafa Sep 21, 2026
27249b2
fix(ebpf): Preserve the pid_t sign of signal and trace targets
mostafa Sep 21, 2026
99d831c
feat(filter): Extract conservative equality, list, and prefix prefilters
mostafa Sep 21, 2026
a2b08a7
feat(ebpf): Prefilter syscalls with versioned in-kernel maps
mostafa Sep 21, 2026
bdfe340
feat(ebpf): Apply rule and CLI prefilters after maps load
mostafa Sep 21, 2026
0f0f766
feat(ebpf): Approve file paths written as trailing-star patterns
mostafa Sep 22, 2026
5fb51d6
test(ebpf): Cover path lists and separate capture from approval
mostafa Sep 22, 2026
7cbb4b9
refactor: Confine platform-only helpers to their build tags
mostafa Sep 23, 2026
6e374ea
feat(build): Add Linux build, lint, and generation-drift targets
mostafa Sep 23, 2026
f719cea
ci: Extend the Linux workflow to lint, race, and a prerequisite probe
mostafa Sep 23, 2026
3733934
docs: Describe the Linux runtime contract and capabilities
mostafa Sep 23, 2026
d3be6a5
feat(config): Default the Linux API transport to a UNIX socket
mostafa Sep 23, 2026
e2113d1
feat(build): Package Fibratus for deb and rpm with a systemd unit
mostafa Sep 23, 2026
7e66a7a
feat(cli): Report eBPF counters in stats and cover both API transports
mostafa Sep 23, 2026
21baf52
docs: Add Linux install and quick-start instructions
mostafa Sep 23, 2026
639c8b1
refactor(linux,windows): Reconcile post-rebase state
rabbitstack Sep 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
72 changes: 72 additions & 0 deletions .github/workflows/linux-port.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: linux-port

on:
pull_request:
branches:
- linux-port
workflow_dispatch:

concurrency:
group: linux-port-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
GO_VERSION: 1.26.x
GOLANGCI_LINT_VERSION: v2.9.0
CLANG_VERSION: 18

jobs:
ebpf:
runs-on: ubuntu-latest
steps:
- name: Validate PR title
if: github.event_name == 'pull_request'
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
# Deliberately before clang is installed: a checkout must build from the
# committed objects alone.
- name: Build without generation tools
run: make
- name: Install clang
run: |
sudo apt-get update
sudo apt-get install -y clang-${{ env.CLANG_VERSION }} llvm-${{ env.CLANG_VERSION }}
clang-${{ env.CLANG_VERSION }} --version
# The versioned packages ship no unversioned symlinks, so name both tools.
- name: Check generation drift
run: make ebpf-drift CLANG=clang-${{ env.CLANG_VERSION }} LLVM_STRIP=llvm-strip-${{ env.CLANG_VERSION }}
- name: Install golangci-lint
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${{ env.GOLANGCI_LINT_VERSION }}
- name: Lint
run: |
export PATH=$(go env GOPATH)/bin:$PATH
make lint
- name: Unit tests
run: make test
- name: Race tests
run: make test-race
- name: Validate rules
run: |
./cmd/fibratus/fibratus rules validate \
--filters.rules.from-paths="rules/linux/*.yml" \
--filters.macros.from-paths="rules/linux/macros/*.yml"
# Fails, rather than skips, when the runner cannot host the backend, so a
# green integration run always means programs actually loaded.
- name: Probe eBPF prerequisites
run: sudo -E env "PATH=$PATH" go test -tags ebpf_integration -count=1 -run TestPrerequisitesAreMet -v ./internal/ebpf
- name: Privileged process source
run: sudo -E env "PATH=$PATH" make test-integration
- name: Package
run: make pkg
- uses: actions/upload-artifact@v4
with:
name: fibratus-linux-packages
path: build/pkg/*
Comment on lines +20 to +72
12 changes: 11 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# Binaries
cmd/fibratus/fibratus.exe
cmd/fibratus/fibratus.syso

cmd/fibratus/fibratus
cmd/systray/fibratus-systray.exe
cmd/systray/fibratus-systray.syso

# Resource message table
pkg/util/eventlog/mc/*
!pkg/util/eventlog/mc/gen.go

# Windows MSI package
build/msi/fibratus-*
build/msi/*.wixpdb
build/msi/*.msi

# IDE
.idea
.vscode

# Python bytecode cache
filaments/__pycache__

# Linux packages
build/pkg/
13 changes: 8 additions & 5 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: "2"
run:
build-tags:
- cap
- filament
# run:
# build-tags:
# - cap
# - filament

linters:
default: none
Expand Down Expand Up @@ -43,7 +43,7 @@ linters:
path: pkg/util/ports/iana_ports.go
- linters:
- goconst
path: pkg/event/flags.go
path: pkg/event/flags_windows.go
- linters:
- goconst
path: pkg/filter/ql/functions/(.+)\.go
Expand All @@ -56,6 +56,9 @@ linters:
- linters:
- goconst
path: pkg/filter/fields/fields_windows.go
- linters:
- goconst
path: pkg/filter/fields/defs_windows.go
- linters:
- goconst
path: cmd/fibratus/app/list/list.go
Expand Down
155 changes: 155 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
.DEFAULT_GOAL := build

SHELL := /bin/bash
.SHELLFLAGS := -euo pipefail -c

BPF2GO_VERSION := v0.20.0
GOLANGCI_LINT_VERSION := v2.9.0
NFPM_VERSION := v2.43.0

# The committed objects are byte-compared in CI, and clang encodes its version
# into BTF, so generating with a different major produces a spurious diff.
CLANG_VERSION := 18

# The generated objects target x86-64 and the runtime refuses other
# architectures, so building the binary pins the same one.
TARGET_ARCH ?= amd64

# Specifies a list of build flags
TAGS ?=

BPF_DIR := internal/ebpf
BPF_OUT := $(BPF_DIR)/bpf

CLANG ?= clang
LLVM_STRIP ?= llvm-strip
GO ?= go
GOFMT ?= gofmt
BPF2GO ?= go run github.com/cilium/ebpf/cmd/bpf2go@$(BPF2GO_VERSION)

BPF_FLAGS := \
-go-package bpf \
-output-dir $(BPF_OUT) \
-cc $(CLANG) \
-strip $(LLVM_STRIP) \
-target bpfel,bpfeb \
-tags linux

# Production headers first; spike/c is only the vmlinux.h fallback.
BPF_CFLAGS := \
-I./$(BPF_DIR)/c \
-I./$(BPF_DIR)/c/common \
-I./$(BPF_DIR)/spike/c \
-O2 \
-g \
-D__TARGET_ARCH_x86

# Find all eBPF sources.
BPF_SOURCES := $(wildcard $(BPF_DIR)/c/*.bpf.c)
BPF_NAMES := $(patsubst $(BPF_DIR)/c/%.bpf.c,%,$(BPF_SOURCES))
BPF_TARGETS := $(foreach name,$(BPF_NAMES), \
$(BPF_OUT)/$(name)_bpfel.go \
$(BPF_OUT)/$(name)_bpfeb.go)

titlecase = $(shell printf '%s' '$(1)' | awk '{print toupper(substr($$0,1,1)) substr($$0,2)}')

.PHONY: ebpf
ebpf: check-clang $(BPF_TARGETS)
$(BPF_OUT)/%_bpfel.go $(BPF_OUT)/%_bpfeb.go &: $(BPF_DIR)/c/%.bpf.c
$(BPF2GO) $(BPF_FLAGS) -output-stem $* $(call titlecase,$*) $(BPF_DIR)/c/$*.bpf.c -- $(BPF_CFLAGS)

.PHONY: check-clang
check-clang:
@command -v $(CLANG) >/dev/null 2>&1 || { \
echo "$(CLANG) not found. Generating the eBPF objects needs clang $(CLANG_VERSION)."; \
exit 1; \
}
@command -v $(LLVM_STRIP) >/dev/null 2>&1 || { \
echo "$(LLVM_STRIP) not found. Versioned llvm packages ship llvm-strip-$(CLANG_VERSION)"; \
echo "without the unversioned name bpf2go looks for."; \
echo "Point LLVM_STRIP at it, e.g. make ebpf LLVM_STRIP=llvm-strip-$(CLANG_VERSION)."; \
exit 1; \
}
@have=$$($(CLANG) --version | sed -n 's/.*clang version \([0-9]*\).*/\1/p' | head -1); \
if [ "$$have" != "$(CLANG_VERSION)" ]; then \
echo "clang $$have found but the committed objects were generated with $(CLANG_VERSION)."; \
echo "Regenerating with another major rewrites every object and fails ebpf-drift."; \
echo "Point CLANG at the right binary, e.g. make ebpf CLANG=clang-$(CLANG_VERSION)."; \
exit 1; \
fi

# Regenerating must be reproducible: same sources and same clang, same bytes.
.PHONY: ebpf-drift
ebpf-drift:
$(MAKE) -B ebpf
git diff --exit-code -- $(BPF_OUT)

ifeq ($(strip $(TAGS)),)
BUILD_TAGS :=
else
BUILD_TAGS := -tags $(TAGS)
endif

# Builds from the committed objects alone, so a fresh checkout needs no clang
# and no kernel headers. Naming the target pair keeps this buildable from a
# developer machine that is neither, which is the cheapest way to prove it.
.PHONY: build
build:
GOOS=linux GOARCH=$(TARGET_ARCH) $(GO) build $(BUILD_TAGS) -o ./cmd/fibratus/fibratus ./cmd/fibratus/

.PHONY: fmt
fmt:
$(GOFMT) -e -s -l -w pkg cmd internal

TEST_PKGS := \
./internal/ebpf \
./internal/bootstrap \
./pkg/api \
./pkg/config \
./pkg/event \
./pkg/filter \
./pkg/ps \
./pkg/rules \
./pkg/rules/action \
./pkg/util/signals

.PHONY: test
test:
$(GO) test $(TEST_PKGS)

.PHONY: test-race
test-race:
$(GO) test -race $(TEST_PKGS)

# Needs a 5.9+ kernel with runtime BTF, and root to load and attach.
.PHONY: test-integration
test-integration:
$(GO) test -tags ebpf_integration -count=1 ./internal/ebpf

# Narrower than TEST_PKGS on purpose. Packages outside this set carry helpers
# that only Windows reaches, so `unused` reports them on every Linux run and
# there is nothing to fix without moving Windows code around.
LINT_PKGS := \
./internal/ebpf/... \
./internal/bootstrap/... \
./pkg/filter/... \
./pkg/rules/...

.PHONY: lint
lint:
golangci-lint run $(LINT_PKGS)

VERSION ?= 0.0.0
PKG_DIR := build/pkg
NFPM ?= go run github.com/goreleaser/nfpm/v2/cmd/nfpm@$(NFPM_VERSION)

.PHONY: pkg
pkg: build
@mkdir -p $(PKG_DIR)
VERSION=$(VERSION) $(NFPM) package --config build/linux/nfpm.yaml --packager deb --target $(PKG_DIR)
VERSION=$(VERSION) $(NFPM) package --config build/linux/nfpm.yaml --packager rpm --target $(PKG_DIR)

.PHONY: clean
clean:
rm -f cmd/fibratus/fibratus
rm -rf $(PKG_DIR)
44 changes: 44 additions & 0 deletions build/linux/fibratus.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[Unit]
Description=Fibratus
Documentation=https://www.fibratus.io
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/fibratus run
Restart=on-failure
RestartSec=5s

# Fibratus starts as root because attaching a syscall tracepoint reads its id
# from /sys/kernel/tracing, which is root-only on stock distributions. The
# bounding set is what actually constrains it: everything below is dropped, so
# the process keeps only what the backend and the kill action need.
#
# CAP_BPF load programs, create and update maps
# CAP_PERFMON attach to tracepoints
# CAP_SYS_PTRACE read /proc/<pid>/exe and cmdline of other users' processes
# CAP_KILL signal a target, needed only by the kill rule action
#
# CAP_BPF and CAP_PERFMON were split out of CAP_SYS_ADMIN in 5.8. On a kernel
# that predates the split, replace both with CAP_SYS_ADMIN.
CapabilityBoundingSet=CAP_BPF CAP_PERFMON CAP_SYS_PTRACE CAP_KILL
AmbientCapabilities=CAP_BPF CAP_PERFMON CAP_SYS_PTRACE CAP_KILL
NoNewPrivileges=yes

# full rather than strict: strict would also mount /run read-only and the API
# socket lives there.
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
LockPersonality=yes

# Process enrichment reads other processes' procfs entries, so this must stay
# permissive. Hiding them would silently empty ps.exe and ps.cmdline.
ProtectProc=default

[Install]
WantedBy=multi-user.target
46 changes: 46 additions & 0 deletions build/linux/nfpm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: fibratus
arch: amd64
platform: linux
version: ${VERSION}
section: admin
priority: optional
maintainer: Nedim Sabic Sabic <https://fibratus.io>
description: |
Security sensor for realtime threat detection and protection
vendor: Fibratus
homepage: https://fibratus.io
license: Apache-2.0

# The BPF objects are embedded in the binary at compile time, so there is
# nothing to ship alongside it.
contents:
- src: ./cmd/fibratus/fibratus
dst: /usr/bin/fibratus

- src: ./configs/fibratus-linux.yml
dst: /etc/fibratus/fibratus.yml
type: config|noreplace

- src: ./rules/linux/*.yml
dst: /etc/fibratus/rules/

- src: ./rules/linux/macros/macros.yml
dst: /etc/fibratus/rules/macros/macros.yml

- src: ./build/linux/fibratus.service
dst: /lib/systemd/system/fibratus.service

overrides:
rpm:
contents:
- src: ./cmd/fibratus/fibratus
dst: /usr/bin/fibratus
- src: ./configs/fibratus-linux.yml
dst: /etc/fibratus/fibratus.yml
type: config|noreplace
- src: ./rules/linux/*.yml
dst: /etc/fibratus/rules/
- src: ./rules/linux/macros/macros.yml
dst: /etc/fibratus/rules/macros/macros.yml
- src: ./build/linux/fibratus.service
dst: /usr/lib/systemd/system/fibratus.service
Loading
Loading