From fa1409f6d7b0b465a5e6a31076213bd6a3b701c9 Mon Sep 17 00:00:00 2001 From: yugal07 Date: Sun, 5 Apr 2026 23:49:52 +0530 Subject: [PATCH 1/2] fix(utils): restore NormalizePath to fix headless /proc and dot paths Signed-off-by: yugal07 --- pkg/utils/datasource_event.go | 10 ++--- pkg/utils/normalize_path_test.go | 72 ++++++++++++++++++++++++++++++++ pkg/utils/path.go | 34 +++++++++++++++ pkg/utils/struct_event.go | 10 ++--- 4 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 pkg/utils/normalize_path_test.go create mode 100644 pkg/utils/path.go diff --git a/pkg/utils/datasource_event.go b/pkg/utils/datasource_event.go index 3c5d803e78..853171642c 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 0000000000..f9f24e59ec --- /dev/null +++ b/pkg/utils/normalize_path_test.go @@ -0,0 +1,72 @@ +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: "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 0000000000..0199ce9168 --- /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 278c8ebe89..46b41d846d 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 { From 26ebe00bf1a1930fa8218350baf294c293611fd9 Mon Sep 17 00:00:00 2001 From: yugal07 Date: Mon, 6 Apr 2026 00:02:57 +0530 Subject: [PATCH 2/2] fix(utils): handle terminal headless proc paths in NormalizePath Signed-off-by: yugal07 --- pkg/utils/normalize_path_test.go | 10 ++++++++++ pkg/utils/path.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/utils/normalize_path_test.go b/pkg/utils/normalize_path_test.go index f9f24e59ec..32d5e300cc 100644 --- a/pkg/utils/normalize_path_test.go +++ b/pkg/utils/normalize_path_test.go @@ -40,6 +40,16 @@ func TestNormalizePath(t *testing.T) { 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", diff --git a/pkg/utils/path.go b/pkg/utils/path.go index 0199ce9168..9a9fcd481e 100644 --- a/pkg/utils/path.go +++ b/pkg/utils/path.go @@ -6,7 +6,7 @@ import ( "strings" ) -var headlessProcRegex = regexp.MustCompile(`^/\d+/(task|fd)/`) +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)