diff options
| author | Ophestra Umiker <cat@ophivana.moe> | 2024-11-02 03:03:44 +0900 |
|---|---|---|
| committer | Ophestra Umiker <cat@ophivana.moe> | 2024-11-02 03:13:57 +0900 |
| commit | 584732f80ab91afb349720cfb8e9979ed2ba173e (patch) | |
| tree | 8ef6ab9f8c9d3b8197682a53fb2c4a7b2ce8da55 /cmd/fshim/ipc/wayland.go | |
| parent | 4b7b899bb35fb4ea218dabe49a674f4d2f80e7f8 (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.go | 75 |
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 +} |
