feat(go): port memory-map detector tranche

This commit is contained in:
Luna 2026-07-11 01:19:56 -07:00
parent c6f7219de8
commit 6a27e6e770
No known key found for this signature in database
13 changed files with 377 additions and 41 deletions

View file

@ -78,12 +78,13 @@ func CaptureWithPaths(paths Paths) (model.State, error) {
}
base := filepath.Join(procRoot, entry.Name())
processes = append(processes, model.Process{
PID: pid,
Comm: strings.TrimSpace(readText(filepath.Join(base, "comm"))),
Cmdline: strings.TrimSpace(strings.ReplaceAll(readText(filepath.Join(base, "cmdline")), "\x00", " ")),
Exe: readLink(filepath.Join(base, "exe")),
Environ: parseEnviron(readText(filepath.Join(base, "environ"))),
FDTargets: readFDTargets(filepath.Join(base, "fd")),
PID: pid,
Comm: strings.TrimSpace(readText(filepath.Join(base, "comm"))),
Cmdline: strings.TrimSpace(strings.ReplaceAll(readText(filepath.Join(base, "cmdline")), "\x00", " ")),
Exe: readLink(filepath.Join(base, "exe")),
Environ: parseEnviron(readText(filepath.Join(base, "environ"))),
FDTargets: readFDTargets(filepath.Join(base, "fd")),
MemoryMaps: parseMemoryMaps(readText(filepath.Join(base, "maps"))),
})
}
sort.Slice(processes, func(i, j int) bool { return processes[i].PID < processes[j].PID })
@ -193,6 +194,49 @@ func readFDTargets(path string) map[string]string {
return result
}
// parseMemoryMaps mirrors Python's split(maxsplit=5) parser. A process may
// disappear or deny maps access between directory enumeration and this read;
// returning an empty slice preserves the detector's fail-open behavior.
func parseMemoryMaps(text string) []model.MemoryMap {
result := make([]model.MemoryMap, 0)
for _, line := range strings.Split(text, "\n") {
fields := strings.Fields(line)
if len(fields) < 5 {
continue
}
bounds := strings.SplitN(fields[0], "-", 2)
if len(bounds) != 2 {
continue
}
start, err := strconv.ParseUint(bounds[0], 16, 64)
if err != nil {
continue
}
end, err := strconv.ParseUint(bounds[1], 16, 64)
if err != nil {
continue
}
path := ""
if len(fields) > 5 {
// Keep pathname spaces intact, just as Python's maxsplit=5 does.
remaining := strings.TrimSpace(line)
for index := 0; index < 5; index++ {
space := strings.IndexAny(remaining, " \t")
if space < 0 {
remaining = ""
break
}
remaining = strings.TrimSpace(remaining[space:])
}
path = remaining
}
result = append(result, model.MemoryMap{
Start: start, End: end, Perms: fields[1], Path: path,
})
}
return result
}
func readText(path string) string {
raw, err := os.ReadFile(path)
if err != nil {