diff --git a/pkg/security/utils/proc_linux.go b/pkg/security/utils/proc_linux.go index 1ee6765ae737e..9a3a8ec869baa 100644 --- a/pkg/security/utils/proc_linux.go +++ b/pkg/security/utils/proc_linux.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "os" "path" "path/filepath" @@ -110,6 +111,11 @@ func StatusPath(pid uint32) string { return procPidPath(pid, "status") } +// TaskStatusPath returns the path to the status file of a task pid in /proc +func TaskStatusPath(pid uint32, task string) string { + return procPidPath3(pid, "task", task, "status") +} + // LoginUIDPath returns the path to the loginuid file of a pid in /proc func LoginUIDPath(pid uint32) string { return procPidPath(pid, "loginuid") @@ -144,6 +150,10 @@ func procPidPath2(pid uint32, path1 string, path2 string) string { return filepath.Join(kernel.ProcFSRoot(), strconv.FormatUint(uint64(pid), 10), path1, path2) } +func procPidPath3(pid uint32, path1, path2, path3 string) string { + return filepath.Join(kernel.ProcFSRoot(), strconv.FormatUint(uint64(pid), 10), path1, path2, path3) +} + // ModulesPath returns the path to the modules file in /proc func ModulesPath() string { return filepath.Join(kernel.ProcFSRoot(), "modules") @@ -410,8 +420,8 @@ func GetProcessPidNamespace(pid uint32) (uint64, error) { } // GetNsPids returns the namespaced pids of the the givent root pid -func GetNsPids(pid uint32) ([]uint32, error) { - statusFile := StatusPath(pid) +func GetNsPids(pid uint32, task string) ([]uint32, error) { + statusFile := TaskStatusPath(pid, task) content, err := os.ReadFile(statusFile) if err != nil { return nil, fmt.Errorf("failed to read status file: %w", err) @@ -442,6 +452,26 @@ func GetNsPids(pid uint32) ([]uint32, error) { return nil, fmt.Errorf("NSpid field not found") } +// GetPidTasks returns the task IDs of a process +func GetPidTasks(pid uint32) ([]string, error) { + taskPath := procPidPath(pid, "task") + + // Read the contents of the task directory + tasks, err := ioutil.ReadDir(taskPath) + if err != nil { + return nil, fmt.Errorf("failed to read task directory: %v", err) + } + + // Collect all task IDs + var taskIDs []string + for _, task := range tasks { + if task.IsDir() { + taskIDs = append(taskIDs, task.Name()) + } + } + return taskIDs, nil +} + // FindPidNamespace search and return the host PID for the given namespaced PID + its namespace func FindPidNamespace(nspid uint32, ns uint64) (uint32, error) { procPids, err := process.Pids() @@ -455,8 +485,17 @@ func FindPidNamespace(nspid uint32, ns uint64) (uint32, error) { continue } - if procNs == ns { - nspids, err := GetNsPids(uint32(procPid)) + if procNs != ns { + continue + } + + tasks, err := GetPidTasks(uint32(procPid)) + if err != nil { + continue + } + + for _, task := range tasks { + nspids, err := GetNsPids(uint32(procPid), task) if err != nil { return 0, err }