Ophestra Umiker
2faf510146
The argument builder was written based on the incorrect assumption that bwrap arguments are unordered. The argument builder is replaced in this commit to correct that mistake. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
139 lines
3.9 KiB
Go
139 lines
3.9 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
|
|
"git.ophivana.moe/cat/fortify/acl"
|
|
"git.ophivana.moe/cat/fortify/dbus"
|
|
"git.ophivana.moe/cat/fortify/internal/state"
|
|
"git.ophivana.moe/cat/fortify/internal/verbose"
|
|
)
|
|
|
|
const (
|
|
dbusSessionBusAddress = "DBUS_SESSION_BUS_ADDRESS"
|
|
dbusSystemBusAddress = "DBUS_SYSTEM_BUS_ADDRESS"
|
|
)
|
|
|
|
var (
|
|
ErrDBusConfig = errors.New("dbus config not supplied")
|
|
)
|
|
|
|
type (
|
|
SealDBusError BaseError
|
|
LookupDBusError BaseError
|
|
StartDBusError BaseError
|
|
CloseDBusError BaseError
|
|
)
|
|
|
|
func (seal *appSeal) shareDBus(config [2]*dbus.Config) error {
|
|
if !seal.et.Has(state.EnableDBus) {
|
|
return nil
|
|
}
|
|
|
|
// session bus is mandatory
|
|
if config[0] == nil {
|
|
return (*SealDBusError)(wrapError(ErrDBusConfig, "attempted to seal session bus proxy with nil config"))
|
|
}
|
|
|
|
// system bus is optional
|
|
seal.sys.dbusSystem = config[1] != nil
|
|
|
|
// upstream address, downstream socket path
|
|
var sessionBus, systemBus [2]string
|
|
|
|
// downstream socket paths
|
|
sessionBus[1] = path.Join(seal.share, "bus")
|
|
systemBus[1] = path.Join(seal.share, "system_bus_socket")
|
|
|
|
// resolve upstream bus addresses
|
|
sessionBus[0], systemBus[0] = dbus.Address()
|
|
|
|
// create proxy instance
|
|
seal.sys.dbus = dbus.New(sessionBus, systemBus)
|
|
|
|
// seal dbus proxy
|
|
if err := seal.sys.dbus.Seal(config[0], config[1]); err != nil {
|
|
return (*SealDBusError)(wrapError(err, "cannot seal message bus proxy:", err))
|
|
}
|
|
|
|
// store addresses for cleanup and logging
|
|
seal.sys.dbusAddr = &[2][2]string{sessionBus, systemBus}
|
|
|
|
// share proxy sockets
|
|
sessionInner := path.Join(seal.sys.runtime, "bus")
|
|
seal.sys.setEnv(dbusSessionBusAddress, "unix:path="+sessionInner)
|
|
seal.sys.bwrap.Bind(sessionBus[1], sessionInner)
|
|
seal.sys.updatePerm(sessionBus[1], acl.Read, acl.Write)
|
|
if seal.sys.dbusSystem {
|
|
systemInner := "/run/dbus/system_bus_socket"
|
|
seal.sys.setEnv(dbusSystemBusAddress, "unix:path="+systemInner)
|
|
seal.sys.bwrap.Bind(systemBus[1], systemInner)
|
|
seal.sys.updatePerm(systemBus[1], acl.Read, acl.Write)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tx *appSealTx) startDBus() error {
|
|
// ready channel passed to dbus package
|
|
ready := make(chan error, 1)
|
|
// used by waiting goroutine to notify process return
|
|
tx.dbusWait = make(chan struct{})
|
|
|
|
// background dbus proxy start
|
|
if err := tx.dbus.Start(ready, os.Stderr, true); err != nil {
|
|
return (*StartDBusError)(wrapError(err, "cannot start message bus proxy:", err))
|
|
}
|
|
verbose.Println("starting message bus proxy:", tx.dbus)
|
|
verbose.Println("message bus proxy bwrap args:", tx.dbus.Bwrap())
|
|
|
|
// background wait for proxy instance and notify completion
|
|
go func() {
|
|
if err := tx.dbus.Wait(); err != nil {
|
|
fmt.Println("fortify: warn: message bus proxy returned error:", err)
|
|
go func() { ready <- err }()
|
|
} else {
|
|
verbose.Println("message bus proxy exit")
|
|
}
|
|
|
|
// ensure socket removal so ephemeral directory is empty at revert
|
|
if err := os.Remove(tx.dbusAddr[0][1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
fmt.Println("fortify: cannot remove dangling session bus socket:", err)
|
|
}
|
|
if tx.dbusSystem {
|
|
if err := os.Remove(tx.dbusAddr[1][1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
fmt.Println("fortify: cannot remove dangling system bus socket:", err)
|
|
}
|
|
}
|
|
|
|
// notify proxy completion
|
|
tx.dbusWait <- struct{}{}
|
|
}()
|
|
|
|
// ready is not nil if the proxy process faulted
|
|
if err := <-ready; err != nil {
|
|
// note that err here is either an I/O related error or a predetermined unexpected behaviour error
|
|
return (*StartDBusError)(wrapError(err, "message bus proxy fault after start:", err))
|
|
}
|
|
verbose.Println("message bus proxy ready")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tx *appSealTx) stopDBus() error {
|
|
if err := tx.dbus.Close(); err != nil {
|
|
if errors.Is(err, os.ErrClosed) {
|
|
return (*CloseDBusError)(wrapError(err, "message bus proxy already closed"))
|
|
} else {
|
|
return (*CloseDBusError)(wrapError(err, "cannot close message bus proxy:", err))
|
|
}
|
|
}
|
|
|
|
// block until proxy wait returns
|
|
<-tx.dbusWait
|
|
return nil
|
|
}
|