- commit
- d560e68d628f2c30c16904b8c391495bb8f308cc
- parent
- 2fbf46a5745f4ad5deca7c7c4840d614fadfb1bd
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2025-10-11 15:19
add post on wayland security
Diffstat
| A | _content/posts/2025-10-03-wayland-security/index.md | 122 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 files changed, 122 insertions, 0 deletions
diff --git a/_content/posts/2025-10-03-wayland-security/index.md b/_content/posts/2025-10-03-wayland-security/index.md
@@ -0,0 +1,122 @@ -1 1 --- -1 2 title: Privileged Wayland Clients -1 3 date: 2025-10-03 -1 4 tags: [wayland, security] -1 5 description: "How do privileged clients in Wayland work exactly? Well, it's complicated." -1 6 --- -1 7 -1 8 When Wayland arrived on the scene some time around 2013, it promised increased -1 9 security: in X11, any client can monitor the inputs and outputs of other -1 10 clients. This allows to implement useful features such as screenshot tools and -1 11 virtual keyboards, but also malicious tools like screen scrapers and -1 12 keyloggers. So in the name of security, Wayland did away with all of that. -1 13 -1 14 This resulted in a bit of a [divide in the -1 15 community](https://blogs.kde.org/2020/10/11/linux-desktop-shell-ipc-wayland-vs-d-bus-and-lack-agreement-when-use-them/): -1 16 Some projects (like Gnome) chose to implement the missing features directly -1 17 in their compositor. Other projects (like wlroots) wanted to go with a more -1 18 modular approach where users could mix and match components. So they went ahead -1 19 and defined Wayland protocol extensions for the missing features. -1 20 -1 21 To avoid reintroducing all the security issues of X11, these protocol -1 22 extensions are intended to only be used by "privileged clients". How does that -1 23 work exactly? -1 24 -1 25 ## Identifying Clients -1 26 -1 27 Well, it's complicated. -1 28 -1 29 Say sway wants to delegate screenshots to -1 30 [flameshot](https://github.com/flameshot-org/flameshot/). It could use -1 31 `wl_client_get_credentials()` to get the PID of each client and then use -1 32 `wl_display_set_global_filter()` to block access to the relevant interfaces -1 33 unless `/proc/PID/exe` links to the flameshot binary. -1 34 -1 35 While this sounds good in theory, it has a couple of issues: `/proc/PID/exe` -1 36 can be faked using `LD_PRELOAD`, and accessing `/proc/` is vulnerable to race -1 37 conditions. -1 38 -1 39 Discussion quickly [shifted towards -1 40 sandboxing](https://gitlab.freedesktop.org/wayland/weston/-/issues/206#note_183479), -1 41 because processes that are not sandboxed can read all of the user's files, -1 42 which already is the worst case scenario, and can change the compositor's -1 43 configuration, which nullifies any restrictions defined there. It was decided -1 44 that any efforts to restrict access to privileged interfaces should focus on -1 45 sandboxed application. Unsandboxed applications would always be privileged. -1 46 -1 47 This lead to the -1 48 [security-context](https://wayland.app/protocols/security-context-v1) protocol -1 49 extension, which allows sandboxing engines like Flatpak to use a separate, -1 50 tagged socket for sandboxed applications.[^1] Most compositors simply block -1 51 access to all privileged interfaces for such clients. -1 52 -1 53 While this is progress, there are still a lot of unsandboxed applications, and -1 54 I do not see that changing any time soon. I think we can do better! -1 55 -1 56 [^1]: [way-secure](https://git.sr.ht/~whynothugo/way-secure) is another, -1 57 standalone implementation. -1 58 -1 59 ## Meaningful Interaction -1 60 -1 61 Another option would be to ask the user for confirmation every time a -1 62 privileged interface is accessed. However, [Matthias Clasen argued in -1 63 2019](https://www.youtube.com/watch?v=bIzJyp8sb70) that a simple confirm dialog -1 64 would just [annoy -1 65 users](https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1970#note_1288230). -1 66 So instead he recommends to require *meaningful interaction*. -1 67 -1 68 For example, when you try to pick a color in Gimp, the meaningful interaction -1 69 would be to select a pixel on the screen. In technical terms, Gimp could talk -1 70 to xdg-desktop-portal, which talks to a portal backend, which in turn has -1 71 privileged access to the compositor. In exchange for the privileged access, the -1 72 portal backend guarantees to prevent abuse by requiring a user interaction. -1 73 -1 74 The compositor still needs a reliable way to identity the portal backend. So -1 75 user interaction is not a solution to the privileged client issue. Instead, it -1 76 is a prerequisite that privileged clients have to satisfy. -1 77 -1 78 ## Is there a better way? -1 79 -1 80 When I press the "print" key on my keyboard, my compositor spawns -1 81 a screenshot tool (in my case `grim`), which then connects back to the -1 82 compositor. So far, we have tried to decide whether that tool should get access -1 83 to privileged interfaces when it connects, either based on its identity or on -1 84 user interaction. But at that point, the meaningful interaction has already -1 85 happened. The meaningful interaction was pressing the "print" key. -1 86 -1 87 This really clicked for me when I realized that all privileged clients are -1 88 spawned by the compositor, either on user interaction or on startup (in which -1 89 case they require meaningful user interaction themselves). We just need to find -1 90 a way to pass additional privileges to the process when it is spawned, without -1 91 allowing other processes to steal them. -1 92 -1 93 I found the answer in a [great article by Martin Roukala from 2014 -1 94 (!)](https://mupuf.org/blog/2014/02/19/wayland-compositors-why-and-how-to-handle/): -1 95 Usually, wayland clients use the `WAYLAND_DISPLAY` environment variable to find -1 96 the socket that they connect to. But there is also `WAYLAND_SOCKET`, which -1 97 tells them to use an already connected file descriptor instead. This way you -1 98 can pass an anonymous socket that cannot be accessed by any other process. -1 99 -1 100 Unfortunately, there is one major issues with this approach: The privileges -1 101 only apply to the first client, not any of its children. For example, `swayidle -1 102 timeout 600 swaylock` would not work because only `swayidle` would get the -1 103 privileged socket. `swaylock` would use the regular socket, without access to -1 104 the privileged `ext_session_lock_manager_v1` interface. -1 105 -1 106 Anyways, I implemented this approach for labwc in -1 107 [#3089](https://github.com/labwc/labwc/pull/3089). I have been using this -1 108 branch for a couple of days now, and it seems to work fine. I don't expect that -1 109 it will be merged though because it contains quite some breaking changes. -1 110 -1 111 ## Conclusion -1 112 -1 113 The status quo is that wlroots-based compositors implement privileged -1 114 interfaces, and any non-sandboxed processes can access them. That is way too -1 115 much attack surface for my taste. -1 116 -1 117 The big question for me is whether the `WAYLAND_SOCKET` approach I described -1 118 above is a step in the right direction or mere security theater. I have a hard -1 119 time deciding either way. -1 120 -1 121 Next I would like to look more into sandboxing to see if I can apply more -1 122 general restrictions, especially to terminal applications.