app: port app to use the system package
This commit does away with almost all baggage left over from the Ego port. Error wrapping also got simplified. All API changes happens to be internal which means no changes to main except renaming of the BaseError type. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
@@ -1,15 +1,11 @@
|
||||
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 (
|
||||
@@ -17,122 +13,30 @@ const (
|
||||
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")
|
||||
sessionPath, systemPath := path.Join(seal.share, "bus"), 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))
|
||||
// configure dbus proxy
|
||||
if err := seal.sys.ProxyDBus(config[0], config[1], sessionPath, systemPath); err != nil {
|
||||
return 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 {
|
||||
seal.sys.bwrap.SetEnv[dbusSessionBusAddress] = "unix:path=" + sessionInner
|
||||
seal.sys.bwrap.Bind(sessionPath, sessionInner)
|
||||
seal.sys.UpdatePerm(sessionPath, acl.Read, acl.Write)
|
||||
if config[1] != nil {
|
||||
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)
|
||||
seal.sys.bwrap.SetEnv[dbusSystemBusAddress] = "unix:path=" + systemInner
|
||||
seal.sys.bwrap.Bind(systemPath, systemInner)
|
||||
seal.sys.UpdatePerm(systemPath, 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user