Ophestra Umiker
584732f80a
All checks were successful
test / test (push) Successful in 19s
This change also fixes a deadlock when shim fails to connect and complete the setup. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
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
|
|
}
|