forked from security/hakurei
This is way higher level than the container package and does not even work unless every path is mounted in the exact same location. This behaviour causes nothing but confusion and problems, Signed-off-by: Ophestra <cat@gensokyo.uk>
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package ldd
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
|
|
"hakurei.app/container"
|
|
"hakurei.app/container/seccomp"
|
|
)
|
|
|
|
const (
|
|
lddName = "ldd"
|
|
lddTimeout = 2 * time.Second
|
|
)
|
|
|
|
var (
|
|
msgStatic = []byte("Not a valid dynamic program")
|
|
msgStaticGlibc = []byte("not a dynamic executable")
|
|
)
|
|
|
|
func Exec(ctx context.Context, p string) ([]*Entry, error) {
|
|
c, cancel := context.WithTimeout(ctx, lddTimeout)
|
|
defer cancel()
|
|
|
|
var toolPath *container.Absolute
|
|
if s, err := exec.LookPath(lddName); err != nil {
|
|
return nil, err
|
|
} else if toolPath, err = container.NewAbsolute(s); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
z := container.NewCommand(c, toolPath.String(), lddName, p)
|
|
z.Hostname = "hakurei-" + lddName
|
|
z.SeccompFlags |= seccomp.AllowMultiarch
|
|
z.SeccompPresets |= seccomp.PresetStrict
|
|
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
|
|
z.Stdout = stdout
|
|
z.Stderr = stderr
|
|
z.Bind(container.FHSRoot, container.FHSRoot, 0).Proc(container.FHSProc).Dev(container.FHSProc, false)
|
|
|
|
if err := z.Start(); err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _, _ = io.Copy(os.Stderr, stderr) }()
|
|
if err := z.Serve(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := z.Wait(); err != nil {
|
|
m := stderr.Bytes()
|
|
if bytes.Contains(m, append([]byte(p+": "), msgStatic...)) ||
|
|
bytes.Contains(m, msgStaticGlibc) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
v := stdout.Bytes()
|
|
return Parse(v)
|
|
}
|