Subject: bug#74220: invisible cursor

From: Jared Finder <[email-masked]>
Date: Thu, 28 Nov 2024 13:45:49 -0800

On 2024-11-28 12:20, Eli Zaretskii wrote:
>> Date: Thu, 28 Nov 2024 10:21:53 -0800
>> From: Jared Finder <[email-masked]>
>> Cc: "Jared Finder via \"Bug reports for GNU Emacs, the Swiss army 
>> knife of
>>  text editors\"" <[email-masked]>, Robert Pluim 
>> <[email-masked]>,
>>  Gerd Möllmann <[email-masked]>, Eli Zaretskii
>>  <[email-masked]>, 74220 <[email-masked]>, Avraham Pinkas
>>  <[email-masked]>
>> 
>> This was an intentional change to Linux 6.7 to avoid a potential
>> privilege escalation. Specifically, apps without the capability
>> CAP_SYS_ADMIN are no longer able to set the kernel selection buffer.
>> Across Emacs versions, granting the Emacs binary the CAP_SYS_ADMIN
>> capability (sudo setcap cap_sys_admin+ep path/to/emacs) fixes the 
>> issue.
> 
> Sorry, I don't follow: what does setting the kernel selection buffer
> have to do with showing the cursor?  And how is it related to GPM?
> What am I missing here?
> 
>> But is this the right fix? CAP_SYS_ADMIN grants many dangerous
>> capabilities on Linux. An alternative fix would be to update redisplay
>> on terminals to draw the mouse cursor. Perhaps this is what is done on
>> other OSes? I would like guidance here on which path is recommended.
> 
> Let's first understand the problem better.
> 
> (And I'm guessing that by "cursor" you mean "mouse pointer"?)

Here's some more specifics:

Emacs draws the mouse pointer in handle_one_term_event in term.c. It 
does this by calling GPM_DrawPointer() with the intended x and y. This 
code is pretty old, a blame says it was from 2007.

GPM_DrawPointer is just a macro, see the GitHub mirror: 
https://github.com/telmich/gpm/blob/master/src/headers/gpm.h#L235. This 
calls a Linux ioctl() to draw the cursor. This code is also pretty old, 
a blame says it was from 2005.

The Linux ioctl() is called as follows, if it used symbolic constants 
and a struct instead of magic byte values:

struct {
     char  subcode;
     short xs, ys, xe, ye;
     short sel_mode;
} gpmbuf;

gpmbuf.subcode = TIOCL_SETSEL; // 2
gpmbuf.xs = gpmbuf.xe = x;
gpmbuf.ys = gpmbuf.ye = y;
gpmbuf.selmode = TIOCL_SELPOINTER; //3
ioctl(fd, TIOCLINUX, &gpmbuf);

This adds one other solution -- I could see if it is reasonable for the 
Linux kernel to not protect TIOCL_SELPOINTER while protecting the rest 
of TIOCL_SETSEL. I'm a bit nervous here as I don't understand the 
security implications of SELPOINTER vs other selections, though on first 
glance it seems reasonable.

   -- MJF