diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/app/start.go | 2 | ||||
| -rw-r--r-- | internal/priv/shim/main.go | 25 | ||||
| -rw-r--r-- | internal/system/dbus.go | 72 | ||||
| -rw-r--r-- | internal/system/op.go | 21 |
4 files changed, 37 insertions, 83 deletions
diff --git a/internal/app/start.go b/internal/app/start.go index aba331e7..837ab227 100644 --- a/internal/app/start.go +++ b/internal/app/start.go @@ -46,7 +46,7 @@ func (a *app) Run(ctx context.Context, rs *RunState) error { } // startup will go ahead, commit system setup - if err := a.seal.sys.Commit(); err != nil { + if err := a.seal.sys.Commit(ctx); err != nil { return err } a.seal.sys.needRevert = true diff --git a/internal/priv/shim/main.go b/internal/priv/shim/main.go index 4dccb876..4397cc37 100644 --- a/internal/priv/shim/main.go +++ b/internal/priv/shim/main.go @@ -1,10 +1,14 @@ package shim import ( + "context" "errors" "os" + "os/exec" + "os/signal" "path" "strconv" + "syscall" "git.gensokyo.uk/security/fortify/fst" "git.gensokyo.uk/security/fortify/helper" @@ -138,19 +142,22 @@ func Main() { ); err != nil { fmsg.Fatalf("malformed sandbox config: %v", err) } else { - cmd := b.Unwrap() - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + b.Stdin(os.Stdin).Stdout(os.Stdout).Stderr(os.Stderr) + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() // unreachable // run and pass through exit code - if err = b.Start(); err != nil { + if err = b.Start(ctx, false); err != nil { fmsg.Fatalf("cannot start target process: %v", err) } else if err = b.Wait(); err != nil { - fmsg.VPrintln("wait:", err) - } - if b.Unwrap().ProcessState != nil { - fmsg.Exit(b.Unwrap().ProcessState.ExitCode()) - } else { - fmsg.Exit(127) + var exitError *exec.ExitError + if !errors.As(err, &exitError) { + fmsg.Println("wait:", err) + fmsg.Exit(127) + panic("unreachable") + } + fmsg.Exit(exitError.ExitCode()) + panic("unreachable") } } } diff --git a/internal/system/dbus.go b/internal/system/dbus.go index 42208267..fd995bb0 100644 --- a/internal/system/dbus.go +++ b/internal/system/dbus.go @@ -3,7 +3,6 @@ package system import ( "bytes" "errors" - "os" "strings" "sync" @@ -26,9 +25,6 @@ func (sys *I) MustProxyDBus(sessionPath string, session *dbus.Config, systemPath func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath string) (func(), error) { d := new(DBus) - // used by waiting goroutine to notify process exit - d.done = make(chan struct{}) - // session bus is mandatory if session == nil { return nil, fmsg.WrapError(ErrDBusConfig, @@ -75,88 +71,34 @@ type DBus struct { out *scanToFmsg // whether system bus proxy is enabled system bool - // notification from goroutine waiting for dbus.Proxy - done chan struct{} } func (d *DBus) Type() Enablement { return Process } -func (d *DBus) apply(_ *I) error { +func (d *DBus) apply(sys *I) error { fmsg.VPrintf("session bus proxy on %q for upstream %q", d.proxy.Session()[1], d.proxy.Session()[0]) if d.system { fmsg.VPrintf("system bus proxy on %q for upstream %q", d.proxy.System()[1], d.proxy.System()[0]) } - // ready channel passed to dbus package - ready := make(chan error, 1) - - // background dbus proxy start - if err := d.proxy.Start(ready, d.out, true, true); err != nil { + // this starts the process and blocks until ready + if err := d.proxy.Start(sys.ctx, d.out, true); err != nil { + d.out.Dump() return fmsg.WrapErrorSuffix(err, "cannot start message bus proxy:") } fmsg.VPrintln("starting message bus proxy:", d.proxy) - if fmsg.Verbose() { // save the extra bwrap arg build when verbose logging is off - fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.BwrapStatic()) - } - - // background wait for proxy instance and notify completion - go func() { - if err := d.proxy.Wait(); err != nil { - fmsg.Println("message bus proxy exited with error:", err) - go func() { ready <- err }() - } else { - fmsg.VPrintln("message bus proxy exit") - } - - // ensure socket removal so ephemeral directory is empty at revert - if err := os.Remove(d.proxy.Session()[1]); err != nil && !errors.Is(err, os.ErrNotExist) { - fmsg.Println("cannot remove dangling session bus socket:", err) - } - if d.system { - if err := os.Remove(d.proxy.System()[1]); err != nil && !errors.Is(err, os.ErrNotExist) { - fmsg.Println("cannot remove dangling system bus socket:", err) - } - } - - // notify proxy completion - close(d.done) - }() - - // ready is not nil if the proxy process faulted - if err := <-ready; err != nil { - // dump message buffer as caller does not dump this - // in an early fault condition - d.out.Dump() - - // note that err here is either an I/O error or a predetermined unexpected behaviour error - return fmsg.WrapErrorSuffix(err, - "message bus proxy fault after start:") - } - fmsg.VPrintln("message bus proxy ready") - return nil } func (d *DBus) revert(_ *I, _ *Criteria) error { // criteria ignored here since dbus is always process-scoped fmsg.VPrintln("terminating message bus proxy") - - if err := d.proxy.Close(); err != nil { - if errors.Is(err, os.ErrClosed) { - return fmsg.WrapError(err, - "message bus proxy already closed") - } else { - return fmsg.WrapErrorSuffix(err, - "cannot stop message bus proxy:") - } - } - - // block until proxy wait returns - <-d.done - return nil + d.proxy.Close() + defer fmsg.VPrintln("message bus proxy exit") + return fmsg.WrapErrorSuffix(d.proxy.Wait(), "message bus proxy error:") } func (d *DBus) Is(o Op) bool { diff --git a/internal/system/op.go b/internal/system/op.go index d8479c7c..8a98fa78 100644 --- a/internal/system/op.go +++ b/internal/system/op.go @@ -1,6 +1,7 @@ package system import ( + "context" "errors" "os" "sync" @@ -57,10 +58,14 @@ func TypeString(e Enablement) string { type I struct { uid int ops []Op - sp *os.File + ctx context.Context + // sync fd passed to bwrap + sp *os.File - state [2]bool - lock sync.Mutex + // whether sys has been reverted + state bool + + lock sync.Mutex } func (sys *I) UID() int { @@ -85,14 +90,14 @@ func (sys *I) Equal(v *I) bool { return true } -func (sys *I) Commit() error { +func (sys *I) Commit(ctx context.Context) error { sys.lock.Lock() defer sys.lock.Unlock() - if sys.state[0] { + if sys.ctx != nil { panic("sys instance committed twice") } - sys.state[0] = true + sys.ctx = ctx sp := New(sys.uid) sp.ops = make([]Op, 0, len(sys.ops)) // prevent copies during commits @@ -125,10 +130,10 @@ func (sys *I) Revert(ec *Criteria) error { sys.lock.Lock() defer sys.lock.Unlock() - if sys.state[1] { + if sys.state { panic("sys instance reverted twice") } - sys.state[1] = true + sys.state = true // collect errors errs := make([]error, len(sys.ops)) |
