From 273d97af8502059193ccb6a188422f9d22eaf106 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 16 Mar 2025 01:20:09 +0900 Subject: [PATCH] ldd: lib paths resolve function This is what always happens right after a ldd call, so implement it here. Signed-off-by: Ophestra --- dbus/proc.go | 79 ++++++++++++------------------ helper/stub.go | 16 ++---- internal/sandbox/container_test.go | 23 ++------- ldd/path.go | 21 ++++++++ 4 files changed, 59 insertions(+), 80 deletions(-) create mode 100644 ldd/path.go diff --git a/dbus/proc.go b/dbus/proc.go index 379f9fd..15f02ac 100644 --- a/dbus/proc.go +++ b/dbus/proc.go @@ -38,7 +38,6 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error cmd.Env = make([]string, 0) }, nil) } else { - // look up absolute path if name is just a file name toolPath := p.name if filepath.Base(p.name) == p.name { if s, err := exec.LookPath(p.name); err != nil { @@ -48,16 +47,6 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error } } - // resolve libraries by parsing ldd output - var proxyDeps []*ldd.Entry - if toolPath != os.Args[0] { - if l, err := ldd.Exec(ctx, toolPath); err != nil { - return err - } else { - proxyDeps = l - } - } - bc := &bwrap.Config{ Hostname: "fortify-dbus", Chdir: "/", @@ -67,56 +56,48 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error DieWithParent: true, } - // resolve proxy socket directories - bindTargetM := make(map[string]struct{}, 2) - - for _, ps := range []string{p.session[1], p.system[1]} { - if pd := path.Dir(ps); len(pd) > 0 { - if pd[0] == '/' { - bindTargetM[pd] = struct{}{} + // these lib paths are unpredictable, so mount them first so they cannot cover anything + if toolPath != os.Args[0] { + if entries, err := ldd.Exec(ctx, toolPath); err != nil { + return err + } else { + for _, name := range ldd.Path(entries) { + bc.Bind(name, name) } } } - bindTarget := make([]string, 0, len(bindTargetM)) - for k := range bindTargetM { - bindTarget = append(bindTarget, k) - } - slices.Sort(bindTarget) - for _, name := range bindTarget { - bc.Bind(name, name, false, true) - } - - roBindTargetM := make(map[string]struct{}, 2+1+len(proxyDeps)) - - // xdb-dbus-proxy bin and dependencies - roBindTargetM[path.Dir(toolPath)] = struct{}{} - for _, ent := range proxyDeps { - if path.IsAbs(ent.Path) { - roBindTargetM[path.Dir(ent.Path)] = struct{}{} - } - if path.IsAbs(ent.Name) { - roBindTargetM[path.Dir(ent.Name)] = struct{}{} - } - } - - // resolve upstream bus directories + // upstream bus directories + upstreamPaths := make([]string, 0, 2) for _, as := range []string{p.session[0], p.system[0]} { if len(as) > 0 && strings.HasPrefix(as, "unix:path=/") { // leave / intact - roBindTargetM[path.Dir(as[10:])] = struct{}{} + upstreamPaths = append(upstreamPaths, path.Dir(as[10:])) } } - - roBindTarget := make([]string, 0, len(roBindTargetM)) - for k := range roBindTargetM { - roBindTarget = append(roBindTarget, k) - } - slices.Sort(roBindTarget) - for _, name := range roBindTarget { + slices.Sort(upstreamPaths) + upstreamPaths = slices.Compact(upstreamPaths) + for _, name := range upstreamPaths { bc.Bind(name, name) } + // parent directories of bind paths + sockDirPaths := make([]string, 0, 2) + if d := path.Dir(p.session[1]); path.IsAbs(d) { + sockDirPaths = append(sockDirPaths, d) + } + if d := path.Dir(p.system[1]); path.IsAbs(d) { + sockDirPaths = append(sockDirPaths, d) + } + slices.Sort(sockDirPaths) + sockDirPaths = slices.Compact(sockDirPaths) + for _, name := range sockDirPaths { + bc.Bind(name, name, false, true) + } + + // xdg-dbus-proxy bin path + binPath := path.Dir(toolPath) + bc.Bind(binPath, binPath) h = helper.MustNewBwrap(c, toolPath, p.seal, true, argF, func(cmd *exec.Cmd) { cmdF(cmd, output, p.CmdF) }, diff --git a/helper/stub.go b/helper/stub.go index 988004c..942f150 100644 --- a/helper/stub.go +++ b/helper/stub.go @@ -6,7 +6,6 @@ import ( "io" "os" "path" - "slices" "strconv" "strings" "syscall" @@ -147,17 +146,10 @@ func bwrapStub() { sc.Chdir = "/" sc.Syscall = &bwrap.SyscallPolicy{DenyDevel: true, Multiarch: true} sc.AsInit = false - - bindTarget := []string{"/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47"} - slices.Sort(bindTarget) - for _, name := range bindTarget { - sc.Bind(name, name, false, true) - } - roBindTarget := []string{"/run/user/1971", path.Dir(os.Args[0])} - slices.Sort(roBindTarget) - for _, name := range roBindTarget { - sc.Bind(name, name) - } + sc. + Bind("/run/user/1971", "/run/user/1971"). + Bind("/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47", "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47", false, true). + Bind(path.Dir(os.Args[0]), path.Dir(os.Args[0])) // manipulate extra files list so fd ends up as 5 efp.Append() diff --git a/internal/sandbox/container_test.go b/internal/sandbox/container_test.go index 566de75..1a629d9 100644 --- a/internal/sandbox/container_test.go +++ b/internal/sandbox/container_test.go @@ -7,8 +7,6 @@ import ( "log" "os" "os/exec" - "path" - "slices" "syscall" "testing" "time" @@ -94,23 +92,10 @@ func TestContainer(t *testing.T) { }, os.Args[0]); err != nil { log.Fatalf("ldd: %v", err) } else { - libPathsM := make(map[string]struct{}, len(entries)) - for _, ent := range entries { - if path.IsAbs(ent.Path) { - libPathsM[path.Dir(ent.Path)] = struct{}{} - } - if path.IsAbs(ent.Name) { - libPathsM[path.Dir(ent.Name)] = struct{}{} - } - } - libPaths = make([]string, 0, len(libPathsM)) - for name := range libPathsM { - libPaths = append(libPaths, name) - } - slices.Sort(libPaths) - for _, name := range libPaths { - container.Bind(name, name, 0) - } + libPaths = ldd.Path(entries) + } + for _, name := range libPaths { + container.Bind(name, name, 0) } mnt := make([]*check.Mntent, 0, 3+len(libPaths)) diff --git a/ldd/path.go b/ldd/path.go new file mode 100644 index 0000000..4e41ce7 --- /dev/null +++ b/ldd/path.go @@ -0,0 +1,21 @@ +package ldd + +import ( + "path" + "slices" +) + +// Path returns a deterministic, deduplicated slice of absolute directory paths in entries. +func Path(entries []*Entry) []string { + p := make([]string, 0, len(entries)*2) + for _, entry := range entries { + if path.IsAbs(entry.Path) { + p = append(p, path.Dir(entry.Path)) + } + if path.IsAbs(entry.Name) { + p = append(p, path.Dir(entry.Name)) + } + } + slices.Sort(p) + return slices.Compact(p) +}