feat: switch macOS learning mode from fs_usage to eslogger
Replace fs_usage (reports Mach thread IDs, requiring process name matching with false positives) with eslogger (Endpoint Security framework, reports real Unix PIDs via audit_token.pid plus fork events for process tree tracking). Key changes: - Daemon starts eslogger instead of fs_usage, with early-exit detection and clear Full Disk Access error messaging - New two-pass eslogger JSON parser: pass 1 builds PID tree from fork events, pass 2 filters filesystem events by PID set - Remove runtime PID polling (StartPIDTracking, pollDescendantPIDs) — process tree is now built post-hoc from the eslogger log - Platform-specific generateLearnedTemplatePlatform() for darwin/linux/stub - Refactor TraceResult and GenerateLearnedTemplate to be platform-agnostic
This commit is contained in:
@@ -10,6 +10,13 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TraceResult holds parsed read and write paths from a system trace log
|
||||
// (strace on Linux, eslogger on macOS).
|
||||
type TraceResult struct {
|
||||
WritePaths []string
|
||||
ReadPaths []string
|
||||
}
|
||||
|
||||
// wellKnownParents are directories under $HOME where applications typically
|
||||
// create their own subdirectory (e.g., ~/.cache/opencode, ~/.config/opencode).
|
||||
var wellKnownParents = []string{
|
||||
@@ -52,14 +59,9 @@ func SanitizeTemplateName(name string) string {
|
||||
return sanitized
|
||||
}
|
||||
|
||||
// GenerateLearnedTemplate parses an strace log, collapses paths, and saves a template.
|
||||
// GenerateLearnedTemplate takes a parsed trace result, collapses paths, and saves a template.
|
||||
// Returns the path where the template was saved.
|
||||
func GenerateLearnedTemplate(straceLogPath, cmdName string, debug bool) (string, error) {
|
||||
result, err := ParseStraceLog(straceLogPath, debug)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse strace log: %w", err)
|
||||
}
|
||||
|
||||
func GenerateLearnedTemplate(result *TraceResult, cmdName string, debug bool) (string, error) {
|
||||
home, _ := os.UserHomeDir()
|
||||
|
||||
// Filter write paths: remove default writable and sensitive paths
|
||||
@@ -231,8 +233,9 @@ func CollapsePaths(paths []string) []string {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort and deduplicate (remove sub-paths of other paths)
|
||||
// Sort, remove exact duplicates, then remove sub-paths of other paths
|
||||
sort.Strings(result)
|
||||
result = removeDuplicates(result)
|
||||
result = deduplicateSubPaths(result)
|
||||
|
||||
return result
|
||||
@@ -364,6 +367,20 @@ func ListLearnedTemplates() ([]LearnedTemplateInfo, error) {
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
// removeDuplicates removes exact duplicate strings from a sorted slice.
|
||||
func removeDuplicates(paths []string) []string {
|
||||
if len(paths) <= 1 {
|
||||
return paths
|
||||
}
|
||||
result := []string{paths[0]}
|
||||
for i := 1; i < len(paths); i++ {
|
||||
if paths[i] != paths[i-1] {
|
||||
result = append(result, paths[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// deduplicateSubPaths removes paths that are sub-paths of other paths in the list.
|
||||
// Assumes the input is sorted.
|
||||
func deduplicateSubPaths(paths []string) []string {
|
||||
|
||||
Reference in New Issue
Block a user