diff options
| author | Ophestra Umiker <cat@ophivana.moe> | 2024-10-11 01:55:33 +0900 |
|---|---|---|
| committer | Ophestra Umiker <cat@ophivana.moe> | 2024-10-11 01:55:33 +0900 |
| commit | b86fa6b4c91a2bf331ae4a50a5aa14b668efc4e6 (patch) | |
| tree | 2865bdf5b60f20199adb5a74bca0fa13b68ea315 /internal/shim/parent.go | |
| parent | 6eb712aec73b6679fe7e2f60e7d1a6607af0ad4a (diff) | |
shim: new shim implementation
This implementation of shim accepts configuration as a gob stream over a unix socket, with support for mediating access to wayland via WAYLAND_SOCKET fd. All configuration is now included in the payload, and child is started inside bwrap configured with supplied bwrap.Config.
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'internal/shim/parent.go')
| -rw-r--r-- | internal/shim/parent.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/internal/shim/parent.go b/internal/shim/parent.go new file mode 100644 index 00000000..7ffc1c41 --- /dev/null +++ b/internal/shim/parent.go @@ -0,0 +1,90 @@ +package shim + +import ( + "encoding/gob" + "errors" + "fmt" + "net" + "os" + "syscall" + + "git.ophivana.moe/cat/fortify/internal/verbose" +) + +// called in the parent process + +func ServeConfig(socket string, payload *Payload, wl string, done chan struct{}) (*net.UnixConn, error) { + var ws *net.UnixConn + if payload.WL { + if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl, Net: "unix"}); err != nil { + return nil, err + } else { + verbose.Println("connected to wayland at", wl) + ws = f + } + } + + if c, err := net.ListenUnix("unix", &net.UnixAddr{Name: socket, Net: "unix"}); err != nil { + return nil, err + } else { + verbose.Println("configuring shim on socket", socket) + if err = os.Chmod(socket, 0777); err != nil { + fmt.Println("fortify: cannot change permissions of shim setup socket:", err) + } + + go func() { + var conn *net.UnixConn + if conn, err = c.AcceptUnix(); err != nil { + fmt.Println("fortify: cannot accept connection from shim:", err) + } else { + if err = gob.NewEncoder(conn).Encode(*payload); err != nil { + fmt.Println("fortify: cannot stream shim payload:", err) + return + } + + if payload.WL { + // get raw connection + var rc syscall.RawConn + if rc, err = ws.SyscallConn(); err != nil { + fmt.Println("fortify: cannot obtain raw wayland connection:", err) + return + } else { + go func() { + // pass wayland socket fd + if err = rc.Control(func(fd uintptr) { + if _, _, err = conn.WriteMsgUnix(nil, syscall.UnixRights(int(fd)), nil); err != nil { + fmt.Println("fortify: cannot pass wayland connection to shim:", err) + return + } + _ = conn.Close() + + // block until shim exits + <-done + verbose.Println("releasing wayland connection") + }); err != nil { + fmt.Println("fortify: cannot obtain wayland connection fd:", err) + } + }() + } + } else { + _ = conn.Close() + } + } + if err = c.Close(); err != nil { + fmt.Println("fortify: cannot close shim socket:", err) + } + if err = os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) { + fmt.Println("fortify: cannot remove dangling shim socket:", err) + } + }() + return ws, nil + } +} + +// Try runs shim and stops execution if FORTIFY_SHIM is set. +func Try() { + if s, ok := os.LookupEnv(EnvShim); ok { + shim(s) + } + panic("unreachable") +} |
