X security and GrabPointer
mrs at mythic-beasts.com
Mon Jun 12 05:56:44 PDT 2006
I am investigating access control in X and I'm interested in finding
some practical solutions for dealing with potentially untrustworthy
clients which might try to steal input, cause denial of service, etc.
I have seen the XACE/XSELinux patches
(http://dgoeddel.home.insightbb.com/X/). These are based on Xorg
6.8.2. Are there any more recent patches? I see from the Wiki
(http://wiki.x.org/wiki/ChangesForX11R72) that the plan is to merge
XACE and Xtsol into Xorg 7.2. Any news on that?
There are some security issues that XACE doesn't really cover. I have
some ideas for how to deal with them, and I thought I'd run them past
people on this list to see if you can spot any problems or have some
I'll start off with pointer grabs, in particular GrabPointer. This
can cause denial of service, because a client can grab the pointer and
never release the grab. (I'll leave aside synchronous passive grabs
Unlike with keyboard grabs, GrabPointer does not usually create a
problem of stealing input, because sensitive information
(e.g. passwords) is not usually entered via the mouse. The XSecurity
extension limits keyboard grabs, but it doesn't restrict pointer grabs
The main use for pointer grabs is to implement menus. A pointer grab
has three effects:
a) The grabbing client receives pointer events even when it doesn't
own the pointer window (i.e. the window under the pointer).
b) The grabbing client has a choice of whether the pointer event is
subsequently also delivered to the pointer window.
c) When pointer events are delivered to the grabbing client, they are
reported on the grab window, and not on the pointer window.
(a) is used by clients to close menus when the user clicks outside the
menu. This isn't harmful by itself. It would also not be harmful to
disable this. Disabling this would mean that the menu stays open when
you click outside the grabbing client's windows, but you would
typically still be able to close the menu by pressing Escape or by
clicking outside the menu but within the client's own windows. (The
client's ability to open top-level override-redirect windows is a
separate security issue which I will leave aside for now.)
(b): Some clients allow clicks outside the menu to be delivered to the
pointer window, while some block this delivery. Qt allows the
delivery. Gtk and XEmacs block the delivery. (At least for the
versions I tried.) If there is no limit on initiating pointer grabs,
the ability to block this delivery is harmful, and is what causes
denial of service. Disabling the ability to block the delivery of the
pointer event to the pointer window should not be harmful. It would
just make XEmacs' and Gtk's menus behave like Qt's menus in this
(c) is not harmful, because it doesn't change which client(s) the
event is reported to. Disabling this behaviour, however, is harmful,
because it stops menus from working in some clients. I tried
disabling GrabPointer entirely, and it stops XEmacs menus working in
the case where you click on the menubar and then click on the menu
item. The second click is ignored, presumably because it is not
reported on the window expected by XEmacs. (Dragging to select a menu
item, however, does work.)
So some options for handling GrabPointer are:
1. Ignore GrabPointer. This switches off (a), (b) and (c). This
stops some clients from working properly.
2. Introduce a "safe pointer grab" and change GrabPointer to use
this for untrusted clients. A safe pointer grab would do (c)
but not (a) or (b). The grab window would perhaps be a piece
of per-client state that affects how events are delivered for a
client, causing the window field to be modified. The normal
grab logic would get bypassed.
3. As with (2), introduce a safe pointer grab, but one that also does
(a). The server would record which client holds a safe pointer
grab. When a button press occurs over a window not owned by the
grabbing client, the button press event would be delivered twice:
to the grabbing client and to the pointer window.
This means menus will get closed as per normal behaviour.
However, it lets clients snoop on mouse button presses. It might
be a bit more complicated to implement than (2).
There is a related issue:
Gtk's pop-up menus do not work when Gtk is run as an untrusted client
under the XSecurity extension. Gtk tries to map an InputOnly window
as a child of the root window, which the XSecurity extension
disallows. Gtk attempts to use this InputOnly window as the grab
window in GrabPointer, but GrabPointer returns NotViewable, because
the window was not successfully mapped. Gtk gives up because
GrabPointer failed. If we change the grab logic, we could relax the
requirement that the grab window be mapped, which does not seem like a
very useful restriction anyway.
More information about the xorg