diff --git a/pkg/utils/datasource_event.go b/pkg/utils/datasource_event.go index 3c5d803e7..853171642 100644 --- a/pkg/utils/datasource_event.go +++ b/pkg/utils/datasource_event.go @@ -397,7 +397,7 @@ func (e *DatasourceEvent) GetEventType() EventType { func (e *DatasourceEvent) GetExePath() string { exepath, _ := e.getFieldAccessor("exepath").String(e.Data) - return exepath + return NormalizePath(exepath) } func (e *DatasourceEvent) GetExitCode() uint32 { @@ -439,7 +439,7 @@ func (e *DatasourceEvent) GetFullPath() string { if path == "" { path, _ = e.getFieldAccessor("fname").String(e.Data) } - return path + return NormalizePath(path) } func (e *DatasourceEvent) GetGid() *uint32 { @@ -490,7 +490,7 @@ func (e *DatasourceEvent) GetNamespace() string { func (e *DatasourceEvent) GetNewPath() string { newPath, _ := e.getFieldAccessor("newpath").String(e.Data) - return newPath + return NormalizePath(newPath) } func (e *DatasourceEvent) GetNumAnswers() int { @@ -500,7 +500,7 @@ func (e *DatasourceEvent) GetNumAnswers() int { func (e *DatasourceEvent) GetOldPath() string { oldPath, _ := e.getFieldAccessor("oldpath").String(e.Data) - return oldPath + return NormalizePath(oldPath) } func (e *DatasourceEvent) GetOpcode() int { @@ -526,7 +526,7 @@ func (e *DatasourceEvent) GetPath() string { return e.GetFullPath() } path, _ := e.getFieldAccessor("fname").String(e.Data) - return path + return NormalizePath(path) } func (e *DatasourceEvent) GetPcomm() string { diff --git a/pkg/utils/normalize_path_test.go b/pkg/utils/normalize_path_test.go new file mode 100644 index 000000000..32d5e300c --- /dev/null +++ b/pkg/utils/normalize_path_test.go @@ -0,0 +1,82 @@ +package utils + +import ( + "testing" +) + +func TestNormalizePath(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "empty path", + input: "", + expected: "", + }, + { + name: "dot path", + input: ".", + expected: "/", + }, + { + name: "absolute path", + input: "/etc/passwd", + expected: "/etc/passwd", + }, + { + name: "headless proc path (task)", + input: "/46/task/46/fd", + expected: "/proc/46/task/46/fd", + }, + { + name: "headless proc path (fd)", + input: "/46/fd/3", + expected: "/proc/46/fd/3", + }, + { + name: "already absolute proc path", + input: "/proc/46/fd/3", + expected: "/proc/46/fd/3", + }, + { + name: "terminal headless proc fd path", + input: "/46/fd", + expected: "/proc/46/fd", + }, + { + name: "terminal headless proc task path", + input: "/46/task", + expected: "/proc/46/task", + }, + { + name: "relative path (not dot)", + input: "usr/bin/ls", + expected: "/usr/bin/ls", + }, + { + name: "relative path with ./", + input: "./config", + expected: "/config", + }, + { + name: "path with redundant slashes", + input: "/etc//passwd", + expected: "/etc/passwd", + }, + { + name: "path with dot components", + input: "/usr/./bin/../lib", + expected: "/usr/lib", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NormalizePath(tt.input); got != tt.expected { + t.Errorf("NormalizePath(%q) = %q, want %q", tt.input, got, tt.expected) + } + }) + } +} diff --git a/pkg/utils/path.go b/pkg/utils/path.go new file mode 100644 index 000000000..9a9fcd481 --- /dev/null +++ b/pkg/utils/path.go @@ -0,0 +1,34 @@ +package utils + +import ( + "path" + "regexp" + "strings" +) + +var headlessProcRegex = regexp.MustCompile(`^/\d+/(task|fd)(/|$)`) + +// NormalizePath normalizes a path by: +// 1. Prepending "/proc" to "headless" proc paths (e.g. /46/task/46/fd -> /proc/46/task/46/fd) +// 2. Ensuring it starts with "/" if it's not empty +// 3. Converting "." to "/" +// 4. Cleaning the path (removing redundant slashes, dot-dots, etc.) +func NormalizePath(p string) string { + if p == "" { + return "" + } + + if p == "." { + return "/" + } + + if headlessProcRegex.MatchString(p) { + p = "/proc" + p + } + + if !strings.HasPrefix(p, "/") { + p = "/" + p + } + + return path.Clean(p) +} diff --git a/pkg/utils/struct_event.go b/pkg/utils/struct_event.go index 278c8ebe8..46b41d846 100644 --- a/pkg/utils/struct_event.go +++ b/pkg/utils/struct_event.go @@ -227,7 +227,7 @@ func (e *StructEvent) GetEventType() EventType { } func (e *StructEvent) GetExePath() string { - return e.ExePath + return NormalizePath(e.ExePath) } func (e *StructEvent) GetExitCode() uint32 { @@ -247,7 +247,7 @@ func (e *StructEvent) GetFlagsRaw() uint32 { } func (e *StructEvent) GetFullPath() string { - return e.FullPath + return NormalizePath(e.FullPath) } func (e *StructEvent) GetGid() *uint32 { @@ -279,7 +279,7 @@ func (e *StructEvent) GetNamespace() string { } func (e *StructEvent) GetNewPath() string { - return e.NewPath + return NormalizePath(e.NewPath) } func (e *StructEvent) GetNumAnswers() int { @@ -287,7 +287,7 @@ func (e *StructEvent) GetNumAnswers() int { } func (e *StructEvent) GetOldPath() string { - return e.OldPath + return NormalizePath(e.OldPath) } func (e *StructEvent) GetOpcode() int { @@ -311,7 +311,7 @@ func (e *StructEvent) GetPath() string { if e.FullPathTracing { return e.GetFullPath() } - return e.Path + return NormalizePath(e.Path) } func (e *StructEvent) GetPcomm() string {