Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proctree improvements (cont) #4572

Merged
merged 3 commits into from
Feb 6, 2025
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
2 changes: 1 addition & 1 deletion docs/docs/events/builtin/extra/sched_process_exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ security, and auditing.
12. **interp** (`const char*`): Specifies the interpreter of the binary.
13. **stdin_type** (`umode_t`): Mode of the standard input.
14. **stdin_path** (`char*`): Path of the standard input.
15. **invoked_from_kernel** (`int`): Flag to determine if the process was initiated by the kernel.
15. **invoked_from_kernel** (`bool`): Flag to determine if the process was initiated by the kernel.
16. **env** (`const char**`): Environment variables associated with the process.

## Hooks
Expand Down
13 changes: 4 additions & 9 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1488,16 +1488,13 @@ int sched_process_exec_event_submit_tail(struct bpf_raw_tracepoint_args *ctx)
void *stdin_path = get_path_str(__builtin_preserve_access_index(&stdin_file->f_path));
const char *interp = get_binprm_interp(bprm);

int invoked_from_kernel = 0;
if (get_task_parent_flags(task) & PF_KTHREAD) {
invoked_from_kernel = 1;
}
bool invoked_from_kernel = !!(get_task_parent_flags(task) & PF_KTHREAD);

save_args_str_arr_to_buf(&p.event->args_buf, (void *) arg_start, (void *) arg_end, argc, 10);
save_str_to_buf(&p.event->args_buf, (void *) interp, 11);
save_to_submit_buf(&p.event->args_buf, &stdin_type, sizeof(unsigned short), 12);
save_str_to_buf(&p.event->args_buf, stdin_path, 13);
save_to_submit_buf(&p.event->args_buf, &invoked_from_kernel, sizeof(int), 14);
save_to_submit_buf(&p.event->args_buf, &invoked_from_kernel, sizeof(bool), 14);
save_str_to_buf(&p.event->args_buf, (void *) p.task_info->context.comm, 15);
if (p.config->options & OPT_EXEC_ENV) {
unsigned long env_start, env_end;
Expand Down Expand Up @@ -7113,15 +7110,13 @@ int sched_process_exec_signal(struct bpf_raw_tracepoint_args *ctx)
void *stdin_path = get_path_str(__builtin_preserve_access_index(&stdin_file->f_path));
const char *interp = get_binprm_interp(bprm);

int invoked_from_kernel = 0;
if (get_task_parent_flags(task) & PF_KTHREAD)
invoked_from_kernel = 1;
bool invoked_from_kernel = !!(get_task_parent_flags(task) & PF_KTHREAD);

save_args_str_arr_to_buf(&signal->args_buf, (void *) arg_start, (void *) arg_end, argc, 14); // argv
save_str_to_buf(&signal->args_buf, (void *) interp, 15); // interp
save_to_submit_buf(&signal->args_buf, &stdin_type, sizeof(unsigned short), 16); // stdin type
save_str_to_buf(&signal->args_buf, stdin_path, 17); // stdin path
save_to_submit_buf(&signal->args_buf, &invoked_from_kernel, sizeof(int), 18); // invoked from kernel ?
save_to_submit_buf(&signal->args_buf, &invoked_from_kernel, sizeof(bool), 18); // invoked from kernel ?

signal_perf_submit(ctx, signal);

Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/controlplane/processes.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func (ctrl *Controller) procTreeExecProcessor(args []trace.Argument) error {
if err != nil {
return err
}
execFeed.InvokedFromKernel, err = parse.ArgVal[int32](args, "invoked_from_kernel")
execFeed.InvokedFromKernel, err = parse.ArgVal[bool](args, "invoked_from_kernel")
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/controlplane/processes_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func Benchmark_procTreeExecProcessor(b *testing.B) {
{ArgMeta: trace.ArgMeta{Name: "interp"}, Value: "/lib64/ld-linux-x86-64.so.2"},
{ArgMeta: trace.ArgMeta{Name: "stdin_type"}, Value: uint16(1)},
{ArgMeta: trace.ArgMeta{Name: "stdin_path"}, Value: "/dev/null"},
{ArgMeta: trace.ArgMeta{Name: "invoked_from_kernel"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "invoked_from_kernel"}, Value: bool(true)},
}

b.ResetTimer()
Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/processor_proctree.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func (t *Tracee) procTreeExecProcessor(event *trace.Event) error {
if err != nil {
return err
}
execFeed.InvokedFromKernel, err = parse.ArgVal[int32](event.Args, "invoked_from_kernel")
execFeed.InvokedFromKernel, err = parse.ArgVal[bool](event.Args, "invoked_from_kernel")
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/processor_proctree_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func Benchmark_procTreeExecProcessor(b *testing.B) {
{ArgMeta: trace.ArgMeta{Name: "interp"}, Value: "/lib64/ld-linux-x86-64.so.2"},
{ArgMeta: trace.ArgMeta{Name: "stdin_type"}, Value: uint16(1)},
{ArgMeta: trace.ArgMeta{Name: "stdin_path"}, Value: "/dev/null"},
{ArgMeta: trace.ArgMeta{Name: "invoked_from_kernel"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "invoked_from_kernel"}, Value: bool(true)},
},
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/events/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -11195,7 +11195,7 @@ var CoreEvents = map[ID]Definition{
{Type: "const char*", Name: "interp"},
{Type: "umode_t", Name: "stdin_type"},
{Type: "char*", Name: "stdin_path"},
{Type: "int", Name: "invoked_from_kernel"},
{Type: "bool", Name: "invoked_from_kernel"},
{Type: "const char*", Name: "prev_comm"},
{Type: "const char**", Name: "env"},
},
Expand Down Expand Up @@ -13216,7 +13216,7 @@ var CoreEvents = map[ID]Definition{
{Type: "const char*", Name: "interp"},
{Type: "umode_t", Name: "stdin_type"},
{Type: "char*", Name: "stdin_path"},
{Type: "int", Name: "invoked_from_kernel"},
{Type: "bool", Name: "invoked_from_kernel"},
},
},
SignalSchedProcessExit: {
Expand Down
7 changes: 4 additions & 3 deletions pkg/proctree/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,12 @@ func (ptds *DataSource) exportProcessInfo(
) datasource.TimeRelevantInfo[datasource.ProcessInfo] {
// Pick the objects related to the process from the process tree.
info := process.GetInfo()
procHash := process.GetHash()
executable := process.GetExecutable()

// Walk children hashes and discover the ones alive at the query time.
aliveChildren := make(map[int]uint32)
for _, childHash := range process.GetChildren() {
for _, childHash := range ptds.procTree.GetChildren(procHash) {
child, ok := ptds.procTree.GetProcessByHash(childHash)
if !ok {
continue
Expand All @@ -109,7 +110,7 @@ func (ptds *DataSource) exportProcessInfo(

// Walk thread hashes and discover the ones alive at the query time.
aliveThreads := make(map[int]uint32)
for _, threadHash := range process.GetThreads() {
for _, threadHash := range ptds.procTree.GetThreads(procHash) {
thread, ok := ptds.procTree.GetThreadByHash(threadHash)
if !ok {
continue
Expand All @@ -126,7 +127,7 @@ func (ptds *DataSource) exportProcessInfo(
// Export the information as the expected datasource process structure.
return datasource.TimeRelevantInfo[datasource.ProcessInfo]{
Info: datasource.ProcessInfo{
EntityId: process.GetHash(),
EntityId: procHash,
// TODO: change types pkg to reduce mem footprint (Pid, NsPid, Ppid, ThreadsIds, ChildProcessesIds)
Pid: int(infoFeed.Pid),
NsPid: int(infoFeed.NsPid),
Expand Down
11 changes: 6 additions & 5 deletions pkg/proctree/fileinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import (
// FileInfoFeed allows external packages to set/get multiple values of a task at once.
type FileInfoFeed struct {
// Name string
Path string // mutable (file path)
Dev uint32 // mutable (device number)
Ctime uint64 // mutable (creation time)
Inode uint64 // mutable (inode number)
InodeMode uint16 // mutable (inode mode)
Path string // mutable (file path)
Dev uint32 // mutable (device number)
InodeMode uint16 // mutable (inode mode)
_ [2]byte // padding
Ctime uint64 // mutable (creation time)
Inode uint64 // mutable (inode number)
}

//
Expand Down
15 changes: 15 additions & 0 deletions pkg/proctree/fileinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package proctree

import (
"os"
"testing"

"github.com/aquasecurity/tracee/pkg/utils/tests"
)

// TestFileInfoFeed_PrintSizes prints the sizes of the structs used in the FileInfoFeed type.
// Run it as DEBUG test to see the output.
func TestFileInfoFeed_PrintSizes(t *testing.T) {
fileInfo := FileInfoFeed{}
tests.PrintStructSizes(t, os.Stdout, fileInfo)
}
84 changes: 7 additions & 77 deletions pkg/proctree/process.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package proctree

import (
"sync"
"sync/atomic"
)

Expand All @@ -11,26 +10,19 @@ import (

// Process represents a process.
type Process struct {
processHash uint32 // hash of process (immutable, so no need of concurrency control)
parentHash uint32 // hash of parent
info *TaskInfo // task info (immutable pointer)
executable *FileInfo // executable info (immutable pointer)
children map[uint32]struct{} // hash of children
threads map[uint32]struct{} // hash of threads
// Control fields
mutex *sync.RWMutex // mutex to protect the process
processHash uint32 // hash of process (immutable, so no need of concurrency control)
parentHash atomic.Uint32 // hash of parent
info *TaskInfo // task info (immutable pointer)
executable *FileInfo // executable info (immutable pointer)
}

// NewProcess creates a new thread with an initialized task info.
func NewProcess(hash uint32, info *TaskInfo) *Process {
return &Process{
processHash: hash,
parentHash: 0,
parentHash: atomic.Uint32{},
info: info,
executable: NewFileInfo(),
children: make(map[uint32]struct{}),
threads: make(map[uint32]struct{}),
mutex: &sync.RWMutex{},
}
}

Expand All @@ -43,7 +35,7 @@ func (p *Process) GetHash() uint32 {

// GetParentHash returns the hash of the parent.
func (p *Process) GetParentHash() uint32 {
return atomic.LoadUint32(&p.parentHash)
return p.parentHash.Load()
}

// GetInfo returns a instanced task info.
Expand All @@ -60,67 +52,5 @@ func (p *Process) GetExecutable() *FileInfo {

// SetParentHash sets the hash of the parent.
func (p *Process) SetParentHash(parentHash uint32) {
atomic.StoreUint32(&p.parentHash, parentHash)
}

//
// Children and Threads
//

// AddChild adds a child to the process.
func (p *Process) AddChild(childHash uint32) {
p.mutex.Lock()
defer p.mutex.Unlock()

p.children[childHash] = struct{}{}
}

// AddThread adds a thread to the process.
func (p *Process) AddThread(threadHash uint32) {
p.mutex.Lock()
defer p.mutex.Unlock()

p.threads[threadHash] = struct{}{}
}

// GetChildren returns the children of the process.
func (p *Process) GetChildren() []uint32 {
p.mutex.RLock()
defer p.mutex.RUnlock()

children := make([]uint32, 0, len(p.children))
for child := range p.children {
children = append(children, child)
}

return children
}

// GetThreads returns the threads of the process.
func (p *Process) GetThreads() []uint32 {
p.mutex.RLock()
defer p.mutex.RUnlock()

threads := make([]uint32, 0, len(p.threads))
for thread := range p.threads {
threads = append(threads, thread)
}

return threads
}

// DelChild deletes a child from the process.
func (p *Process) DelChild(childHash uint32) {
p.mutex.Lock()
defer p.mutex.Unlock()

delete(p.children, childHash)
}

// DelThread deletes a thread from the process.
func (p *Process) DelThread(threadHash uint32) {
p.mutex.Lock()
defer p.mutex.Unlock()

delete(p.threads, threadHash)
p.parentHash.Store(parentHash)
}
14 changes: 14 additions & 0 deletions pkg/proctree/process_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package proctree

import (
"os"
"testing"

"github.com/aquasecurity/tracee/pkg/utils/tests"
)

// TestProcess_PrintSizes prints the sizes of the structs used in the Process type.
// Run it as DEBUG test to see the output.
func TestProcess_PrintSizes(t *testing.T) {
tests.PrintStructSizes(t, os.Stdout, Process{})
}
Loading
Loading