aboutsummaryrefslogtreecommitdiffhomepage
path: root/ldd
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-03-14 17:51:29 +0900
committerOphestra <cat@gensokyo.uk>2025-03-14 17:55:55 +0900
commit4bb5d9780f3c46e942dc778d93c28391caee33c7 (patch)
treebe07ad4378fa9dda5f2615a9d5e07b71bd17c1e5 /ldd
parentf41fd946284aa30e7529bd92193632b20d77a2dd (diff)
ldd: run in native sandbox
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'ldd')
-rw-r--r--ldd/exec.go52
-rw-r--r--ldd/ldd.go5
-rw-r--r--ldd/ldd_test.go11
3 files changed, 30 insertions, 38 deletions
diff --git a/ldd/exec.go b/ldd/exec.go
index 5c51c6a2..4f77ae30 100644
--- a/ldd/exec.go
+++ b/ldd/exec.go
@@ -7,8 +7,7 @@ import (
"os/exec"
"time"
- "git.gensokyo.uk/security/fortify/helper"
- "git.gensokyo.uk/security/fortify/helper/bwrap"
+ "git.gensokyo.uk/security/fortify/internal/sandbox"
)
const lddTimeout = 2 * time.Second
@@ -18,34 +17,31 @@ var (
msgStaticGlibc = []byte("not a dynamic executable")
)
-func Exec(ctx context.Context, p string) ([]*Entry, error) {
- var h helper.Helper
-
- if toolPath, err := exec.LookPath("ldd"); err != nil {
- return nil, err
- } else if h, err = helper.NewBwrap(
- (&bwrap.Config{
- Hostname: "fortify-ldd",
- Chdir: "/",
- Syscall: &bwrap.SyscallPolicy{DenyDevel: true, Multiarch: true},
- NewSession: true,
- DieWithParent: true,
- }).Bind("/", "/").DevTmpfs("/dev"), toolPath, false,
- nil, func(_, _ int) []string { return []string{p} },
- nil, nil,
- ); err != nil {
- return nil, err
- }
-
- stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
- h.Stdout(stdout).Stderr(stderr)
+func Exec(ctx context.Context, p string) ([]*Entry, error) { return ExecFilter(ctx, nil, nil, p) }
+func ExecFilter(ctx context.Context,
+ commandContext func(context.Context) *exec.Cmd,
+ f func([]byte) []byte,
+ p string) ([]*Entry, error) {
c, cancel := context.WithTimeout(ctx, lddTimeout)
defer cancel()
- if err := h.Start(c, false); err != nil {
+ container := sandbox.New(c, "ldd", p)
+ container.Hostname = "fortify-ldd"
+ stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
+ container.Stdout = stdout
+ container.Stderr = stderr
+ container.Bind("/", "/", 0).Dev("/dev")
+
+ if commandContext != nil {
+ container.CommandContext = commandContext
+ }
+
+ if err := container.Start(); err != nil {
+ return nil, err
+ } else if err = container.Serve(); err != nil {
return nil, err
}
- if err := h.Wait(); err != nil {
+ if err := container.Wait(); err != nil {
m := stderr.Bytes()
if bytes.Contains(m, append([]byte(p+": "), msgStatic...)) ||
bytes.Contains(m, msgStaticGlibc) {
@@ -56,5 +52,9 @@ func Exec(ctx context.Context, p string) ([]*Entry, error) {
return nil, err
}
- return Parse(stdout)
+ v := stdout.Bytes()
+ if f != nil {
+ v = f(v)
+ }
+ return Parse(v)
}
diff --git a/ldd/ldd.go b/ldd/ldd.go
index 434fbab6..ca4156c4 100644
--- a/ldd/ldd.go
+++ b/ldd/ldd.go
@@ -2,7 +2,6 @@
package ldd
import (
- "fmt"
"math"
"path"
"strconv"
@@ -15,8 +14,8 @@ type Entry struct {
Location uint64 `json:"location"`
}
-func Parse(stdout fmt.Stringer) ([]*Entry, error) {
- payload := strings.Split(strings.TrimSpace(stdout.String()), "\n")
+func Parse(p []byte) ([]*Entry, error) {
+ payload := strings.Split(strings.TrimSpace(string(p)), "\n")
result := make([]*Entry, len(payload))
for i, ent := range payload {
diff --git a/ldd/ldd_test.go b/ldd/ldd_test.go
index 2e5d010c..9c348c3c 100644
--- a/ldd/ldd_test.go
+++ b/ldd/ldd_test.go
@@ -3,7 +3,6 @@ package ldd_test
import (
"errors"
"reflect"
- "strings"
"testing"
"git.gensokyo.uk/security/fortify/ldd"
@@ -34,10 +33,7 @@ libzstd.so.1 => /usr/lib/libzstd.so.1 7ff71bfd2000
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- stdout := new(strings.Builder)
- stdout.WriteString(tc.out)
-
- if _, err := ldd.Parse(stdout); !errors.Is(err, tc.wantErr) {
+ if _, err := ldd.Parse([]byte(tc.out)); !errors.Is(err, tc.wantErr) {
t.Errorf("Parse() error = %v, wantErr %v", err, tc.wantErr)
}
})
@@ -111,10 +107,7 @@ libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7ff71c0a4000)`,
}
for _, tc := range testCases {
t.Run(tc.file, func(t *testing.T) {
- stdout := new(strings.Builder)
- stdout.WriteString(tc.out)
-
- if got, err := ldd.Parse(stdout); err != nil {
+ if got, err := ldd.Parse([]byte(tc.out)); err != nil {
t.Errorf("Parse() error = %v", err)
} else if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Parse() got = %#v, want %#v", got, tc.want)