[PATCH RESEND] tty: Require CAP_SYS_ADMIN for all usages of TIOCL_SELMOUSEREPORT

From: Günther Noack
Date: Fri Apr 11 2025 - 03:02:22 EST


This requirement was overeagerly loosened in commit 2f83e38a095f
("tty: Permit some TIOCL_SETSEL modes without CAP_SYS_ADMIN"), but as
it turns out,

(1) the logic I implemented there was inconsistent (apologies!),

(2) TIOCL_SELMOUSEREPORT might actually be a small security risk
after all, and

(3) TIOCL_SELMOUSEREPORT is only meant to be used by the mouse
daemon (GPM or Consolation), which runs as CAP_SYS_ADMIN
already.

In more detail:

1. The previous patch has inconsistent logic:

In commit 2f83e38a095f ("tty: Permit some TIOCL_SETSEL modes
without CAP_SYS_ADMIN"), we checked for sel_mode ==
TIOCL_SELMOUSEREPORT, but overlooked that the lower four bits of
this "mode" parameter were actually used as an additional way to
pass an argument. So the patch did actually still require
CAP_SYS_ADMIN, if any of the mouse button bits are set, but did not
require it if none of the mouse buttons bits are set.

This logic is inconsistent and was not intentional. We should have
the same policies for using TIOCL_SELMOUSEREPORT independent of the
value of the "hidden" mouse button argument.

I sent a separate documentation patch to the man page list with
more details on TIOCL_SELMOUSEREPORT:
https://lore.kernel.org/all/20250223091342.35523-2-gnoack3000@xxxxxxxxx/

2. TIOCL_SELMOUSEREPORT is indeed a potential security risk which can
let an attacker simulate "keyboard" input to command line
applications on the same terminal, like TIOCSTI and some other
TIOCLINUX "selection mode" IOCTLs.

By enabling mouse reporting on a terminal and then injecting mouse
reports through TIOCL_SELMOUSEREPORT, an attacker can simulate
mouse movements on the same terminal, similar to the TIOCSTI
keystroke injection attacks that were previously possible with
TIOCSTI and other TIOCL_SETSEL selection modes.

Many programs (including libreadline/bash) are then prone to
misinterpret these mouse reports as normal keyboard input because
they do not expect input in the X11 mouse protocol form. The
attacker does not have complete control over the escape sequence,
but they can at least control the values of two consecutive bytes
in the binary mouse reporting escape sequence.

I went into more detail on that in the discussion at
https://lore.kernel.org/all/20250221.0a947528d8f3@xxxxxxxxxx/

It is not equally trivial to simulate arbitrary keystrokes as it
was with TIOCSTI (commit 83efeeeb3d04 ("tty: Allow TIOCSTI to be
disabled")), but the general mechanism is there, and together with
the small number of existing legit use cases (see below), it would
be better to revert back to requiring CAP_SYS_ADMIN for
TIOCL_SELMOUSEREPORT, as it was already the case before
commit 2f83e38a095f ("tty: Permit some TIOCL_SETSEL modes without
CAP_SYS_ADMIN").

3. TIOCL_SELMOUSEREPORT is only used by the mouse daemons (GPM or
Consolation), and they are the only legit use case:

To quote console_codes(4):

The mouse tracking facility is intended to return
xterm(1)-compatible mouse status reports. Because the console
driver has no way to know the device or type of the mouse, these
reports are returned in the console input stream only when the
virtual terminal driver receives a mouse update ioctl. These
ioctls must be generated by a mouse-aware user-mode application
such as the gpm(8) daemon.

Jared Finder has also confirmed in
https://lore.kernel.org/all/491f3df9de6593df8e70dbe77614b026@xxxxxxxxxx/
that Emacs does not call TIOCL_SELMOUSEREPORT directly, and it
would be difficult to find good reasons for doing that, given that
it would interfere with the reports that GPM is sending.

More information on the interaction between GPM, terminals and the
kernel with additional pointers is also available in this patch:
https://lore.kernel.org/all/a773e48920aa104a65073671effbdee665c105fc.1603963593.git.tammo.block@xxxxxxxxx/

For background on who else uses TIOCL_SELMOUSEREPORT: Debian Code
search finds one page of results, the only two known callers are
the two mouse daemons GPM and Consolation. (GPM does not show up
in the search results because it uses literal numbers to refer to
TIOCLINUX-related enums. I looked through GPM by hand instead.
TIOCL_SELMOUSEREPORT is also not used from libgpm.)
https://codesearch.debian.net/search?q=TIOCL_SELMOUSEREPORT

Cc: Jared Finder <jared@xxxxxxxxxx>
Cc: Jann Horn <jannh@xxxxxxxxxx>
Cc: Hanno Böck <hanno@xxxxxxxxx>
Cc: Jiri Slaby <jirislaby@xxxxxxxxxx>
Cc: Kees Cook <kees@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Fixes: 2f83e38a095f ("tty: Permit some TIOCL_SETSEL modes without CAP_SYS_ADMIN")
Signed-off-by: Günther Noack <gnoack3000@xxxxxxxxx>
---
drivers/tty/vt/selection.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 0bd6544e30a6b..791e2f1f7c0b6 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -193,13 +193,12 @@ int set_selection_user(const struct tiocl_selection __user *sel,
return -EFAULT;

/*
- * TIOCL_SELCLEAR, TIOCL_SELPOINTER and TIOCL_SELMOUSEREPORT are OK to
- * use without CAP_SYS_ADMIN as they do not modify the selection.
+ * TIOCL_SELCLEAR and TIOCL_SELPOINTER are OK to use without
+ * CAP_SYS_ADMIN as they do not modify the selection.
*/
switch (v.sel_mode) {
case TIOCL_SELCLEAR:
case TIOCL_SELPOINTER:
- case TIOCL_SELMOUSEREPORT:
break;
default:
if (!capable(CAP_SYS_ADMIN))

base-commit: 27102b38b8ca7ffb1622f27bcb41475d121fb67f
--
2.48.1