Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/linux-port.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ jobs:
make -B ebpf
git diff --exit-code -- internal/ebpf/bpf
- name: Unit tests
run: go test ./internal/ebpf ./internal/bootstrap ./pkg/event ./pkg/ps ./pkg/api ./pkg/util/signals
run: make test
- name: Validate rules
run: |
make build
./cmd/fibratus/fibratus rules validate \
--filters.rules.from-paths="rules/linux/*.yml" \
--filters.macros.from-paths="rules/linux/macros/*.yml"
- name: Privileged process source
run: sudo -E env "PATH=$PATH" go test -tags ebpf_integration -count=1 ./internal/ebpf
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,21 @@ build:
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 ./internal/ebpf ./internal/bootstrap ./pkg/event ./pkg/ps ./pkg/api ./pkg/util/signals ./pkg/filter ./pkg/rules
$(GO) test $(TEST_PKGS)

.PHONY: clean
clean:
Expand Down
6 changes: 3 additions & 3 deletions internal/ebpf/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,16 @@ func (r rawEvent) toEvent() *event.Event {
evt.Params.Append(params.FD, params.Int64, int64(r.Arg3))
evt.Params.Append(params.MmapOffset, params.Uint64, r.Arg0)
case event.ProcessVMRead, event.ProcessVMWrite:
evt.Params.Append(params.TargetProcessID, params.PID, uint64(uint32(r.Arg0)))
evt.Params.Append(params.TargetProcessID, params.Int64, int64(int32(r.Arg0)))
evt.Params.Append(params.MemBaseAddress, params.Address, r.Arg2)
evt.Params.Append(params.MemRegionSize, params.Uint64, r.Arg3)
evt.Params.Append(params.MmapFlags, params.Uint64, r.Flags)
case event.Kill:
evt.Params.Append(params.TargetProcessID, params.PID, uint64(uint32(r.Arg0)))
evt.Params.Append(params.TargetProcessID, params.Int64, int64(int32(r.Arg0)))
evt.Params.Append(params.Signal, params.Int32, int32(r.Arg1))
case event.Ptrace:
evt.Params.Append(params.PtraceRequest, params.Int64, int64(r.Arg0))
evt.Params.Append(params.TargetProcessID, params.PID, uint64(uint32(r.Arg1)))
evt.Params.Append(params.TargetProcessID, params.Int64, int64(int32(r.Arg1)))
evt.Params.Append(params.PtraceAddr, params.Address, r.Arg2)
evt.Params.Append(params.PtraceData, params.Uint64, r.Arg3)
case event.Prctl:
Expand Down
36 changes: 36 additions & 0 deletions internal/ebpf/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,39 @@ func TestSucceededHelper(t *testing.T) {
evt.Params.Append(params.Retval, params.Int64, int64(-2))
assert.False(t, succeeded(evt))
}

// The first argument of kill is a pid_t whose sign selects the scope of the
// signal, so it must survive the conversion to an event parameter.
func TestSignalTargetKeepsPidSign(t *testing.T) {
var tests = []struct {
name string
arg0 uint64
want int64
}{
{"single process", 4242, 4242},
{"caller process group", 0, 0},
{"every permitted process", uint64(^uint32(0)), -1},
{"process group", uint64(uint32(0xFFFFEF6E)), -4242},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
evt := rawEvent{Type: uint32(event.Kill), Arg0: tt.arg0, Arg1: 9}.toEvent()
target, err := evt.Params.GetInt64(params.TargetProcessID)
require.NoError(t, err)
assert.Equal(t, tt.want, target)
})
}
}

func TestPtraceAndProcessVMTargetsAreSigned(t *testing.T) {
ptrace := rawEvent{Type: uint32(event.Ptrace), Arg0: 16, Arg1: 4242}.toEvent()
target, err := ptrace.Params.GetInt64(params.TargetProcessID)
require.NoError(t, err)
assert.Equal(t, int64(4242), target)

vmread := rawEvent{Type: uint32(event.ProcessVMRead), Arg0: 4242}.toEvent()
target, err = vmread.Params.GetInt64(params.TargetProcessID)
require.NoError(t, err)
assert.Equal(t, int64(4242), target)
}
4 changes: 2 additions & 2 deletions make.bat
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ copy /y ".\configs\fibratus.yml" "%RELEASE_DIR%\Config\fibratus.yml"
copy /y ".\pkg\outputs\eventlog\mc\fibratus.dll" "%RELEASE_DIR%\fibratus.dll"

robocopy ".\filaments" "%RELEASE_DIR%\Filaments" /E /S /XF *.md /XD __pycache__ .idea
robocopy ".\rules" "%RELEASE_DIR%\Rules" /E /S /XF *.md *.png
robocopy ".\rules" "%RELEASE_DIR%\Rules" /E /S /XF *.md *.png /XD linux

:: Download the embedded Python distribution
echo Downloading Python %PYTHON_VER%...
Expand Down Expand Up @@ -180,7 +180,7 @@ copy /y ".\cmd\fibratus\fibratus.ico" "%RELEASE_DIR%\Bin"
copy /y ".\configs\fibratus.yml" "%RELEASE_DIR%\Config\fibratus.yml"
copy /y ".\pkg\outputs\eventlog\mc\fibratus.dll" "%RELEASE_DIR%\fibratus.dll"

robocopy ".\rules" "%RELEASE_DIR%\Rules" /E /S /XF *.md *.png
robocopy ".\rules" "%RELEASE_DIR%\Rules" /E /S /XF *.md *.png /XD linux

:: Copy Debug Help DLL
copy %SystemRoot%\System32\dbghelp.dll "%RELEASE_DIR%\Bin"
Expand Down
4 changes: 2 additions & 2 deletions pkg/filter/accessor_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func (a *psAccessor) Get(f Field, e *event.Event) (params.Value, error) {
}
return int64(sig), nil
case fields.PsTargetPID:
return e.Params.GetUint64(params.TargetProcessID)
return e.Params.GetInt64(params.TargetProcessID)
case fields.PsPtraceRequest:
return e.Params.GetInt64(params.PtraceRequest)
case fields.PsPrctlOption:
Expand Down Expand Up @@ -308,7 +308,7 @@ func (*memAccessor) Get(f Field, e *event.Event) (params.Value, error) {
case fields.MemMmapOffset:
return e.Params.GetUint64(params.MmapOffset)
case fields.MemTargetPID:
return e.Params.GetUint64(params.TargetProcessID)
return e.Params.GetInt64(params.TargetProcessID)
default:
return nil, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/filter/fields/defs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var fields = platformFields(map[Field]FieldInfo{
PsParentUsername: {PsParentUsername, "parent process username", platformString(), []string{"ps.parent.username = 'root'"}, nil, nil},
PsParentEnvs: {PsParentEnvs, "parent process environment variables", params.Slice, []string{"ps.parent.envs in ('PATH:/usr/bin')"}, nil, nil},
PsSignal: {PsSignal, "POSIX signal number", params.Int64, []string{"ps.signal = 9"}, nil, nil},
PsTargetPID: {PsTargetPID, "target process identifier of kill, ptrace, or process_vm operations", params.Uint64, []string{"ps.target.pid = 4242"}, nil, nil},
PsTargetPID: {PsTargetPID, "target process identifier of kill, ptrace, or process_vm operations. Signal targets keep the pid_t sign, where zero is the caller process group, -1 is every permitted process, and any other negative value is the process group of its absolute value", params.Int64, []string{"ps.target.pid = 4242", "ps.target.pid < 0"}, nil, nil},
PsPtraceRequest: {PsPtraceRequest, "ptrace request code", params.Int64, []string{"ps.ptrace.request = 16"}, nil, nil},
PsPrctlOption: {PsPrctlOption, "prctl option code", params.Int64, []string{"ps.prctl.option = 15"}, nil, nil},
PsCloneFlags: {PsCloneFlags, "clone flags bitmask", params.Uint64, []string{"ps.clone_flags = 0"}, nil, nil},
Expand All @@ -69,7 +69,7 @@ var fields = platformFields(map[Field]FieldInfo{
MemMmapFlags: {MemMmapFlags, "mmap flags bitmask", params.Uint64, []string{"mem.mmap.flags = 1"}, nil, nil},
MemMmapFD: {MemMmapFD, "file descriptor backing a mapping", params.Int64, []string{"mem.mmap.fd = 3"}, nil, nil},
MemMmapOffset: {MemMmapOffset, "file offset of a memory mapping", params.Uint64, []string{"mem.mmap.offset = 0"}, nil, nil},
MemTargetPID: {MemTargetPID, "target process identifier of a process_vm operation", params.Uint64, []string{"mem.target.pid = 4242"}, nil, nil},
MemTargetPID: {MemTargetPID, "target process identifier of a process_vm operation", params.Int64, []string{"mem.target.pid = 4242"}, nil, nil},
ThreadTID: {ThreadTID, "thread identifier", params.Uint64, []string{"thread.tid = 1024"}, nil, nil},
ThreadPID: {ThreadPID, "thread group identifier of the thread", params.Uint64, []string{"thread.pid = 1024"}, nil, nil},
})
40 changes: 34 additions & 6 deletions pkg/filter/filter_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,34 @@ func TestProcFilter(t *testing.T) {
PID: 4242,
PS: ps,
Params: event.Params{
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(99)},
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(99)},
params.Signal: {Name: params.Signal, Type: params.Int32, Value: int32(9)},
params.Retval: {Name: params.Retval, Type: params.Int64, Value: int64(0)},
},
}
// kill accepts a pid_t whose sign selects the scope of the signal
broadcastKill := &event.Event{
Type: event.Kill,
Category: event.Process,
Name: "kill",
PID: 4242,
PS: ps,
Params: event.Params{
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(-1)},
params.Signal: {Name: params.Signal, Type: params.Int32, Value: int32(9)},
},
}
groupKill := &event.Event{
Type: event.Kill,
Category: event.Process,
Name: "kill",
PID: 4242,
PS: ps,
Params: event.Params{
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(-4242)},
params.Signal: {Name: params.Signal, Type: params.Int32, Value: int32(9)},
},
}
ptrace := &event.Event{
Type: event.Ptrace,
Category: event.Process,
Expand All @@ -217,7 +240,7 @@ func TestProcFilter(t *testing.T) {
PS: ps,
Params: event.Params{
params.PtraceRequest: {Name: params.PtraceRequest, Type: params.Int64, Value: int64(16)},
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(99)},
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(99)},
},
}
prctl := &event.Event{
Expand Down Expand Up @@ -272,6 +295,11 @@ func TestProcFilter(t *testing.T) {
{execve, `evt.arg[exe] = '/bin/bash'`, true},
{kill, `ps.signal = 9`, true},
{kill, `ps.target.pid = 99`, true},
{kill, `ps.target.pid > 0`, true},
{kill, `ps.target.pid < 0`, false},
{broadcastKill, `ps.target.pid < 0`, true},
{broadcastKill, `ps.target.pid > 0`, false},
{groupKill, `ps.target.pid < 0`, true},
{ptrace, `ps.ptrace.request = 16`, true},
{ptrace, `ps.target.pid = 99`, true},
{prctl, `ps.prctl.option = 15`, true},
Expand Down Expand Up @@ -413,7 +441,7 @@ func TestMemFilter(t *testing.T) {
Name: "process_vm_readv",
PID: 4242,
Params: event.Params{
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(99)},
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(99)},
params.MemBaseAddress: {Name: params.MemBaseAddress, Type: params.Address, Value: uint64(4096)},
params.MemRegionSize: {Name: params.MemRegionSize, Type: params.Uint64, Value: uint64(16)},
},
Expand All @@ -424,7 +452,7 @@ func TestMemFilter(t *testing.T) {
Name: "process_vm_writev",
PID: 4242,
Params: event.Params{
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(77)},
params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(77)},
params.MemBaseAddress: {Name: params.MemBaseAddress, Type: params.Address, Value: uint64(4096)},
},
}
Expand Down Expand Up @@ -541,8 +569,8 @@ func TestEveryLinuxEventType(t *testing.T) {
{&event.Event{Type: event.Connect, Category: event.Net, Name: "connect", PS: ps, Params: event.Params{params.NetDport: {Name: params.NetDport, Type: params.Port, Value: uint16(443)}}}, `net.dport = 443`},
{&event.Event{Type: event.Accept, Category: event.Net, Name: "accept", PS: ps, Params: event.Params{params.NetSport: {Name: params.NetSport, Type: params.Port, Value: uint16(80)}}}, `net.sport = 80`},
{&event.Event{Type: event.Mmap, Category: event.Mem, Name: "mmap", PS: ps, Params: event.Params{params.MemRegionSize: {Name: params.MemRegionSize, Type: params.Uint64, Value: uint64(4096)}}}, `mem.size = 4096`},
{&event.Event{Type: event.ProcessVMRead, Category: event.Mem, Name: "process_vm_readv", PS: ps, Params: event.Params{params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(9)}}}, `mem.target.pid = 9`},
{&event.Event{Type: event.ProcessVMWrite, Category: event.Mem, Name: "process_vm_writev", PS: ps, Params: event.Params{params.TargetProcessID: {Name: params.TargetProcessID, Type: params.PID, Value: uint64(8)}}}, `mem.target.pid = 8`},
{&event.Event{Type: event.ProcessVMRead, Category: event.Mem, Name: "process_vm_readv", PS: ps, Params: event.Params{params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(9)}}}, `mem.target.pid = 9`},
{&event.Event{Type: event.ProcessVMWrite, Category: event.Mem, Name: "process_vm_writev", PS: ps, Params: event.Params{params.TargetProcessID: {Name: params.TargetProcessID, Type: params.Int64, Value: int64(8)}}}, `mem.target.pid = 8`},
{&event.Event{Type: event.Kill, Category: event.Process, Name: "kill", PS: ps, Params: event.Params{params.Signal: {Name: params.Signal, Type: params.Int32, Value: int32(9)}}}, `ps.signal = 9`},
{&event.Event{Type: event.Ptrace, Category: event.Process, Name: "ptrace", PS: ps, Params: event.Params{params.PtraceRequest: {Name: params.PtraceRequest, Type: params.Int64, Value: int64(16)}}}, `ps.ptrace.request = 16`},
{&event.Event{Type: event.Prctl, Category: event.Process, Name: "prctl", PS: ps, Params: event.Params{params.PrctlOption: {Name: params.PrctlOption, Type: params.Int64, Value: int64(15)}}}, `ps.prctl.option = 15`},
Expand Down
7 changes: 7 additions & 0 deletions pkg/rules/_fixtures/kill_action_linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: Kill process executed from a temporary directory
id: 33333333-3333-4333-8333-333333333333
version: 1.0.0
condition: evt.name = 'execve' and ps.exe imatches '/tmp/*'
action:
- name: kill
min-engine-version: 3.0.0
5 changes: 5 additions & 0 deletions pkg/rules/_fixtures/shared/semantic_net.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: match destination port
id: 22222222-2222-4222-8222-222222222222
version: 1.0.0
condition: evt.category = 'net' and net.dport = 443
min-engine-version: 2.0.0
5 changes: 5 additions & 0 deletions pkg/rules/_fixtures/shared/semantic_process.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: match process category
id: 11111111-1111-4111-8111-111111111111
version: 1.0.0
condition: evt.category = 'process'
min-engine-version: 2.0.0
Loading
Loading