aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/fshim/ipc/wayland.go
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-11-02 03:03:44 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-11-02 03:13:57 +0900
commit584732f80ab91afb349720cfb8e9979ed2ba173e (patch)
tree8ef6ab9f8c9d3b8197682a53fb2c4a7b2ce8da55 /cmd/fshim/ipc/wayland.go
parent4b7b899bb35fb4ea218dabe49a674f4d2f80e7f8 (diff)
cmd: shim and init into separate binaries
This change also fixes a deadlock when shim fails to connect and complete the setup. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'cmd/fshim/ipc/wayland.go')
-rw-r--r--cmd/fshim/ipc/wayland.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/cmd/fshim/ipc/wayland.go b/cmd/fshim/ipc/wayland.go
new file mode 100644
index 00000000..132e74f4
--- /dev/null
+++ b/cmd/fshim/ipc/wayland.go
@@ -0,0 +1,75 @@
+package shim0
+
+import (
+ "fmt"
+ "net"
+ "sync"
+ "syscall"
+
+ "git.ophivana.moe/security/fortify/internal/fmsg"
+)
+
+// Wayland implements wayland mediation.
+type Wayland struct {
+ // wayland socket path
+ Path string
+
+ // wayland connection
+ conn *net.UnixConn
+
+ connErr error
+ sync.Once
+ // wait for wayland client to exit
+ done chan struct{}
+}
+
+func (wl *Wayland) WriteUnix(conn *net.UnixConn) error {
+ // connect to host wayland socket
+ if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl.Path, Net: "unix"}); err != nil {
+ return fmsg.WrapErrorSuffix(err,
+ fmt.Sprintf("cannot connect to wayland at %q:", wl.Path))
+ } else {
+ fmsg.VPrintf("connected to wayland at %q", wl.Path)
+ wl.conn = f
+ }
+
+ // set up for passing wayland socket
+ if rc, err := wl.conn.SyscallConn(); err != nil {
+ return fmsg.WrapErrorSuffix(err, "cannot obtain raw wayland connection:")
+ } else {
+ ec := make(chan error)
+ go func() {
+ // pass wayland connection fd
+ if err = rc.Control(func(fd uintptr) {
+ if _, _, err = conn.WriteMsgUnix(nil, syscall.UnixRights(int(fd)), nil); err != nil {
+ ec <- fmsg.WrapErrorSuffix(err, "cannot pass wayland connection to shim:")
+ return
+ }
+ ec <- nil
+
+ // block until shim exits
+ <-wl.done
+ fmsg.VPrintln("releasing wayland connection")
+ }); err != nil {
+ ec <- fmsg.WrapErrorSuffix(err, "cannot obtain wayland connection fd:")
+ return
+ }
+ }()
+ return <-ec
+ }
+}
+
+func (wl *Wayland) Close() error {
+ wl.Do(func() {
+ close(wl.done)
+ wl.connErr = wl.conn.Close()
+ })
+
+ return wl.connErr
+}
+
+func NewWayland() *Wayland {
+ wl := new(Wayland)
+ wl.done = make(chan struct{})
+ return wl
+}