From ad0034b09aaa76aca478304518c1394ba292a619 Mon Sep 17 00:00:00 2001 From: Ophestra Umiker Date: Sun, 20 Oct 2024 00:07:48 +0900 Subject: [PATCH] app: move app ID to app struct App ID is inherent to App, and it makes no sense to generate it as part of the app sealing process. Signed-off-by: Ophestra Umiker --- internal/app/app.go | 29 ++++++++++++++++++++++------- internal/app/id.go | 11 +++++------ internal/app/seal.go | 9 +-------- internal/app/share.runtime.go | 2 +- internal/app/share.system.go | 2 +- internal/app/start.go | 2 +- internal/app/system.go | 4 ++-- main.go | 8 +++++--- 8 files changed, 38 insertions(+), 29 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index a04ae74..4c3a60c 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -7,26 +7,39 @@ import ( ) type App interface { - Seal(config *Config) error + // ID returns a copy of App's unique ID. + ID() ID + // Start sets up the system and starts the App. Start() error + // Wait waits for App's process to exit and reverts system setup. Wait() (int, error) + // WaitErr returns error returned by the underlying wait syscall. WaitErr() error + + Seal(config *Config) error String() string } type app struct { + // application unique identifier + id *ID + // underlying user switcher process + cmd *exec.Cmd // child process related information seal *appSeal - // underlying fortified child process - cmd *exec.Cmd + // wayland connection if wayland mediation is enabled wayland *net.UnixConn // error returned waiting for process - wait error + waitErr error lock sync.RWMutex } +func (a *app) ID() ID { + return *a.id +} + func (a *app) String() string { if a == nil { return "(invalid fortified app)" @@ -47,9 +60,11 @@ func (a *app) String() string { } func (a *app) WaitErr() error { - return a.wait + return a.waitErr } -func New() App { - return new(app) +func New() (App, error) { + a := new(app) + a.id = new(ID) + return a, newAppID(a.id) } diff --git a/internal/app/id.go b/internal/app/id.go index e996a3a..6ca4831 100644 --- a/internal/app/id.go +++ b/internal/app/id.go @@ -5,14 +5,13 @@ import ( "encoding/hex" ) -type appID [16]byte +type ID [16]byte -func (a *appID) String() string { +func (a *ID) String() string { return hex.EncodeToString(a[:]) } -func newAppID() (*appID, error) { - a := &appID{} - _, err := rand.Read(a[:]) - return a, err +func newAppID(id *ID) error { + _, err := rand.Read(id[:]) + return err } diff --git a/internal/app/seal.go b/internal/app/seal.go index 9fd6dfb..d296aa9 100644 --- a/internal/app/seal.go +++ b/internal/app/seal.go @@ -53,18 +53,11 @@ func (a *app) Seal(config *Config) error { // create seal seal := new(appSeal) - // generate application ID - if id, err := newAppID(); err != nil { - return fmsg.WrapErrorSuffix(err, - "cannot generate application ID:") - } else { - seal.id = id - } - // fetch system constants seal.SystemConstants = internal.GetSC() // pass through config values + seal.id = a.id.String() seal.fid = config.ID seal.command = config.Command diff --git a/internal/app/share.runtime.go b/internal/app/share.runtime.go index 79570e6..f738013 100644 --- a/internal/app/share.runtime.go +++ b/internal/app/share.runtime.go @@ -32,7 +32,7 @@ func (seal *appSeal) shareRuntime() { seal.sys.UpdatePermType(system.User, seal.RuntimePath, acl.Execute) // ensure process-specific share local to XDG_RUNTIME_DIR (e.g. `/run/user/%d/fortify/%s`) - seal.shareLocal = path.Join(seal.RunDirPath, seal.id.String()) + seal.shareLocal = path.Join(seal.RunDirPath, seal.id) seal.sys.Ephemeral(system.Process, seal.shareLocal, 0700) seal.sys.UpdatePerm(seal.shareLocal, acl.Execute) } diff --git a/internal/app/share.system.go b/internal/app/share.system.go index 9b2565a..478885a 100644 --- a/internal/app/share.system.go +++ b/internal/app/share.system.go @@ -20,7 +20,7 @@ func (seal *appSeal) shareSystem() { // ensure process-specific share (e.g. `/tmp/fortify.%d/%s`) // acl is unnecessary as this directory is world executable - seal.share = path.Join(seal.SharePath, seal.id.String()) + seal.share = path.Join(seal.SharePath, seal.id) seal.sys.Ephemeral(system.Process, seal.share, 0701) // ensure child tmpdir parent directory (e.g. `/tmp/fortify.%d/tmpdir`) diff --git a/internal/app/start.go b/internal/app/start.go index a0d2906..314ade4 100644 --- a/internal/app/start.go +++ b/internal/app/start.go @@ -173,7 +173,7 @@ func (a *app) Wait() (int, error) { var exitError *exec.ExitError if !errors.As(err, &exitError) { // should be unreachable - a.wait = err + a.waitErr = err } // store non-zero return code diff --git a/internal/app/system.go b/internal/app/system.go index 240b38b..e0c869b 100644 --- a/internal/app/system.go +++ b/internal/app/system.go @@ -12,14 +12,14 @@ import ( // appSeal seals the application with child-related information type appSeal struct { - // application unique identifier - id *appID // wayland socket path if mediated wayland is enabled wl string // wait for wayland client to exit if mediated wayland is enabled, // (wlDone == nil) determines whether mediated wayland setup is performed wlDone chan struct{} + // app unique ID string representation + id string // freedesktop application ID fid string // argv to start process with in the final confined environment diff --git a/main.go b/main.go index d450f69..755853f 100644 --- a/main.go +++ b/main.go @@ -54,8 +54,10 @@ func main() { // invoke app r := 1 - a := app.New() - if err := a.Seal(loadConfig()); err != nil { + a, err := app.New() + if err != nil { + fatalf("cannot create app: %s\n", err) + } else if err = a.Seal(loadConfig()); err != nil { logBaseError(err, "fortify: cannot seal app:") } else if err = a.Start(); err != nil { logBaseError(err, "fortify: cannot start app:") @@ -65,7 +67,7 @@ func main() { } logWaitError(err) } - if err := a.WaitErr(); err != nil { + if err = a.WaitErr(); err != nil { fmt.Println("fortify: inner wait failed:", err) } os.Exit(r)