Implementing X11 access control
There are two places that X11 access control can be implemented:
- in the X server itself, or
- in another process that proxies the X11 connection.
There are also two approaches for doing access control:
- Add checks to accept or deny various X requests.
- Define an object layer for X objects. Convert between the X11 protocol and the object layer in both directions, but do access control in the object layer.
XACE/XSELinux take the first choice in both cases, inserting checks within the existing X server code base. This is not surprising considering that SELinux takes the same approach with Linux. XACE is Xorg's equivalent to Linux's LSM hooks.
Defining an object layer and mapping to and from it is the approach that Plash takes with POSIX.
These two choices are orthogonal:
- A proxy can translate to and from an object layer (rebuilding requests before passing them on), or it can simply accept/deny requests (passing on accepted requests unmodified). For the latter, it may or may not need to store state about X objects depending on what basis it is doing the checks.
- An object-capability layer can be moved into the X server.
Why not take the object-layer approach for X as well as POSIX? X is a lot more complicated than POSIX. It involves more requests and object types. It covers event delivery. X windows cannot be individually transparently forwarded because they form a tree and X windows can be reparented. On the plus side, there should be no race conditions with X (there is no equivalent of symlinks in POSIX).
Possible code to reuse for proxy
X protocol monitor proxies
Libraries
- XCB: Xlib replacement, uses an XML-based specification of the X protocol and its extensions
- python-xlib:
- Python-native X library
- Quite old, last updated 2002
- Request definitions written in Python. Would prefer XCB's definitions
- No server side: no decoding of X requests
- Method call interface unnecessary for our purposes
Using Xnest as a basis for a proxy
Xnest implements an X display as a window inside another X display. Each Xnest window is implemented by a corresponding X window on the host X server.
Would it be possible to change Xnest so that top-level Xnest windows appear as top-level windows on the host? i.e. Do what the Cygwin X server does. Probably not easy.
Xnest is part of the Xorg codebase and shares a lot of code with normal X servers. This includes input handling (keyboard and mouse). The window ID on incoming mouse events is ignored, and mouse events are redispatched according to Xnest's window tree. This means that the layout of Xnest windows must be duplicated in their underlying host windows, otherwise events will be dispatched to the wrong Xnest window.
xpra
xpra forwards an X window from one X server (such as the headless Xvfb) to another using the X damage extension. It can provide functionality similar to Xnest, except that:
- it is rootless: it forwards top-level windows, rather than the whole root window;
- it does not implement an X server itself; it simply forwards between X servers;
- it works at the pixmap level.
xpra has similar use cases to xmove, which allows X clients to be moved between servers, except that xmove implements a server itself.
x2x
x2x has support for forwarding the X clipboard between two displays. It is a tool for sharing a keyboard and mouse between two X displays.
Similar tools:
propsel will do the same without sharing the keyboard and mouse.
