diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-03-15 23:57:44 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-03-16 00:01:25 +0900 |
| commit | 6e7ddb2d2ec6b163dc2c178bc4d73b5943f51206 (patch) | |
| tree | 37ffe1564782377c1983909362ed6109c3f06b28 /dbus | |
| parent | bac4e67867faa7d8274b684575140a65827d3a4c (diff) | |
helper: eliminate commandContext replacement
This is done more cleanly by modifying Args in cmdF.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'dbus')
| -rw-r--r-- | dbus/dbus_test.go | 66 | ||||
| -rw-r--r-- | dbus/proc.go (renamed from dbus/run.go) | 85 | ||||
| -rw-r--r-- | dbus/proxy.go | 2 | ||||
| -rw-r--r-- | dbus/samples_test.go | 37 | ||||
| -rw-r--r-- | dbus/stub_test.go | 4 |
5 files changed, 118 insertions, 76 deletions
diff --git a/dbus/dbus_test.go b/dbus/dbus_test.go index 57a441a4..0b264dcf 100644 --- a/dbus/dbus_test.go +++ b/dbus/dbus_test.go @@ -3,6 +3,9 @@ package dbus_test import ( "context" "errors" + "fmt" + "os" + "os/exec" "strings" "testing" "time" @@ -100,12 +103,13 @@ func TestProxy_Seal(t *testing.T) { } func TestProxy_Start_Wait_Close_String(t *testing.T) { - t.Run("sandboxed", func(t *testing.T) { + t.Run("sandbox", func(t *testing.T) { + proxyName := dbus.ProxyName + dbus.ProxyName = os.Args[0] + t.Cleanup(func() { dbus.ProxyName = proxyName }) testProxyStartWaitCloseString(t, true) }) - t.Run("direct", func(t *testing.T) { - testProxyStartWaitCloseString(t, false) - }) + t.Run("direct", func(t *testing.T) { testProxyStartWaitCloseString(t, false) }) } func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { @@ -125,14 +129,30 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { }) t.Run("proxy for "+id, func(t *testing.T) { - helper.InternalReplaceExecCommand(t) - overridePath(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") + } else { + cmd.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"}, cmd.Args[1:]...) + } + } output := new(strings.Builder) - t.Run("unsealed behaviour of "+id, func(t *testing.T) { - t.Run("unsealed string of "+id, func(t *testing.T) { + t.Run("unsealed", func(t *testing.T) { + t.Run("string", func(t *testing.T) { want := "(unsealed dbus proxy)" if got := p.String(); got != want { t.Errorf("String() = %v, want %v", @@ -141,7 +161,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { } }) - t.Run("unsealed start of "+id, func(t *testing.T) { + t.Run("start", func(t *testing.T) { want := "proxy not sealed" if err := p.Start(context.Background(), nil, sandbox); err == nil || err.Error() != want { t.Errorf("Start() error = %v, wantErr %q", @@ -150,7 +170,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { } }) - t.Run("unsealed wait of "+id, func(t *testing.T) { + t.Run("wait", func(t *testing.T) { wantErr := "dbus: not started" if err := p.Wait(); err == nil || err.Error() != wantErr { t.Errorf("Wait() error = %v, wantErr %v", @@ -168,7 +188,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { } }) - t.Run("sealed behaviour of "+id, func(t *testing.T) { + t.Run("sealed", func(t *testing.T) { want := strings.Join(append(tc[0].want, tc[1].want...), " ") if got := p.String(); got != want { t.Errorf("String() = %v, want %v", @@ -176,7 +196,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { return } - t.Run("sealed start of "+id, func(t *testing.T) { + t.Run("start", func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -185,8 +205,14 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { err) } - t.Run("started string of "+id, func(t *testing.T) { - wantSubstr := dbus.ProxyName + " --args=" + 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 got := p.String(); !strings.Contains(got, wantSubstr) { t.Errorf("String() = %v, want %v", p.String(), wantSubstr) @@ -194,7 +220,7 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { } }) - t.Run("started wait of "+id, func(t *testing.T) { + t.Run("wait", func(t *testing.T) { p.Close() if err := p.Wait(); err != nil { t.Errorf("Wait() error = %v\noutput: %s", @@ -206,11 +232,3 @@ func testProxyStartWaitCloseString(t *testing.T, sandbox bool) { }) } } - -func overridePath(t *testing.T) { - proxyName := dbus.ProxyName - dbus.ProxyName = "/nonexistent-xdg-dbus-proxy" - t.Cleanup(func() { - dbus.ProxyName = proxyName - }) -} diff --git a/dbus/run.go b/dbus/proc.go index 30b06f4e..379f9fd3 100644 --- a/dbus/run.go +++ b/dbus/proc.go @@ -8,6 +8,7 @@ import ( "os/exec" "path" "path/filepath" + "slices" "strconv" "strings" "syscall" @@ -26,25 +27,12 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error return errors.New("proxy not sealed") } - var ( - h helper.Helper - - argF = func(argsFd, statFd int) []string { - if statFd == -1 { - return []string{"--args=" + strconv.Itoa(argsFd)} - } else { - return []string{"--args=" + strconv.Itoa(argsFd), "--fd=" + strconv.Itoa(statFd)} - } - } - ) + var h helper.Helper c, cancel := context.WithCancelCause(ctx) if !sandbox { h = helper.NewDirect(c, p.name, p.seal, true, argF, func(cmd *exec.Cmd) { - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - if output != nil { - cmd.Stdout, cmd.Stderr = output, output - } + cmdF(cmd, output, p.CmdF) // xdg-dbus-proxy does not need to inherit the environment cmd.Env = make([]string, 0) @@ -62,7 +50,7 @@ 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 != "/nonexistent-xdg-dbus-proxy" { + if toolPath != os.Args[0] { if l, err := ldd.Exec(ctx, toolPath); err != nil { return err } else { @@ -71,7 +59,6 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error } bc := &bwrap.Config{ - Unshare: nil, Hostname: "fortify-dbus", Chdir: "/", Syscall: &bwrap.SyscallPolicy{DenyDevel: true, Multiarch: true}, @@ -81,28 +68,35 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error } // resolve proxy socket directories - bindTarget := make(map[string]struct{}, 2) + 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] == '/' { - bindTarget[pd] = struct{}{} + bindTargetM[pd] = struct{}{} } } } - for k := range bindTarget { - bc.Bind(k, k, false, true) + + 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) } - roBindTarget := make(map[string]struct{}, 2+1+len(proxyDeps)) + roBindTargetM := make(map[string]struct{}, 2+1+len(proxyDeps)) // xdb-dbus-proxy bin and dependencies - roBindTarget[path.Dir(toolPath)] = struct{}{} + roBindTargetM[path.Dir(toolPath)] = struct{}{} for _, ent := range proxyDeps { if path.IsAbs(ent.Path) { - roBindTarget[path.Dir(ent.Path)] = struct{}{} + roBindTargetM[path.Dir(ent.Path)] = struct{}{} } if path.IsAbs(ent.Name) { - roBindTarget[path.Dir(ent.Name)] = struct{}{} + roBindTargetM[path.Dir(ent.Name)] = struct{}{} } } @@ -110,20 +104,25 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error for _, as := range []string{p.session[0], p.system[0]} { if len(as) > 0 && strings.HasPrefix(as, "unix:path=/") { // leave / intact - roBindTarget[path.Dir(as[10:])] = struct{}{} + roBindTargetM[path.Dir(as[10:])] = struct{}{} } } - for k := range roBindTarget { - bc.Bind(k, k) + roBindTarget := make([]string, 0, len(roBindTargetM)) + for k := range roBindTargetM { + roBindTarget = append(roBindTarget, k) + } + slices.Sort(roBindTarget) + for _, name := range roBindTarget { + bc.Bind(name, name) } - h = helper.MustNewBwrap(c, toolPath, p.seal, true, argF, func(cmd *exec.Cmd) { - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - if output != nil { - cmd.Stdout, cmd.Stderr = output, output - } - }, nil, bc, nil) + h = helper.MustNewBwrap(c, toolPath, + p.seal, true, + argF, func(cmd *exec.Cmd) { cmdF(cmd, output, p.CmdF) }, + nil, + bc, nil, + ) p.bwrap = bc } @@ -182,3 +181,21 @@ func (p *Proxy) Close() { p.cancel(proxyClosed) p.cancel = nil } + +func argF(argsFd, statFd int) []string { + if statFd == -1 { + return []string{"--args=" + strconv.Itoa(argsFd)} + } else { + 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 5e92e341..e7785fd8 100644 --- a/dbus/proxy.go +++ b/dbus/proxy.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "os/exec" "sync" "git.gensokyo.uk/security/fortify/helper" @@ -26,6 +27,7 @@ type Proxy struct { name string session [2]string system [2]string + CmdF func(cmd *exec.Cmd) sysP bool seal io.WriterTo diff --git a/dbus/samples_test.go b/dbus/samples_test.go index 653a02f4..75ed0225 100644 --- a/dbus/samples_test.go +++ b/dbus/samples_test.go @@ -6,6 +6,12 @@ import ( "git.gensokyo.uk/security/fortify/dbus" ) +const ( + sampleHostPath = "/run/user/1971/bus" + sampleHostAddr = "unix:path=" + sampleHostPath + sampleBindPath = "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/bus" +) + var samples = []dbusTestCase{ { "org.chromium.Chromium", &dbus.Config{ @@ -19,10 +25,10 @@ var samples = []dbusTestCase{ Log: false, Filter: true, }, false, false, - [2]string{"unix:path=/run/user/1971/bus", "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/bus"}, + [2]string{sampleHostAddr, sampleBindPath}, []string{ - "unix:path=/run/user/1971/bus", - "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/bus", + sampleHostAddr, + sampleBindPath, "--filter", "--talk=org.freedesktop.Notifications", "--talk=org.freedesktop.FileManager1", @@ -48,9 +54,10 @@ var samples = []dbusTestCase{ Log: false, Filter: true, }, false, false, - [2]string{"unix:path=/run/dbus/system_bus_socket", "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/system_bus_socket"}, - []string{"unix:path=/run/dbus/system_bus_socket", - "/tmp/fortify.1971/12622d846cc3fe7b4c10359d01f0eb47/system_bus_socket", + [2]string{sampleHostAddr, sampleBindPath}, + []string{ + sampleHostAddr, + sampleBindPath, "--filter", "--talk=org.bluez", "--talk=org.freedesktop.Avahi", @@ -68,10 +75,10 @@ var samples = []dbusTestCase{ Log: false, Filter: true, }, false, false, - [2]string{"unix:path=/run/user/1971/bus", "/tmp/fortify.1971/34c24f16a0d791d28835ededaf446033/bus"}, + [2]string{sampleHostAddr, sampleBindPath}, []string{ - "unix:path=/run/user/1971/bus", - "/tmp/fortify.1971/34c24f16a0d791d28835ededaf446033/bus", + sampleHostAddr, + sampleBindPath, "--filter", "--talk=org.freedesktop.Notifications", "--talk=org.kde.StatusNotifierWatcher", @@ -91,10 +98,10 @@ var samples = []dbusTestCase{ Log: true, Filter: true, }, false, false, - [2]string{"unix:path=/run/user/1971/bus", "/tmp/fortify.1971/5da7845287a936efbc2fa75d7d81e501/bus"}, + [2]string{sampleHostAddr, sampleBindPath}, []string{ - "unix:path=/run/user/1971/bus", - "/tmp/fortify.1971/5da7845287a936efbc2fa75d7d81e501/bus", + sampleHostAddr, + sampleBindPath, "--filter", "--see=uk.gensokyo.CrashTestDummy1", "--talk=org.freedesktop.Notifications", @@ -114,10 +121,10 @@ var samples = []dbusTestCase{ Log: true, Filter: true, }, false, true, - [2]string{"unix:path=/run/user/1971/bus", "/tmp/fortify.1971/5da7845287a936efbc2fa75d7d81e501/bus"}, + [2]string{sampleHostAddr, sampleBindPath}, []string{ - "unix:path=/run/user/1971/bus", - "/tmp/fortify.1971/5da7845287a936efbc2fa75d7d81e501/bus", + sampleHostAddr, + sampleBindPath, "--filter", "--see=uk.gensokyo.CrashTestDummy", "--talk=org.freedesktop.Notifications", diff --git a/dbus/stub_test.go b/dbus/stub_test.go index b83deb20..13a7d1df 100644 --- a/dbus/stub_test.go +++ b/dbus/stub_test.go @@ -6,6 +6,4 @@ import ( "git.gensokyo.uk/security/fortify/helper" ) -func TestHelperChildStub(t *testing.T) { - helper.InternalChildStub() -} +func TestHelperStub(t *testing.T) { helper.InternalHelperStub() } |
