forked from security/hakurei
app: migrate to new shim implementation
Both machinectl and sudo launch methods launch shim as shim is now responsible for setting up the sandbox. Various app structures are adapted to accommodate bwrap configuration and mediated wayland access. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
@@ -2,11 +2,16 @@ package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.ophivana.moe/cat/fortify/helper"
|
||||
"git.ophivana.moe/cat/fortify/internal/shim"
|
||||
"git.ophivana.moe/cat/fortify/internal/state"
|
||||
"git.ophivana.moe/cat/fortify/internal/verbose"
|
||||
)
|
||||
@@ -14,6 +19,8 @@ import (
|
||||
type (
|
||||
// ProcessError encapsulates errors returned by starting *exec.Cmd
|
||||
ProcessError BaseError
|
||||
// ShimError encapsulates errors returned by shim.ServeConfig.
|
||||
ShimError BaseError
|
||||
)
|
||||
|
||||
// Start starts the fortified child
|
||||
@@ -21,12 +28,30 @@ func (a *app) Start() error {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
|
||||
// resolve exec paths
|
||||
e := [2]string{helper.BubblewrapName}
|
||||
if len(a.seal.command) > 0 {
|
||||
e[1] = a.seal.command[0]
|
||||
}
|
||||
for i, n := range e {
|
||||
if len(n) == 0 {
|
||||
continue
|
||||
}
|
||||
if filepath.Base(n) == n {
|
||||
if s, err := exec.LookPath(n); err == nil {
|
||||
e[i] = s
|
||||
} else {
|
||||
return (*ProcessError)(wrapError(err, fmt.Sprintf("cannot find %q in PATH: %v", n, err)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.seal.sys.commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// select command builder
|
||||
var commandBuilder func() (args []string)
|
||||
var commandBuilder func(shimEnv string) (args []string)
|
||||
switch a.seal.launchOption {
|
||||
case LaunchMethodSudo:
|
||||
commandBuilder = a.commandBuilderSudo
|
||||
@@ -37,15 +62,30 @@ func (a *app) Start() error {
|
||||
}
|
||||
|
||||
// configure child process
|
||||
a.cmd = exec.Command(a.seal.toolPath, commandBuilder()...)
|
||||
confSockPath := path.Join(a.seal.share, "shim")
|
||||
a.cmd = exec.Command(a.seal.toolPath, commandBuilder(shim.EnvShim+"="+confSockPath)...)
|
||||
a.cmd.Env = []string{}
|
||||
a.cmd.Stdin = os.Stdin
|
||||
a.cmd.Stdout = os.Stdout
|
||||
a.cmd.Stderr = os.Stderr
|
||||
a.cmd.Dir = a.seal.RunDirPath
|
||||
|
||||
// start child process
|
||||
verbose.Println("starting main process:", a.cmd)
|
||||
if wls, err := shim.ServeConfig(confSockPath, &shim.Payload{
|
||||
Argv: a.seal.command,
|
||||
Env: a.seal.env,
|
||||
Exec: e,
|
||||
Bwrap: a.seal.bwrap,
|
||||
WL: a.seal.wlDone != nil,
|
||||
|
||||
Verbose: verbose.Get(),
|
||||
}, a.seal.wl, a.seal.wlDone); err != nil {
|
||||
return (*ShimError)(wrapError(err, "cannot listen on shim socket:", err))
|
||||
} else {
|
||||
a.wayland = wls
|
||||
}
|
||||
|
||||
// start shim
|
||||
verbose.Println("starting shim as target user:", a.cmd)
|
||||
if err := a.cmd.Start(); err != nil {
|
||||
return (*ProcessError)(wrapError(err, "cannot start process:", err))
|
||||
}
|
||||
@@ -62,11 +102,11 @@ func (a *app) Start() error {
|
||||
}
|
||||
|
||||
// register process state
|
||||
var e = new(StateStoreError)
|
||||
e.Inner, e.DoErr = a.seal.store.Do(func(b state.Backend) {
|
||||
e.InnerErr = b.Save(&sd)
|
||||
var err = new(StateStoreError)
|
||||
err.Inner, err.DoErr = a.seal.store.Do(func(b state.Backend) {
|
||||
err.InnerErr = b.Save(&sd)
|
||||
})
|
||||
return e.equiv("cannot save process state:", e)
|
||||
return err.equiv("cannot save process state:", e)
|
||||
}
|
||||
|
||||
// StateStoreError is returned for a failed state save
|
||||
@@ -146,6 +186,14 @@ func (a *app) Wait() (int, error) {
|
||||
|
||||
verbose.Println("process", strconv.Itoa(a.cmd.Process.Pid), "exited with exit code", r)
|
||||
|
||||
// close wayland connection
|
||||
if a.wayland != nil {
|
||||
close(a.seal.wlDone)
|
||||
if err := a.wayland.Close(); err != nil {
|
||||
fmt.Println("fortify: cannot close wayland connection:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// update store and revert app setup transaction
|
||||
e := new(StateStoreError)
|
||||
e.Inner, e.DoErr = a.seal.store.Do(func(b state.Backend) {
|
||||
@@ -187,7 +235,9 @@ func (a *app) Wait() (int, error) {
|
||||
ct = append(ct, i)
|
||||
}
|
||||
}
|
||||
verbose.Println("will revert operations tagged", ct, "as no remaining launchers hold these enablements")
|
||||
if len(ct) > 0 {
|
||||
verbose.Println("will revert operations tagged", ct, "as no remaining launchers hold these enablements")
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.seal.sys.revert(tags); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user