aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/app/app.go4
-rw-r--r--internal/app/seal.go44
-rw-r--r--internal/app/share.display.go6
-rw-r--r--internal/app/start.go19
-rw-r--r--internal/app/system.go42
-rw-r--r--internal/shim/parent.go17
-rw-r--r--internal/shim/wayland.go35
7 files changed, 94 insertions, 73 deletions
diff --git a/internal/app/app.go b/internal/app/app.go
index 4c3a60c3..5c5e3452 100644
--- a/internal/app/app.go
+++ b/internal/app/app.go
@@ -1,7 +1,6 @@
package app
import (
- "net"
"os/exec"
"sync"
)
@@ -27,9 +26,6 @@ type app struct {
cmd *exec.Cmd
// child process related information
seal *appSeal
-
- // wayland connection if wayland mediation is enabled
- wayland *net.UnixConn
// error returned waiting for process
waitErr error
diff --git a/internal/app/seal.go b/internal/app/seal.go
index d4b4efa7..7de6aecb 100644
--- a/internal/app/seal.go
+++ b/internal/app/seal.go
@@ -11,6 +11,7 @@ import (
"git.ophivana.moe/security/fortify/dbus"
"git.ophivana.moe/security/fortify/internal"
"git.ophivana.moe/security/fortify/internal/fmsg"
+ "git.ophivana.moe/security/fortify/internal/shim"
"git.ophivana.moe/security/fortify/internal/state"
"git.ophivana.moe/security/fortify/internal/system"
"git.ophivana.moe/security/fortify/internal/verbose"
@@ -36,6 +37,43 @@ var (
ErrMachineCtl = errors.New("machinectl not available")
)
+// appSeal seals the application with child-related information
+type appSeal struct {
+ // app unique ID string representation
+ id string
+ // wayland mediation, disabled if nil
+ wl *shim.Wayland
+
+ // freedesktop application ID
+ fid string
+ // argv to start process with in the final confined environment
+ command []string
+ // persistent process state store
+ store state.Store
+
+ // uint8 representation of launch method sealed from config
+ launchOption uint8
+ // process-specific share directory path
+ share string
+ // process-specific share directory path local to XDG_RUNTIME_DIR
+ shareLocal string
+
+ // path to launcher program
+ toolPath string
+ // pass-through enablement tracking from config
+ et system.Enablements
+
+ // prevents sharing from happening twice
+ shared bool
+ // seal system-level component
+ sys *appSealSys
+
+ // used in various sealing operations
+ internal.SystemConstants
+
+ // protected by upstream mutex
+}
+
// Seal seals the app launch context
func (a *app) Seal(config *Config) error {
a.lock.Lock()
@@ -176,10 +214,10 @@ func (a *app) Seal(config *Config) error {
seal.sys.bwrap.SetEnv = make(map[string]string)
}
- // create wayland client wait channel if mediated wayland is enabled
- // this channel being set enables mediated wayland setup later on
+ // create wayland struct and client wait channel if mediated wayland is enabled
+ // this field being set enables mediated wayland setup later on
if config.Confinement.Sandbox.Wayland {
- seal.wlDone = make(chan struct{})
+ seal.wl = shim.NewWayland()
}
// open process state store
diff --git a/internal/app/share.display.go b/internal/app/share.display.go
index 7c50b636..18fad7a7 100644
--- a/internal/app/share.display.go
+++ b/internal/app/share.display.go
@@ -34,7 +34,7 @@ func (seal *appSeal) shareDisplay() error {
if wd, ok := os.LookupEnv(waylandDisplay); !ok {
return fmsg.WrapError(ErrWayland,
"WAYLAND_DISPLAY is not set")
- } else if seal.wlDone == nil {
+ } else if seal.wl == nil {
// hardlink wayland socket
wp := path.Join(seal.RuntimePath, wd)
wpi := path.Join(seal.shareLocal, "wayland")
@@ -46,8 +46,8 @@ func (seal *appSeal) shareDisplay() error {
// ensure Wayland socket ACL (e.g. `/run/user/%d/wayland-%d`)
seal.sys.UpdatePermType(system.EWayland, wp, acl.Read, acl.Write, acl.Execute)
} else {
- // set wayland socket path (e.g. `/run/user/%d/wayland-%d`)
- seal.wl = path.Join(seal.RuntimePath, wd)
+ // set wayland socket path for mediation (e.g. `/run/user/%d/wayland-%d`)
+ seal.wl.Path = path.Join(seal.RuntimePath, wd)
}
}
diff --git a/internal/app/start.go b/internal/app/start.go
index 6d301028..3106a1e8 100644
--- a/internal/app/start.go
+++ b/internal/app/start.go
@@ -62,23 +62,19 @@ func (a *app) Start() error {
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.Stdin, a.cmd.Stdout, a.cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
a.cmd.Dir = a.seal.RunDirPath
- if wls, err := shim.ServeConfig(confSockPath, a.seal.sys.UID(), &shim.Payload{
+ if err := shim.ServeConfig(confSockPath, a.seal.sys.UID(), &shim.Payload{
Argv: a.seal.command,
Exec: shimExec,
Bwrap: a.seal.sys.bwrap,
- WL: a.seal.wlDone != nil,
+ WL: a.seal.wl != nil,
Verbose: verbose.Get(),
- }, a.seal.wl, a.seal.wlDone); err != nil {
+ }, a.seal.wl); err != nil {
return fmsg.WrapErrorSuffix(err,
- "cannot listen on shim socket:")
- } else {
- a.wayland = wls
+ "cannot serve shim setup:")
}
// start shim
@@ -185,9 +181,8 @@ 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 {
+ if a.seal.wl != nil {
+ if err := a.seal.wl.Close(); err != nil {
fmt.Println("fortify: cannot close wayland connection:", err)
}
}
diff --git a/internal/app/system.go b/internal/app/system.go
index 834bdc91..2fc413e7 100644
--- a/internal/app/system.go
+++ b/internal/app/system.go
@@ -5,51 +5,9 @@ import (
"git.ophivana.moe/security/fortify/dbus"
"git.ophivana.moe/security/fortify/helper/bwrap"
- "git.ophivana.moe/security/fortify/internal"
- "git.ophivana.moe/security/fortify/internal/state"
"git.ophivana.moe/security/fortify/internal/system"
)
-// appSeal seals the application with child-related information
-type appSeal struct {
- // 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
- command []string
- // persistent process state store
- store state.Store
-
- // uint8 representation of launch method sealed from config
- launchOption uint8
- // process-specific share directory path
- share string
- // process-specific share directory path local to XDG_RUNTIME_DIR
- shareLocal string
-
- // path to launcher program
- toolPath string
- // pass-through enablement tracking from config
- et system.Enablements
-
- // prevents sharing from happening twice
- shared bool
- // seal system-level component
- sys *appSealSys
-
- // used in various sealing operations
- internal.SystemConstants
-
- // protected by upstream mutex
-}
-
// appSealSys encapsulates app seal behaviour with OS interactions
type appSealSys struct {
bwrap *bwrap.Config
diff --git a/internal/shim/parent.go b/internal/shim/parent.go
index 9382db22..0e903838 100644
--- a/internal/shim/parent.go
+++ b/internal/shim/parent.go
@@ -14,19 +14,18 @@ import (
// called in the parent process
-func ServeConfig(socket string, uid int, payload *Payload, wl string, done chan struct{}) (*net.UnixConn, error) {
- var ws *net.UnixConn
+func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
if payload.WL {
- if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl, Net: "unix"}); err != nil {
- return nil, err
+ if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl.Path, Net: "unix"}); err != nil {
+ return err
} else {
verbose.Println("connected to wayland at", wl)
- ws = f
+ wl.UnixConn = f
}
}
if c, err := net.ListenUnix("unix", &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
- return nil, err
+ return err
} else {
verbose.Println("configuring shim on socket", socket)
if err = acl.UpdatePerm(socket, uid, acl.Read, acl.Write, acl.Execute); err != nil {
@@ -47,7 +46,7 @@ func ServeConfig(socket string, uid int, payload *Payload, wl string, done chan
if payload.WL {
// get raw connection
var rc syscall.RawConn
- if rc, err = ws.SyscallConn(); err != nil {
+ if rc, err = wl.SyscallConn(); err != nil {
fmt.Println("fortify: cannot obtain raw wayland connection:", err)
return
} else {
@@ -61,7 +60,7 @@ func ServeConfig(socket string, uid int, payload *Payload, wl string, done chan
_ = conn.Close()
// block until shim exits
- <-done
+ <-wl.done
verbose.Println("releasing wayland connection")
}); err != nil {
fmt.Println("fortify: cannot obtain wayland connection fd:", err)
@@ -79,6 +78,6 @@ func ServeConfig(socket string, uid int, payload *Payload, wl string, done chan
fmt.Println("fortify: cannot remove dangling shim socket:", err)
}
}()
- return ws, nil
+ return nil
}
}
diff --git a/internal/shim/wayland.go b/internal/shim/wayland.go
new file mode 100644
index 00000000..05f04278
--- /dev/null
+++ b/internal/shim/wayland.go
@@ -0,0 +1,35 @@
+package shim
+
+import (
+ "net"
+ "sync"
+)
+
+// Wayland implements wayland mediation.
+type Wayland struct {
+ // wayland socket path
+ Path string
+
+ // wayland connection
+ *net.UnixConn
+
+ connErr error
+ sync.Once
+ // wait for wayland client to exit
+ done chan struct{}
+}
+
+func (wl *Wayland) Close() error {
+ wl.Do(func() {
+ close(wl.done)
+ wl.connErr = wl.UnixConn.Close()
+ })
+
+ return wl.connErr
+}
+
+func NewWayland() *Wayland {
+ wl := new(Wayland)
+ wl.done = make(chan struct{})
+ return wl
+}