From 268a90f1a505a00e1eab794e9c1760fdff5592d3 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sat, 15 Feb 2025 14:45:09 +0900 Subject: [PATCH] app: improve WAYLAND_DISPLAY correctness This now has identical behaviour as wayland C library. Signed-off-by: Ophestra --- internal/app/app_nixos_test.go | 2 +- internal/app/app_pd_test.go | 2 +- internal/app/share.go | 35 +++++++++++++++++----------------- internal/system/wayland.go | 4 ++++ test.nix | 3 +++ wl/consts.go | 15 +++++++++++++++ 6 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 wl/consts.go diff --git a/internal/app/app_nixos_test.go b/internal/app/app_nixos_test.go index 062bfe0..18a42e1 100644 --- a/internal/app/app_nixos_test.go +++ b/internal/app/app_nixos_test.go @@ -102,7 +102,7 @@ var testCasesNixos = []sealTestCase{ "SHELL": "/run/current-system/sw/bin/zsh", "TERM": "xterm-256color", "USER": "u0_a1", - "WAYLAND_DISPLAY": "/run/user/1971/wayland-0", + "WAYLAND_DISPLAY": "wayland-0", "XDG_RUNTIME_DIR": "/run/user/1971", "XDG_SESSION_CLASS": "user", "XDG_SESSION_TYPE": "tty", diff --git a/internal/app/app_pd_test.go b/internal/app/app_pd_test.go index 2d042a2..269c8aa 100644 --- a/internal/app/app_pd_test.go +++ b/internal/app/app_pd_test.go @@ -267,7 +267,7 @@ var testCasesPd = []sealTestCase{ "SHELL": "/run/current-system/sw/bin/zsh", "TERM": "xterm-256color", "USER": "chronos", - "WAYLAND_DISPLAY": "/run/user/65534/wayland-0", + "WAYLAND_DISPLAY": "wayland-0", "XDG_RUNTIME_DIR": "/run/user/65534", "XDG_SESSION_CLASS": "user", "XDG_SESSION_TYPE": "tty", diff --git a/internal/app/share.go b/internal/app/share.go index f9eec26..9e7d0f1 100644 --- a/internal/app/share.go +++ b/internal/app/share.go @@ -13,6 +13,7 @@ import ( "git.gensokyo.uk/security/fortify/internal/fmsg" "git.gensokyo.uk/security/fortify/internal/linux" "git.gensokyo.uk/security/fortify/internal/system" + "git.gensokyo.uk/security/fortify/wl" ) const ( @@ -27,9 +28,6 @@ const ( term = "TERM" display = "DISPLAY" - // https://manpages.debian.org/experimental/libwayland-doc/wl_display_connect.3.en.html - waylandDisplay = "WAYLAND_DISPLAY" - pulseServer = "PULSE_SERVER" pulseCookie = "PULSE_COOKIE" @@ -38,7 +36,6 @@ const ( ) var ( - ErrWayland = errors.New(waylandDisplay + " unset") ErrXDisplay = errors.New(display + " unset") ErrPulseCookie = errors.New("pulse cookie not present") @@ -144,34 +141,36 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os linux.System) error { // set up wayland if seal.et.Has(system.EWayland) { - var wp string - if wd, ok := os.LookupEnv(waylandDisplay); !ok { - return fmsg.WrapError(ErrWayland, - "WAYLAND_DISPLAY is not set") + var socketPath string + if name, ok := os.LookupEnv(wl.WaylandDisplay); !ok { + fmsg.VPrintln(wl.WaylandDisplay + " is not set, assuming " + wl.FallbackName) + socketPath = path.Join(seal.RuntimePath, wl.FallbackName) + } else if !path.IsAbs(name) { + socketPath = path.Join(seal.RuntimePath, name) } else { - wp = path.Join(seal.RuntimePath, wd) + socketPath = name } - w := path.Join(seal.sys.runtime, "wayland-0") - seal.sys.bwrap.SetEnv[waylandDisplay] = w + innerPath := path.Join(seal.sys.runtime, wl.FallbackName) + seal.sys.bwrap.SetEnv[wl.WaylandDisplay] = wl.FallbackName if !seal.directWayland { // set up security-context-v1 - wc := path.Join(seal.SharePath, "wayland") - wt := path.Join(wc, seal.id) - seal.sys.Ensure(wc, 0711) + socketDir := path.Join(seal.SharePath, "wayland") + outerPath := path.Join(socketDir, seal.id) + seal.sys.Ensure(socketDir, 0711) appID := seal.fid if appID == "" { // use instance ID in case app id is not set appID = "uk.gensokyo.fortify." + seal.id } - seal.sys.Wayland(wt, wp, appID, seal.id) - seal.sys.bwrap.Bind(wt, w) + seal.sys.Wayland(outerPath, socketPath, appID, seal.id) + seal.sys.bwrap.Bind(outerPath, innerPath) } else { // bind mount wayland socket (insecure) fmsg.VPrintln("direct wayland access, PROCEED WITH CAUTION") - seal.sys.bwrap.Bind(wp, w) + seal.sys.bwrap.Bind(socketPath, innerPath) // ensure Wayland socket ACL (e.g. `/run/user/%d/wayland-%d`) - seal.sys.UpdatePermType(system.EWayland, wp, acl.Read, acl.Write, acl.Execute) + seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute) } } diff --git a/internal/system/wayland.go b/internal/system/wayland.go index 7c23347..9646b46 100644 --- a/internal/system/wayland.go +++ b/internal/system/wayland.go @@ -38,6 +38,10 @@ func (w Wayland) apply(sys *I) error { } if err := w.conn.Attach(w.pair[1]); err != nil { + // make console output less nasty + if errors.Is(err, os.ErrNotExist) { + err = os.ErrNotExist + } return fmsg.WrapErrorSuffix(err, fmt.Sprintf("cannot attach to wayland on %q:", w.pair[1])) } else { diff --git a/test.nix b/test.nix index 5f41d40..f71d906 100644 --- a/test.nix +++ b/test.nix @@ -282,6 +282,9 @@ nixosTest { if output != "": raise Exception(f"unexpected output\n{output}") + # Verify graceful failure on bad Wayland display name: + print(machine.fail("sudo -u alice -i fortify -v run --wayland true")) + # Start fortify permissive defaults within Wayland session: fortify('-v run --wayland --dbus notify-send -a "NixOS Tests" "Test notification" "Notification from within sandbox." && touch /tmp/dbus-done') machine.wait_for_file("/tmp/dbus-done") diff --git a/wl/consts.go b/wl/consts.go new file mode 100644 index 0000000..2ad4028 --- /dev/null +++ b/wl/consts.go @@ -0,0 +1,15 @@ +package wl + +const ( + // WaylandDisplay contains the name of the server socket + // (https://gitlab.freedesktop.org/wayland/wayland/-/blob/1.23.1/src/wayland-client.c#L1147) + // which is concatenated with XDG_RUNTIME_DIR + // (https://gitlab.freedesktop.org/wayland/wayland/-/blob/1.23.1/src/wayland-client.c#L1171) + // or used as-is if absolute + // (https://gitlab.freedesktop.org/wayland/wayland/-/blob/1.23.1/src/wayland-client.c#L1176). + WaylandDisplay = "WAYLAND_DISPLAY" + + // FallbackName is used as the wayland socket name if WAYLAND_DISPLAY is unset + // (https://gitlab.freedesktop.org/wayland/wayland/-/blob/1.23.1/src/wayland-client.c#L1149). + FallbackName = "wayland-0" +)