From ce508b36f3020ccdf52851b499424b034ddd36ef Mon Sep 17 00:00:00 2001 From: Ofek Shaked Date: Sun, 29 Dec 2024 15:42:34 +0200 Subject: [PATCH] fix(events): derive multiple hooked_syscall events if needed After running the init function of a kernel module, the kernel frees the memory that was allocated for it but doesn't remove its symbol from kallsyms. This resulsts in a scenario where a subsequent loaded module can be allocated to the same area as the free'd init function of the prevous module. This could result in 2 symbols at the same address, one is the free'd init function and another from the newly loaded module. This caused an undeterminism in which symbol is used by the hooked_syscall event, which only used the first symbol that was found, resulting in random test failures. This commit changes the hooked_syscall event to emit one event for each found symbol. --- pkg/events/derive/hooked_syscall.go | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/pkg/events/derive/hooked_syscall.go b/pkg/events/derive/hooked_syscall.go index 9160e274f346..a31057f2fef8 100644 --- a/pkg/events/derive/hooked_syscall.go +++ b/pkg/events/derive/hooked_syscall.go @@ -28,19 +28,19 @@ func InitHookedSyscall() error { } func DetectHookedSyscall(kernelSymbols *environment.KernelSymbolTable) DeriveFunction { - return deriveSingleEvent(events.HookedSyscall, deriveDetectHookedSyscallArgs(kernelSymbols)) + return deriveMultipleEvents(events.HookedSyscall, deriveDetectHookedSyscallArgs(kernelSymbols)) } -func deriveDetectHookedSyscallArgs(kernelSymbols *environment.KernelSymbolTable) deriveArgsFunction { - return func(event trace.Event) ([]interface{}, error) { +func deriveDetectHookedSyscallArgs(kernelSymbols *environment.KernelSymbolTable) multiDeriveArgsFunction { + return func(event trace.Event) ([][]interface{}, []error) { syscallId, err := parse.ArgVal[int32](event.Args, "syscall_id") if err != nil { - return nil, errfmt.Errorf("error parsing syscall_id arg: %v", err) + return nil, []error{errfmt.Errorf("error parsing syscall_id arg: %v", err)} } address, err := parse.ArgVal[uint64](event.Args, "syscall_address") if err != nil { - return nil, errfmt.Errorf("error parsing syscall_address arg: %v", err) + return nil, []error{errfmt.Errorf("error parsing syscall_address arg: %v", err)} } alreadyReportedAddress, found := reportedHookedSyscalls.Get(syscallId) @@ -50,18 +50,20 @@ func deriveDetectHookedSyscallArgs(kernelSymbols *environment.KernelSymbolTable) reportedHookedSyscalls.Add(syscallId, address) // Upsert - hookedFuncName := "" - hookedOwner := "" - hookedFuncSymbol, err := kernelSymbols.GetSymbolByAddr(address) - if err == nil { - hookedFuncName = hookedFuncSymbol[0].Name - hookedOwner = hookedFuncSymbol[0].Owner - } - syscallName := convertToSyscallName(syscallId) hexAddress := fmt.Sprintf("%x", address) - return []interface{}{syscallName, hexAddress, hookedFuncName, hookedOwner}, nil + hookedFuncSymbols, err := kernelSymbols.GetSymbolByAddr(address) + if err != nil { + return [][]interface{}{{syscallName, hexAddress, "", ""}}, nil + } + + events := make([][]interface{}, 0) + for _, symbol := range hookedFuncSymbols { + events = append(events, []interface{}{syscallName, hexAddress, symbol.Name, symbol.Owner}) + } + + return events, nil } }