fix: refactor ent file walking to use mounted filesystem root

This commit is contained in:
blacktop
2026-05-07 11:10:59 -06:00
parent 2a1fc1bf70
commit 9360b3b7a4
2 changed files with 108 additions and 23 deletions
+40 -23
View File
@@ -30,6 +30,11 @@ import (
// Entitlements is a map of entitlements
type Entitlements map[string]any
type mountedEntitlementFile struct {
Path string
DBPath string
}
// Config is the configuration for the entitlements command
type Config struct {
IPSW string
@@ -377,37 +382,23 @@ func scanEnts(ipswPath, dmgPath, dmgType string, conf *Config) (map[string]strin
}()
}
var files []string
if err := filepath.Walk(mountPoint, func(path string, info os.FileInfo, err error) error {
if err != nil {
// Skip paths with permission errors gracefully
if os.IsPermission(err) {
log.Debugf("skipping path due to permission denied: %s", path)
return nil
}
log.Debugf("failed to walk mount %s: %v", mountPoint, err)
return nil
}
if !info.IsDir() {
files = append(files, path)
}
return nil
}); err != nil {
return nil, fmt.Errorf("failed to walk files in dir %s: %v", mountPoint, err)
files, err := mountedEntitlementFiles(mountPoint)
if err != nil {
return nil, err
}
entDB := make(map[string]string)
for _, file := range files {
var m *macho.File
fat, err := macho.OpenFat(file)
fat, err := macho.OpenFat(file.Path)
if err == nil {
m = fat.Arches[len(fat.Arches)-1].File // grab last arch (probably arm64e)
} else {
if err == macho.ErrNotFat {
m, err = macho.Open(file)
m, err = macho.Open(file.Path)
if err != nil {
log.WithError(err).Warnf("failed to get entitlements for %s", file)
log.WithError(err).Warnf("failed to get entitlements for %s", file.Path)
continue // bad macho file (skip)
}
} else {
@@ -423,7 +414,7 @@ func scanEnts(ipswPath, dmgPath, dmgType string, conf *Config) (map[string]strin
// Fallback to DER entitlements if normal ones are empty
if decoded, err := ents.DerDecode(m.CodeSignature().EntitlementsDER); err == nil {
output.WriteString(decoded)
log.Warnf("using DER entitlements for %s", file)
log.Warnf("using DER entitlements for %s", file.Path)
}
}
// Add launch constraints if requested (for diff, not for database)
@@ -466,11 +457,37 @@ func scanEnts(ipswPath, dmgPath, dmgType string, conf *Config) (map[string]strin
}
}
entDB[strings.TrimPrefix(file, mountPoint)] = output.String()
entDB[file.DBPath] = output.String()
} else {
entDB[strings.TrimPrefix(file, mountPoint)] = ""
entDB[file.DBPath] = ""
}
}
return entDB, nil
}
func mountedEntitlementFiles(mountPoint string) ([]mountedEntitlementFile, error) {
root := utils.MountedFilesystemRoot(mountPoint)
var files []mountedEntitlementFile
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
// Skip paths with permission errors gracefully
if os.IsPermission(err) {
log.Debugf("skipping path due to permission denied: %s", path)
return nil
}
log.Debugf("failed to walk mount %s: %v", root, err)
return nil
}
if !info.IsDir() {
files = append(files, mountedEntitlementFile{
Path: path,
DBPath: strings.TrimPrefix(path, root),
})
}
return nil
}); err != nil {
return nil, fmt.Errorf("failed to walk files in dir %s: %v", root, err)
}
return files, nil
}
+68
View File
@@ -0,0 +1,68 @@
package ent
import (
"os"
"path/filepath"
"testing"
)
func TestMountedEntitlementFilesRootNormalization(t *testing.T) {
tests := []struct {
name string
fileParts []string
wantParts []string
}{
{
name: "apfs fuse root",
fileParts: []string{"root", "System", "Library", "CoreServices", "testd"},
wantParts: []string{"System", "Library", "CoreServices", "testd"},
},
{
name: "direct root",
fileParts: []string{"System", "Library", "CoreServices", "testd"},
wantParts: []string{"System", "Library", "CoreServices", "testd"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
root := t.TempDir()
path := pathUnder(root, tt.fileParts...)
writeTestFile(t, path)
files, err := mountedEntitlementFiles(root)
if err != nil {
t.Fatal(err)
}
if len(files) != 1 {
t.Fatalf("expected 1 file, got %d: %#v", len(files), files)
}
wantDBPath := rootedPath(tt.wantParts...)
if files[0].Path != path {
t.Fatalf("Path = %q, want %q", files[0].Path, path)
}
if files[0].DBPath != wantDBPath {
t.Fatalf("DBPath = %q, want %q", files[0].DBPath, wantDBPath)
}
})
}
}
func writeTestFile(t *testing.T, path string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte("test"), 0644); err != nil {
t.Fatal(err)
}
}
func pathUnder(root string, parts ...string) string {
return filepath.Join(append([]string{root}, parts...)...)
}
func rootedPath(parts ...string) string {
return string(filepath.Separator) + filepath.Join(parts...)
}