From 68f174554782b1ce379473260ca10ad0b4b07c67 Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 19 Nov 2024 09:39:29 +0100 Subject: [PATCH 1/7] chore(decl): abstract process creation Abstract process creation through a new process package. Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku --- pkg/process/doc.go | 17 +++ pkg/process/process.go | 246 +++++++++++++++++++++++++++++++++++ pkg/test/runner/host/host.go | 116 ++++------------- 3 files changed, 288 insertions(+), 91 deletions(-) create mode 100644 pkg/process/doc.go create mode 100644 pkg/process/process.go diff --git a/pkg/process/doc.go b/pkg/process/doc.go new file mode 100644 index 00000000..7d59964a --- /dev/null +++ b/pkg/process/doc.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package process provides the Process abstraction, allowing to define and interact with a new OS process. +package process diff --git a/pkg/process/process.go b/pkg/process/process.go new file mode 100644 index 00000000..035acb3c --- /dev/null +++ b/pkg/process/process.go @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package process + +import ( + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "regexp" + + "github.com/go-logr/logr" + "golang.org/x/sys/unix" + + "github.com/falcosecurity/event-generator/pkg/random" +) + +// Process represent an OS process. +type Process struct { + logger logr.Logger + // command is the command the process is associated with. + command string + // simExePath is the "simulated" executable path. This sets the executable path accessible through + // `readlink -f /proc/ Date: Tue, 19 Nov 2024 10:08:43 +0100 Subject: [PATCH 2/7] feat(decl/loader): add process resource YAML definition Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku --- pkg/test/loader/loader.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/test/loader/loader.go b/pkg/test/loader/loader.go index d0410e80..cfba584c 100644 --- a/pkg/test/loader/loader.go +++ b/pkg/test/loader/loader.go @@ -189,6 +189,8 @@ func (r *TestResource) UnmarshalYAML(node *yaml.Node) error { spec = &TestResourceClientServerSpec{} case TestResourceTypeFD: spec = &TestResourceFDSpec{} + case TestResourceTypeProcess: + spec = &TestResourceProcessSpec{} default: panic(fmt.Sprintf("unknown test resource type %q", decodedType)) } @@ -217,6 +219,12 @@ func (r TestResource) MarshalYAML() (interface{}, error) { }{Type: resourceType, Name: r.Name, Spec: r.Spec.(*TestResourceClientServerSpec)}, nil case TestResourceTypeFD: return r.marshalFD() + case TestResourceTypeProcess: + return struct { + Type TestResourceType `yaml:"type"` + Name string `yaml:"name"` + Spec *TestResourceProcessSpec `yaml:"spec,inline"` + }{Type: resourceType, Name: r.Name, Spec: r.Spec.(*TestResourceProcessSpec)}, nil default: return nil, fmt.Errorf("unknown test resource type %q", resourceType) } @@ -301,6 +309,8 @@ const ( TestResourceTypeClientServer TestResourceType = "clientServer" // TestResourceTypeFD specifies that the resource creates a file descriptor. TestResourceTypeFD TestResourceType = "fd" + // TestResourceTypeProcess specifies that the resource creates a process. + TestResourceTypeProcess TestResourceType = "process" ) // UnmarshalYAML populates the TestResourceType instance by unmarshalling the content of the provided YAML node. @@ -313,6 +323,7 @@ func (t *TestResourceType) UnmarshalYAML(node *yaml.Node) error { switch TestResourceType(value) { case TestResourceTypeClientServer: case TestResourceTypeFD: + case TestResourceTypeProcess: default: return fmt.Errorf("unknown test step type %q", value) } @@ -495,6 +506,23 @@ type TestResourceFDMemSpec struct { FileName string `yaml:"fileName" validate:"required"` } +// TestResourceProcessSpec describes a process test resource. +type TestResourceProcessSpec struct { + // ExePath is the executable path. If omitted, it is randomly generated. + ExePath *string `yaml:"exePath" validate:"omitempty,min=1"` + // Args is a string containing the space-separated list of command line arguments. If a single argument contains + // spaces, the entire argument must be quoted in order to not be considered as multiple arguments. If omitted, it + // defaults to "". + Args *string `yaml:"args,omitempty" validate:"omitempty,min=1"` + // Exe is the argument in position 0 (a.k.a. argv[0]) of the process. If omitted, it defaults to Name if this is + // specified; otherwise, it defaults to filepath.Base(ExePath). + Exe *string `yaml:"exe,omitempty" validate:"omitempty,min=1"` + // Name is the process name. If omitted, it defaults to filepath.Base(ExePath). + Name *string `yaml:"procName,omitempty" validate:"omitempty,min=1"` + // Env is the set of environment variables that must be provided to the process (in addition to the default ones). + Env map[string]string `yaml:"env,omitempty" validate:"omitempty,min=1"` +} + // TestStep describes a test step. type TestStep struct { Type TestStepType `yaml:"type" validate:"-"` From 2946b6ba495f6d8bdda212a05983e2250974eb42 Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 19 Nov 2024 10:09:58 +0100 Subject: [PATCH 3/7] feat(decl/resources): add process test resource Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku Date: Tue, 19 Nov 2024 10:11:41 +0100 Subject: [PATCH 4/7] docs(decl/write): fix typo in write system call test step comment Signed-off-by: Leonardo Di Giovanna --- pkg/test/step/syscall/write/write.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/test/step/syscall/write/write.go b/pkg/test/step/syscall/write/write.go index 686683dd..c2729716 100644 --- a/pkg/test/step/syscall/write/write.go +++ b/pkg/test/step/syscall/write/write.go @@ -42,7 +42,7 @@ type writeSyscall struct { func New(name string, rawArgs map[string]string, fieldBindings []*step.FieldBinding) (syscall.Syscall, error) { w := &writeSyscall{} - // s.args.Len defaults to the buffer length at run time, if unbound. + // w.args.Len defaults to the buffer length at run time, if unbound. argsContainer := reflect.ValueOf(&w.args).Elem() bindOnlyArgsContainer := reflect.ValueOf(&w.bindOnlyArgs).Elem() retValContainer := reflect.ValueOf(w).Elem() From 2238525651d820bdc8169f937c6d86a1b83cea97 Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 19 Nov 2024 10:18:23 +0100 Subject: [PATCH 5/7] style(decl/loader): change switch style Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku --- pkg/test/loader/loader.go | 44 ++++++++------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/pkg/test/loader/loader.go b/pkg/test/loader/loader.go index cfba584c..9660f62e 100644 --- a/pkg/test/loader/loader.go +++ b/pkg/test/loader/loader.go @@ -321,9 +321,7 @@ func (t *TestResourceType) UnmarshalYAML(node *yaml.Node) error { } switch TestResourceType(value) { - case TestResourceTypeClientServer: - case TestResourceTypeFD: - case TestResourceTypeProcess: + case TestResourceTypeClientServer, TestResourceTypeFD, TestResourceTypeProcess: default: return fmt.Errorf("unknown test step type %q", value) } @@ -369,11 +367,8 @@ func (t *TestResourceClientServerL4Proto) UnmarshalYAML(node *yaml.Node) error { } switch TestResourceClientServerL4Proto(value) { - case TestResourceClientServerL4ProtoUDP4: - case TestResourceClientServerL4ProtoUDP6: - case TestResourceClientServerL4ProtoTCP4: - case TestResourceClientServerL4ProtoTCP6: - case TestResourceClientServerL4ProtoUnix: + case TestResourceClientServerL4ProtoUDP4, TestResourceClientServerL4ProtoUDP6, TestResourceClientServerL4ProtoTCP4, + TestResourceClientServerL4ProtoTCP6, TestResourceClientServerL4ProtoUnix: default: return fmt.Errorf("unknown clientServer test resource l4 proto %q", value) } @@ -460,14 +455,9 @@ func (t *TestResourceFDSubtype) UnmarshalYAML(node *yaml.Node) error { } switch TestResourceFDSubtype(value) { - case TestResourceFDSubtypeFile: - case TestResourceFDSubtypeDirectory: - case TestResourceFDSubtypePipe: - case TestResourceFDSubtypeEvent: - case TestResourceFDSubtypeSignal: - case TestResourceFDSubtypeEpoll: - case TestResourceFDSubtypeInotify: - case TestResourceFDSubtypeMem: + case TestResourceFDSubtypeFile, TestResourceFDSubtypeDirectory, TestResourceFDSubtypePipe, + TestResourceFDSubtypeEvent, TestResourceFDSubtypeSignal, TestResourceFDSubtypeEpoll, + TestResourceFDSubtypeInotify, TestResourceFDSubtypeMem: default: return fmt.Errorf("unknown fd test resource subtype %q", value) } @@ -652,8 +642,6 @@ func (s *TestStepSyscallSpec) fieldBindings() []*TestStepFieldBinding { type SyscallName string const ( - // SyscallNameUndefined specifies that the system call name is not defined. - SyscallNameUndefined SyscallName = "undefined" // SyscallNameWrite specifies the name of the write system call. SyscallNameWrite SyscallName = "write" // SyscallNameRead specifies the name of the read system call. @@ -697,23 +685,9 @@ func (s *SyscallName) UnmarshalYAML(node *yaml.Node) error { return err } switch SyscallName(value) { - case SyscallNameWrite: - case SyscallNameRead: - case SyscallNameOpen: - case SyscallNameOpenAt: - case SyscallNameOpenAt2: - case SyscallNameSymLink: - case SyscallNameSymLinkAt: - case SyscallNameLink: - case SyscallNameLinkAt: - case SyscallNameInitModule: - case SyscallNameFinitModule: - case SyscallNameDup: - case SyscallNameDup2: - case SyscallNameDup3: - case SyscallNameConnect: - case SyscallNameSocket: - case SyscallNameSendTo: + case SyscallNameWrite, SyscallNameRead, SyscallNameOpen, SyscallNameOpenAt, SyscallNameOpenAt2, SyscallNameSymLink, + SyscallNameSymLinkAt, SyscallNameLink, SyscallNameLinkAt, SyscallNameInitModule, SyscallNameFinitModule, + SyscallNameDup, SyscallNameDup2, SyscallNameDup3, SyscallNameConnect, SyscallNameSocket, SyscallNameSendTo: default: return fmt.Errorf("unknown syscall %q", value) } From 963e7f4679931aef0fabd744d4a78a95f7c3a1e5 Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 19 Nov 2024 10:32:14 +0100 Subject: [PATCH 6/7] cleanup(decl/syscalls): remove unused ret fields Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku --- pkg/test/step/syscall/finitmodule/finitmodule.go | 8 ++------ pkg/test/step/syscall/initmodule/initmodule.go | 8 ++------ pkg/test/step/syscall/link/link.go | 2 +- pkg/test/step/syscall/linkat/linkat.go | 2 +- pkg/test/step/syscall/sendto/sendto.go | 7 +------ pkg/test/step/syscall/symlink/symlink.go | 2 +- pkg/test/step/syscall/symlinkat/symlinkat.go | 2 +- 7 files changed, 9 insertions(+), 22 deletions(-) diff --git a/pkg/test/step/syscall/finitmodule/finitmodule.go b/pkg/test/step/syscall/finitmodule/finitmodule.go index 75d5d804..29ebd46a 100644 --- a/pkg/test/step/syscall/finitmodule/finitmodule.go +++ b/pkg/test/step/syscall/finitmodule/finitmodule.go @@ -36,7 +36,7 @@ type finitModuleSyscall struct { bindOnlyArgs struct { FD int `field_type:"fd"` } - Ret int + // Return value is neither set nor bindable. } // New creates a new finit_module system call test step. @@ -54,9 +54,5 @@ func New(name string, rawArgs map[string]string, } func (f *finitModuleSyscall) run(_ context.Context) error { - if err := unix.FinitModule(f.bindOnlyArgs.FD, f.args.ParamValues, f.args.Flags); err != nil { - return err - } - - return nil + return unix.FinitModule(f.bindOnlyArgs.FD, f.args.ParamValues, f.args.Flags) } diff --git a/pkg/test/step/syscall/initmodule/initmodule.go b/pkg/test/step/syscall/initmodule/initmodule.go index 835b53ce..3df9d006 100644 --- a/pkg/test/step/syscall/initmodule/initmodule.go +++ b/pkg/test/step/syscall/initmodule/initmodule.go @@ -34,7 +34,7 @@ type initModuleSyscall struct { } // bindOnlyArgs represents arguments that can only be provided by binding. bindOnlyArgs struct{} - Ret int + // Return value is neither set nor bindable. } // New creates a new init_module system call test step. @@ -51,9 +51,5 @@ func New(name string, rawArgs map[string]string, } func (i *initModuleSyscall) run(_ context.Context) error { - if err := unix.InitModule(i.args.ModuleImage, i.args.ParamValues); err != nil { - return err - } - - return nil + return unix.InitModule(i.args.ModuleImage, i.args.ParamValues) } diff --git a/pkg/test/step/syscall/link/link.go b/pkg/test/step/syscall/link/link.go index 5f3e94e7..59f1e85f 100644 --- a/pkg/test/step/syscall/link/link.go +++ b/pkg/test/step/syscall/link/link.go @@ -39,7 +39,7 @@ type linkSyscall struct { // bindOnlyArgs represents arguments that can only be provided by binding. bindOnlyArgs struct{} savedNewPath []byte - Ret int + // Return value is neither set nor bindable. } // New creates a new link system call test step. diff --git a/pkg/test/step/syscall/linkat/linkat.go b/pkg/test/step/syscall/linkat/linkat.go index ea2aa5d1..afc99ac3 100644 --- a/pkg/test/step/syscall/linkat/linkat.go +++ b/pkg/test/step/syscall/linkat/linkat.go @@ -41,7 +41,7 @@ type linkAtSyscall struct { NewDirFD int `field_type:"fd"` } savedNewPath []byte - Ret int + // Return value is neither set nor bindable. } // New creates a new linkat system call test step. diff --git a/pkg/test/step/syscall/sendto/sendto.go b/pkg/test/step/syscall/sendto/sendto.go index 0d57be54..ae57e2ef 100644 --- a/pkg/test/step/syscall/sendto/sendto.go +++ b/pkg/test/step/syscall/sendto/sendto.go @@ -42,7 +42,6 @@ type sendToSyscall struct { // sendto system call returns the number of characters sent but both unix.Sendto and syscall.Sendto do not return // it and do not allow to rewrite it by using direct calls to unix.Syscall or syscall.Syscall. For this reason, the // returned value is currently neither set nor bindable. - Ret int } // New creates a new sendto system call test step. @@ -63,9 +62,5 @@ func (s *sendToSyscall) run(_ context.Context) error { if length == 0 { length = len(s.args.Buf) } - if err := unix.Sendto(s.bindOnlyArgs.FD, s.args.Buf[:length], s.args.Flags, s.args.DestAddr); err != nil { - return err - } - - return nil + return unix.Sendto(s.bindOnlyArgs.FD, s.args.Buf[:length], s.args.Flags, s.args.DestAddr) } diff --git a/pkg/test/step/syscall/symlink/symlink.go b/pkg/test/step/syscall/symlink/symlink.go index 2c137d15..311e0217 100644 --- a/pkg/test/step/syscall/symlink/symlink.go +++ b/pkg/test/step/syscall/symlink/symlink.go @@ -39,7 +39,7 @@ type symlinkSyscall struct { // bindOnlyArgs represents arguments that can only be provided by binding. bindOnlyArgs struct{} savedLinkPath []byte - Ret int + // Return value is neither set nor bindable. } // New creates a new symlink system call test step. diff --git a/pkg/test/step/syscall/symlinkat/symlinkat.go b/pkg/test/step/syscall/symlinkat/symlinkat.go index 6993402b..574c5389 100644 --- a/pkg/test/step/syscall/symlinkat/symlinkat.go +++ b/pkg/test/step/syscall/symlinkat/symlinkat.go @@ -39,7 +39,7 @@ type symlinkAtSyscall struct { NewDirFD int `field_type:"fd"` } savedLinkPath []byte - Ret int + // Return value is neither set nor bindable. } // New creates a new symlinkat system call test step. From 2cf4b77caf86e86c18d46e1cdb9632c58aa225ea Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 19 Nov 2024 10:53:11 +0100 Subject: [PATCH 7/7] feat(decl/syscalls): add kill system call test step Signed-off-by: Leonardo Di Giovanna Co-authored-by: Aldo Lacuku --- pkg/test/field/field.go | 4 ++ pkg/test/loader/loader.go | 5 ++- pkg/test/step/syscall/base/base.go | 12 ++++++ pkg/test/step/syscall/base/consts.go | 37 ++++++++++++++++ pkg/test/step/syscall/builder/builder.go | 3 ++ pkg/test/step/syscall/kill/doc.go | 17 ++++++++ pkg/test/step/syscall/kill/kill.go | 54 ++++++++++++++++++++++++ pkg/test/step/syscall/syscall.go | 2 + 8 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 pkg/test/step/syscall/kill/doc.go create mode 100644 pkg/test/step/syscall/kill/kill.go diff --git a/pkg/test/field/field.go b/pkg/test/field/field.go index e6cb6ef0..76ba1691 100644 --- a/pkg/test/field/field.go +++ b/pkg/test/field/field.go @@ -79,6 +79,10 @@ const ( TypeSocketProtocol Type = "socket_protocol" // TypeSendFlags specifies that the field contains the sendto system call flags. TypeSendFlags Type = "send_flags" + // TypePID specifies that the field contains a process identifier. + TypePID Type = "pid" + // TypeSignal specifies that the field contains a signal. + TypeSignal Type = "signal" ) const ( diff --git a/pkg/test/loader/loader.go b/pkg/test/loader/loader.go index 9660f62e..c3d9fd98 100644 --- a/pkg/test/loader/loader.go +++ b/pkg/test/loader/loader.go @@ -676,6 +676,8 @@ const ( SyscallNameSocket SyscallName = "socket" // SyscallNameSendTo specifies the name of the sendto system call. SyscallNameSendTo SyscallName = "sendto" + // SyscallNameKill specifies the name of the kill system call. + SyscallNameKill SyscallName = "kill" ) // UnmarshalYAML populates the SyscallName instance by unmarshalling the content of the provided YAML node. @@ -687,7 +689,8 @@ func (s *SyscallName) UnmarshalYAML(node *yaml.Node) error { switch SyscallName(value) { case SyscallNameWrite, SyscallNameRead, SyscallNameOpen, SyscallNameOpenAt, SyscallNameOpenAt2, SyscallNameSymLink, SyscallNameSymLinkAt, SyscallNameLink, SyscallNameLinkAt, SyscallNameInitModule, SyscallNameFinitModule, - SyscallNameDup, SyscallNameDup2, SyscallNameDup3, SyscallNameConnect, SyscallNameSocket, SyscallNameSendTo: + SyscallNameDup, SyscallNameDup2, SyscallNameDup3, SyscallNameConnect, SyscallNameSocket, SyscallNameSendTo, + SyscallNameKill: default: return fmt.Errorf("unknown syscall %q", value) } diff --git a/pkg/test/step/syscall/base/base.go b/pkg/test/step/syscall/base/base.go index 5fc8e07b..daffacd3 100644 --- a/pkg/test/step/syscall/base/base.go +++ b/pkg/test/step/syscall/base/base.go @@ -235,6 +235,18 @@ func setArgFieldValue(argField *field.Field, value string) error { return fmt.Errorf("cannot parse value as send flags: %w", err) } argFieldValue.SetInt(int64(sendFlags)) + case field.TypePID: + pid, err := strconv.Atoi(value) + if err != nil { + return fmt.Errorf("cannot parse value as PID: %w", err) + } + argFieldValue.SetInt(int64(pid)) + case field.TypeSignal: + signal, err := parseSingleValue(value, signals) + if err != nil { + return fmt.Errorf("cannot parse value as signal: %w", err) + } + argFieldValue.SetInt(int64(signal)) case field.TypeUndefined: return fmt.Errorf("argument field type is undefined") default: diff --git a/pkg/test/step/syscall/base/consts.go b/pkg/test/step/syscall/base/consts.go index 13349483..c7b5a821 100644 --- a/pkg/test/step/syscall/base/consts.go +++ b/pkg/test/step/syscall/base/consts.go @@ -188,3 +188,40 @@ var sendFlags = map[string]int{ "MSG_NOSIGNAL": unix.MSG_NOSIGNAL, "MSG_OOB": unix.MSG_OOB, } + +var signals = map[string]int{ + "SIGABRT": int(unix.SIGABRT), + "SIGALRM": int(unix.SIGALRM), + "SIGBUS": int(unix.SIGBUS), + "SIGCHLD": int(unix.SIGCHLD), + "SIGCLD": int(unix.SIGCLD), + "SIGCONT": int(unix.SIGCONT), + "SIGFPE": int(unix.SIGFPE), + "SIGHUP": int(unix.SIGHUP), + "SIGILL": int(unix.SIGILL), + "SIGINT": int(unix.SIGINT), + "SIGIO": int(unix.SIGIO), + "SIGIOT": int(unix.SIGIOT), + "SIGKILL": int(unix.SIGKILL), + "SIGPIPE": int(unix.SIGPIPE), + "SIGPOLL": int(unix.SIGPOLL), + "SIGPROF": int(unix.SIGPROF), + "SIGPWR": int(unix.SIGPWR), + "SIGQUIT": int(unix.SIGQUIT), + "SIGSEGV": int(unix.SIGSEGV), + "SIGSTKFLT": int(unix.SIGSTKFLT), + "SIGSTOP": int(unix.SIGSTOP), + "SIGTSTP": int(unix.SIGTSTP), + "SIGSYS": int(unix.SIGSYS), + "SIGTERM": int(unix.SIGTERM), + "SIGTRAP": int(unix.SIGTRAP), + "SIGTTIN": int(unix.SIGTTIN), + "SIGTTOU": int(unix.SIGTTOU), + "SIGURG": int(unix.SIGURG), + "SIGUSR1": int(unix.SIGUSR1), + "SIGUSR2": int(unix.SIGUSR2), + "SIGVTALRM": int(unix.SIGVTALRM), + "SIGXCPU": int(unix.SIGXCPU), + "SIGXFSZ": int(unix.SIGXFSZ), + "SIGWINCH": int(unix.SIGWINCH), +} diff --git a/pkg/test/step/syscall/builder/builder.go b/pkg/test/step/syscall/builder/builder.go index 06d508e9..0a47ede5 100644 --- a/pkg/test/step/syscall/builder/builder.go +++ b/pkg/test/step/syscall/builder/builder.go @@ -25,6 +25,7 @@ import ( "github.com/falcosecurity/event-generator/pkg/test/step/syscall/dup3" "github.com/falcosecurity/event-generator/pkg/test/step/syscall/finitmodule" "github.com/falcosecurity/event-generator/pkg/test/step/syscall/initmodule" + "github.com/falcosecurity/event-generator/pkg/test/step/syscall/kill" "github.com/falcosecurity/event-generator/pkg/test/step/syscall/link" "github.com/falcosecurity/event-generator/pkg/test/step/syscall/linkat" "github.com/falcosecurity/event-generator/pkg/test/step/syscall/open" @@ -88,6 +89,8 @@ func (b *builder) Build(name syscall.Name, stepName string, description *syscall return errDecorator(finitmodule.New(stepName, rawArgs, fieldBindings)) case syscall.NameSendTo: return errDecorator(sendto.New(stepName, rawArgs, fieldBindings)) + case syscall.NameKill: + return errDecorator(kill.New(stepName, rawArgs, fieldBindings)) default: return nil, fmt.Errorf("unknown syscall %q", name) } diff --git a/pkg/test/step/syscall/kill/doc.go b/pkg/test/step/syscall/kill/doc.go new file mode 100644 index 00000000..29c68564 --- /dev/null +++ b/pkg/test/step/syscall/kill/doc.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package kill provides the implementation of a kill system call test step. +package kill diff --git a/pkg/test/step/syscall/kill/kill.go b/pkg/test/step/syscall/kill/kill.go new file mode 100644 index 00000000..beae8db7 --- /dev/null +++ b/pkg/test/step/syscall/kill/kill.go @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kill + +import ( + "context" + "reflect" + + "golang.org/x/sys/unix" + + "github.com/falcosecurity/event-generator/pkg/test/step" + "github.com/falcosecurity/event-generator/pkg/test/step/syscall" + "github.com/falcosecurity/event-generator/pkg/test/step/syscall/base" +) + +type killSyscall struct { + // args represents arguments that can be provided by value or by binding. + args struct { + Sig unix.Signal `field_type:"signal"` + } + // bindOnlyArgs represents arguments that can only be provided by binding. + bindOnlyArgs struct { + PID int `field_type:"pid"` + } + // Return value is neither set nor bindable. +} + +// New creates a new kill system call test step. +func New(name string, rawArgs map[string]string, + fieldBindings []*step.FieldBinding) (syscall.Syscall, error) { + k := &killSyscall{} + argsContainer := reflect.ValueOf(&k.args).Elem() + bindOnlyArgsContainer := reflect.ValueOf(&k.bindOnlyArgs).Elem() + retValContainer := reflect.ValueOf(k).Elem() + return base.New(name, rawArgs, fieldBindings, argsContainer, bindOnlyArgsContainer, retValContainer, nil, k.run, + nil) +} + +func (k *killSyscall) run(_ context.Context) error { + return unix.Kill(k.bindOnlyArgs.PID, k.args.Sig) +} diff --git a/pkg/test/step/syscall/syscall.go b/pkg/test/step/syscall/syscall.go index 626ac77a..20674c59 100644 --- a/pkg/test/step/syscall/syscall.go +++ b/pkg/test/step/syscall/syscall.go @@ -68,6 +68,8 @@ const ( NameSocket = "socket" // NameSendTo specifies the name of the sendto system call test step. NameSendTo = "sendto" + // NameKill specifies the name of the kill system call test step. + NameKill = "kill" ) // Description contains information to build a new Syscall test step.