Repository navigation
feat(rules): Add Linux detection rules and a signal-based kill action - #735
Merged
rabbitstack merged 4 commits intoSep 21, 2026
Merged
Conversation
Revalidate PID plus start boot time from /proc before SIGKILL so a reused PID cannot be terminated.
… connect Ship an initial Linux detection set in a dedicated tree so Windows packaging and rule validation stay on the Windows catalog.
Prove Linux types are indexed, shipped rules fire, sequence lifecycle matches, and shared field fixtures compile on both platforms.
The kill, ptrace, and process_vm target was truncated through uint32 and widened as unsigned, so kill(-1) surfaced as 4294967295. Carry the argument as a signed value and expose ps.target.pid and mem.target.pid as signed, so a process group or broadcast target stays distinguishable from a process identifier.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of this PR / why it is needed?
Linux capture emits process, file, network, memory and signal events, and the filter catalog can express them, but nothing acts on them yet. The rule engine had no Linux ruleset to load and the kill action returned "not implemented". This PR closes that gap so a Linux deployment can detect and respond.
It ships three things:
A signal-based kill action. Terminating by PID alone is unsafe because the identifier can be recycled between the moment a rule matches and the moment the signal is delivered. The action opens a pidfd first, which pins the identifier for the lifetime of the descriptor, then compares the live
/proc/<pid>/statstart time against the start boot time captured on the event, and only then delivers SIGKILL throughpidfd_send_signal. A process that has already exited is treated as success, mirroring the Windows behaviour onERROR_INVALID_PARAMETER. A mismatched start time refuses to signal and reports why.pidfd_openarrived in 5.3, below the runtime floor the loader already enforces.action.Killnow takes theActionContextrather than a pid slice, because the Linux implementation needs the process start time that only the events carry. The Windows implementation keeps resolving pids exactly as before. This also removes aMustGetPidcall from the engine's logging path, which could panic on an event that carries no pid parameter.An initial Linux ruleset. Four rules covering execution from world-writable directories, ptrace attach, SIGKILL against another process, and a script interpreter opening an outbound connection after execution, plus the macros they share. They live under
rules/linux/because every rule underrules/is compiled against the Windows event catalog byfibratus rules validateduring packaging, and Linux event names would fail there. The MSI packaging step excludes the directory for the same reason.A signed target identifier. The
kill,ptraceandprocess_vm_*target was truncated throughuint32and widened as unsigned, sokill(-1, SIGKILL)was recorded as4294967295.pid_tis signed and its sign selects the scope of the signal, so the value is now carried signed andps.target.pidandmem.target.pidare exposed as signed. Process group and broadcast targets stay distinguishable from a process identifier, andps.target.pid < 0selects them. Note that the filter lexer does not accept negative literals, sops.target.pid = -1will not parse; the relational form is the one to use, and the field documentation says so.What type of change does this PR introduce?
/kind feature (non-breaking change which adds functionality)
/kind bug-fix (non-breaking change which fixes an issue)
Any specific area of the project related to this PR?
/area rule-engine
/area rules
/area event
/area tests
Special notes for the reviewer
The engine already indexed Linux event types and categories through
NameToTypes, so no change was needed there. The tests assert it rather than assuming it.Two decisions worth a second opinion:
execvemacro requiresevt.retval = 0, so a failed execution does not alert. Theptrace,killandconnectmacros deliberately do not gate on the return value, because a denied ptrace attach or a refused connection carries the same intent as a successful one. Each macro says which behaviour it has.matchesrather thanimatches. Linux paths are case-sensitive and case-insensitive globbing would widen the rule beyond what it claims.The Linux workflow now runs
make test, so the package list has a single definition shared with local runs, and it gainedpkg/rules/action,pkg/rules,pkg/filterandpkg/config. Arules validatestep runs the built binary against the shipped Linux ruleset and reports no warnings.Verified on Linux with the full unit suite, including an end-to-end test that spawns a real process, terminates it through the pidfd path, and asserts a process whose captured start time disagrees is left alone.
GOOS=windows go build ./...and the Windows rule packaging path are unaffected.Does this PR introduce a user-facing change?
The kill action works on Linux, where it sends SIGKILL after confirming the target is still the process the rule matched on. Linux installations gain an initial ruleset covering execution from world-writable directories, ptrace attach, SIGKILL against another process, and interpreter outbound connections.
ps.target.pidandmem.target.pidare now signed. Filters comparing them against a process identifier are unaffected; a target that denotes a process group or a broadcast now reads as a negative value instead of a large unsigned one.