diff mbox series

[v2] tty: Permit some TIOCL_SETSEL modes without CAP_SYS_ADMIN

Message ID 20250110142122.1013222-1-gnoack@google.com (mailing list archive)
State Mainlined
Commit 2f83e38a095f8bf7c6029883d894668b03b9bd93
Headers show
Series [v2] tty: Permit some TIOCL_SETSEL modes without CAP_SYS_ADMIN | expand

Commit Message

Günther Noack Jan. 10, 2025, 2:21 p.m. UTC
With this, processes without CAP_SYS_ADMIN are able to use TIOCLINUX with
subcode TIOCL_SETSEL, in the selection modes TIOCL_SETPOINTER,
TIOCL_SELCLEAR and TIOCL_SELMOUSEREPORT.

TIOCL_SETSEL was previously changed to require CAP_SYS_ADMIN, as this IOCTL
let callers change the selection buffer and could be used to simulate
keypresses.  These three TIOCL_SETSEL selection modes, however, are safe to
use, as they do not modify the selection buffer.

This fixes a mouse support regression that affected Emacs (invisible mouse
cursor).

Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/ee3ec63269b43b34e1c90dd8c9743bf8@finder.org
Fixes: 8d1b43f6a6df ("tty: Restrict access to TIOCLINUX' copy-and-paste subcommands")
Signed-off-by: Günther Noack <gnoack@google.com>
---
Changes in V2:

 * Removed comment in vt.c (per Greg's suggestion)

 * CC'd stable@

 * I *kept* the CAP_SYS_ADMIN check *after* copy_from_user(),
   with the reasoning that:

   1. I do not see a good alternative to reorder the code here.
      We need the data from copy_from_user() in order to know whether
      the CAP_SYS_ADMIN check even needs to be performed.
   2. A previous get_user() from an adjacent memory region already worked
      (making this a very unlikely failure)

I would still appreciate a more formal Tested-by from Hanno (hint, hint) :)

---
 drivers/tty/vt/selection.c | 14 ++++++++++++++
 drivers/tty/vt/vt.c        |  2 --
 2 files changed, 14 insertions(+), 2 deletions(-)

Comments

Kees Cook Jan. 10, 2025, 4:50 p.m. UTC | #1
On Fri, Jan 10, 2025 at 02:21:22PM +0000, Günther Noack wrote:
> With this, processes without CAP_SYS_ADMIN are able to use TIOCLINUX with
> subcode TIOCL_SETSEL, in the selection modes TIOCL_SETPOINTER,
> TIOCL_SELCLEAR and TIOCL_SELMOUSEREPORT.
> 
> TIOCL_SETSEL was previously changed to require CAP_SYS_ADMIN, as this IOCTL
> let callers change the selection buffer and could be used to simulate
> keypresses.  These three TIOCL_SETSEL selection modes, however, are safe to
> use, as they do not modify the selection buffer.
> 
> This fixes a mouse support regression that affected Emacs (invisible mouse
> cursor).
> 
> Cc: stable@vger.kernel.org
> Link: https://lore.kernel.org/r/ee3ec63269b43b34e1c90dd8c9743bf8@finder.org
> Fixes: 8d1b43f6a6df ("tty: Restrict access to TIOCLINUX' copy-and-paste subcommands")
> Signed-off-by: Günther Noack <gnoack@google.com>

Reviewed-by: Kees Cook <kees@kernel.org>
Greg Kroah-Hartman Jan. 12, 2025, 1:14 p.m. UTC | #2
On Fri, Jan 10, 2025 at 02:21:22PM +0000, Günther Noack wrote:
> With this, processes without CAP_SYS_ADMIN are able to use TIOCLINUX with
> subcode TIOCL_SETSEL, in the selection modes TIOCL_SETPOINTER,
> TIOCL_SELCLEAR and TIOCL_SELMOUSEREPORT.
> 
> TIOCL_SETSEL was previously changed to require CAP_SYS_ADMIN, as this IOCTL
> let callers change the selection buffer and could be used to simulate
> keypresses.  These three TIOCL_SETSEL selection modes, however, are safe to
> use, as they do not modify the selection buffer.
> 
> This fixes a mouse support regression that affected Emacs (invisible mouse
> cursor).
> 
> Cc: stable@vger.kernel.org
> Link: https://lore.kernel.org/r/ee3ec63269b43b34e1c90dd8c9743bf8@finder.org
> Fixes: 8d1b43f6a6df ("tty: Restrict access to TIOCLINUX' copy-and-paste subcommands")
> Signed-off-by: Günther Noack <gnoack@google.com>
> ---
> Changes in V2:
> 
>  * Removed comment in vt.c (per Greg's suggestion)
> 
>  * CC'd stable@
> 
>  * I *kept* the CAP_SYS_ADMIN check *after* copy_from_user(),
>    with the reasoning that:
> 
>    1. I do not see a good alternative to reorder the code here.
>       We need the data from copy_from_user() in order to know whether
>       the CAP_SYS_ADMIN check even needs to be performed.
>    2. A previous get_user() from an adjacent memory region already worked
>       (making this a very unlikely failure)
> 
> I would still appreciate a more formal Tested-by from Hanno (hint, hint) :)

This really is v3, as you sent a v2 last year, right?

b4 got really confused, but I think I figured it out.  Whenever you
resend, bump the version number please, otherwise it causes problems.
Remember, some of use deal with thousands of patches a week...

thanks,

greg k-h
diff mbox series

Patch

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 564341f1a74f..0bd6544e30a6 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -192,6 +192,20 @@  int set_selection_user(const struct tiocl_selection __user *sel,
 	if (copy_from_user(&v, sel, sizeof(*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.
+	 */
+	switch (v.sel_mode) {
+	case TIOCL_SELCLEAR:
+	case TIOCL_SELPOINTER:
+	case TIOCL_SELMOUSEREPORT:
+		break;
+	default:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+	}
+
 	return set_selection_kernel(&v, tty);
 }
 
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 96842ce817af..be5564ed8c01 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3345,8 +3345,6 @@  int tioclinux(struct tty_struct *tty, unsigned long arg)
 
 	switch (type) {
 	case TIOCL_SETSEL:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
 		return set_selection_user(param, tty);
 	case TIOCL_PASTESEL:
 		if (!capable(CAP_SYS_ADMIN))