aboutsummaryrefslogtreecommitdiffhomepage
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus_test.go60
-rw-r--r--dbus/proc.go132
-rw-r--r--dbus/proxy.go7
-rw-r--r--dbus/samples_test.go4
4 files changed, 107 insertions, 96 deletions
diff --git a/dbus/dbus_test.go b/dbus/dbus_test.go
index 0b264dcf..b8391c3b 100644
--- a/dbus/dbus_test.go
+++ b/dbus/dbus_test.go
@@ -1,6 +1,7 @@
package dbus_test
import (
+ "bytes"
"context"
"errors"
"fmt"
@@ -12,6 +13,8 @@ import (
"git.gensokyo.uk/security/fortify/dbus"
"git.gensokyo.uk/security/fortify/helper"
+ "git.gensokyo.uk/security/fortify/internal"
+ "git.gensokyo.uk/security/fortify/internal/sandbox"
)
func TestNew(t *testing.T) {
@@ -103,6 +106,10 @@ func TestProxy_Seal(t *testing.T) {
}
func TestProxy_Start_Wait_Close_String(t *testing.T) {
+ oldWaitDelay := helper.WaitDelay
+ helper.WaitDelay = 16 * time.Second
+ t.Cleanup(func() { helper.WaitDelay = oldWaitDelay })
+
t.Run("sandbox", func(t *testing.T) {
proxyName := dbus.ProxyName
dbus.ProxyName = os.Args[0]
@@ -112,7 +119,7 @@ func TestProxy_Start_Wait_Close_String(t *testing.T) {
t.Run("direct", func(t *testing.T) { testProxyStartWaitCloseString(t, false) })
}
-func testProxyStartWaitCloseString(t *testing.T, sandbox bool) {
+func testProxyStartWaitCloseString(t *testing.T, useSandbox bool) {
for id, tc := range testCasePairs() {
// this test does not test errors
if tc[0].wantErr {
@@ -130,25 +137,28 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) {
t.Run("proxy for "+id, func(t *testing.T) {
p := dbus.New(tc[0].bus, tc[1].bus)
- p.CmdF = func(cmd *exec.Cmd) {
- wantArgv0 := dbus.ProxyName
- if sandbox {
- wantArgv0 = "bwrap"
- }
- if cmd.Args[0] != wantArgv0 {
- panic(fmt.Sprintf("unexpected argv0 %q", os.Args[0]))
- }
- cmd.Err = nil
- cmd.Path = os.Args[0]
-
- if sandbox {
- cmd.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"},
- append(cmd.Args[:5], append([]string{"-test.run=TestHelperStub", "--"}, cmd.Args[5:]...)...)...)
- cmd.Env = append(cmd.Env, "GO_TEST_FORTIFY_BWRAP_STUB_TYPE=dbus")
+ p.CommandContext = func(ctx context.Context) (cmd *exec.Cmd) {
+ return exec.CommandContext(ctx, os.Args[0], "-test.v",
+ "-test.run=TestHelperInit", "--", "init")
+ }
+ p.CmdF = func(v any) {
+ if useSandbox {
+ container := v.(*sandbox.Container)
+ if container.Args[0] != dbus.ProxyName {
+ panic(fmt.Sprintf("unexpected argv0 %q", os.Args[0]))
+ }
+ container.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"}, container.Args[1:]...)
} else {
+ cmd := v.(*exec.Cmd)
+ if cmd.Args[0] != dbus.ProxyName {
+ panic(fmt.Sprintf("unexpected argv0 %q", os.Args[0]))
+ }
+ cmd.Err = nil
+ cmd.Path = os.Args[0]
cmd.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"}, cmd.Args[1:]...)
}
}
+ p.FilterF = func(v []byte) []byte { return bytes.SplitN(v, []byte("TestHelperInit\n"), 2)[1] }
output := new(strings.Builder)
t.Run("unsealed", func(t *testing.T) {
@@ -163,7 +173,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) {
t.Run("start", func(t *testing.T) {
want := "proxy not sealed"
- if err := p.Start(context.Background(), nil, sandbox); err == nil || err.Error() != want {
+ if err := p.Start(context.Background(), nil, useSandbox); err == nil || err.Error() != want {
t.Errorf("Start() error = %v, wantErr %q",
err, errors.New(want))
return
@@ -200,18 +210,15 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
- if err := p.Start(ctx, output, sandbox); err != nil {
+ if err := p.Start(ctx, output, useSandbox); err != nil {
t.Fatalf("Start(nil, nil) error = %v",
err)
}
t.Run("string", func(t *testing.T) {
wantSubstr := fmt.Sprintf("%s -test.run=TestHelperStub -- --args=3 --fd=4", os.Args[0])
- if sandbox {
- wantSubstr = fmt.Sprintf(
- "%s -test.run=TestHelperStub -- bwrap --args 6 -- %s -test.run=TestHelperStub -- --args=3 --fd=4",
- os.Args[0], os.Args[0],
- )
+ if useSandbox {
+ wantSubstr = fmt.Sprintf(`argv: ["%s" "-test.run=TestHelperStub" "--" "--args=3" "--fd=4"], flags: 0x0, seccomp: 0x3e`, os.Args[0])
}
if got := p.String(); !strings.Contains(got, wantSubstr) {
t.Errorf("String() = %v, want %v",
@@ -232,3 +239,10 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) {
})
}
}
+
+func TestHelperInit(t *testing.T) {
+ if len(os.Args) != 5 || os.Args[4] != "init" {
+ return
+ }
+ sandbox.Init(internal.Exit)
+}
diff --git a/dbus/proc.go b/dbus/proc.go
index 15f02ac5..446ca90e 100644
--- a/dbus/proc.go
+++ b/dbus/proc.go
@@ -14,12 +14,13 @@ import (
"syscall"
"git.gensokyo.uk/security/fortify/helper"
- "git.gensokyo.uk/security/fortify/helper/bwrap"
+ "git.gensokyo.uk/security/fortify/internal/sandbox"
"git.gensokyo.uk/security/fortify/ldd"
+ "git.gensokyo.uk/security/fortify/seccomp"
)
// Start launches the D-Bus proxy.
-func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error {
+func (p *Proxy) Start(ctx context.Context, output io.Writer, useSandbox bool) error {
p.lock.Lock()
defer p.lock.Unlock()
@@ -30,11 +31,15 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error
var h helper.Helper
c, cancel := context.WithCancelCause(ctx)
- if !sandbox {
+ if !useSandbox {
h = helper.NewDirect(c, p.name, p.seal, true, argF, func(cmd *exec.Cmd) {
- cmdF(cmd, output, p.CmdF)
-
- // xdg-dbus-proxy does not need to inherit the environment
+ if p.CmdF != nil {
+ p.CmdF(cmd)
+ }
+ if output != nil {
+ cmd.Stdout, cmd.Stderr = output, output
+ }
+ cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Env = make([]string, 0)
}, nil)
} else {
@@ -47,64 +52,65 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error
}
}
- bc := &bwrap.Config{
- Hostname: "fortify-dbus",
- Chdir: "/",
- Syscall: &bwrap.SyscallPolicy{DenyDevel: true, Multiarch: true},
- Clearenv: true,
- NewSession: true,
- DieWithParent: true,
+ var libPaths []string
+ if entries, err := ldd.ExecFilter(ctx, p.CommandContext, p.FilterF, toolPath); err != nil {
+ return err
+ } else {
+ libPaths = ldd.Path(entries)
}
- // 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)
+ h = helper.New(
+ c, toolPath,
+ p.seal, true,
+ argF, func(container *sandbox.Container) {
+ container.Seccomp |= seccomp.FlagMultiarch
+ container.Hostname = "fortify-dbus"
+ container.CommandContext = p.CommandContext
+ if output != nil {
+ container.Stdout, container.Stderr = output, output
}
- }
- }
- // 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
- upstreamPaths = append(upstreamPaths, path.Dir(as[10:]))
- }
- }
- slices.Sort(upstreamPaths)
- upstreamPaths = slices.Compact(upstreamPaths)
- for _, name := range upstreamPaths {
- bc.Bind(name, name)
- }
+ if p.CmdF != nil {
+ p.CmdF(container)
+ }
- // 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)
- }
+ // these lib paths are unpredictable, so mount them first so they cannot cover anything
+ for _, name := range libPaths {
+ container.Bind(name, name, 0)
+ }
- // 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) },
- nil,
- bc, nil,
- )
- p.bwrap = bc
+ // 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
+ upstreamPaths = append(upstreamPaths, path.Dir(as[10:]))
+ }
+ }
+ slices.Sort(upstreamPaths)
+ upstreamPaths = slices.Compact(upstreamPaths)
+ for _, name := range upstreamPaths {
+ container.Bind(name, name, 0)
+ }
+
+ // 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 {
+ container.Bind(name, name, sandbox.BindWritable)
+ }
+
+ // xdg-dbus-proxy bin path
+ binPath := path.Dir(toolPath)
+ container.Bind(binPath, binPath, 0)
+ }, nil)
}
if err := h.Start(); err != nil {
@@ -170,13 +176,3 @@ func argF(argsFd, statFd int) []string {
return []string{"--args=" + strconv.Itoa(argsFd), "--fd=" + strconv.Itoa(statFd)}
}
}
-
-func cmdF(cmd *exec.Cmd, output io.Writer, cmdF func(cmd *exec.Cmd)) {
- cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
- if output != nil {
- cmd.Stdout, cmd.Stderr = output, output
- }
- if cmdF != nil {
- cmdF(cmd)
- }
-}
diff --git a/dbus/proxy.go b/dbus/proxy.go
index e7785fd8..209ae573 100644
--- a/dbus/proxy.go
+++ b/dbus/proxy.go
@@ -9,7 +9,6 @@ import (
"sync"
"git.gensokyo.uk/security/fortify/helper"
- "git.gensokyo.uk/security/fortify/helper/bwrap"
)
// ProxyName is the file name or path to the proxy program.
@@ -20,16 +19,18 @@ var ProxyName = "xdg-dbus-proxy"
// Once sealed, configuration changes will no longer be possible and attempting to do so will result in a panic.
type Proxy struct {
helper helper.Helper
- bwrap *bwrap.Config
ctx context.Context
cancel context.CancelCauseFunc
name string
session [2]string
system [2]string
- CmdF func(cmd *exec.Cmd)
+ CmdF func(any)
sysP bool
+ CommandContext func(ctx context.Context) (cmd *exec.Cmd)
+ FilterF func([]byte) []byte
+
seal io.WriterTo
lock sync.RWMutex
}
diff --git a/dbus/samples_test.go b/dbus/samples_test.go
index 75ed0225..31c163d5 100644
--- a/dbus/samples_test.go
+++ b/dbus/samples_test.go
@@ -7,9 +7,9 @@ import (
)
const (
- sampleHostPath = "/run/user/1971/bus"
+ sampleHostPath = "/tmp/bus"
sampleHostAddr = "unix:path=" + sampleHostPath
- sampleBindPath = "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/bus"
+ sampleBindPath = "/tmp/proxied_bus"
)
var samples = []dbusTestCase{