mirror of https://github.com/encounter/SDL.git
Prevent keystrokes from leaking through to the console when using evdev.
This uses the same method Weston and X use. Sadly, to be fully effective when launching remotely, this needs root permissions.
This commit is contained in:
parent
074a1c4c63
commit
e9d2133934
|
@ -148,5 +148,8 @@ this determining the CAPS LOCK behavior:
|
||||||
Notes
|
Notes
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
* Input events from the keyboard leak through to the console
|
* When launching apps remotely (via SSH), SDL can prevent local keystrokes from
|
||||||
|
leaking into the console only if it has root privileges. Launching apps locally
|
||||||
|
does not suffer from this issue.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,18 @@ static _THIS = NULL;
|
||||||
#include <linux/keyboard.h>
|
#include <linux/keyboard.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* We need this to prevent keystrokes from appear in the console */
|
||||||
|
#ifndef KDSKBMUTE
|
||||||
|
#define KDSKBMUTE 0x4B51
|
||||||
|
#endif
|
||||||
|
#ifndef KDSKBMODE
|
||||||
|
#define KDSKBMODE 0x4B45
|
||||||
|
#endif
|
||||||
|
#ifndef K_OFF
|
||||||
|
#define K_OFF 0x04
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_assert.h"
|
#include "SDL_assert.h"
|
||||||
#include "SDL_endian.h"
|
#include "SDL_endian.h"
|
||||||
|
@ -370,6 +382,72 @@ static int SDL_EVDEV_get_console_fd(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent keystrokes from reaching the tty */
|
||||||
|
static int SDL_EVDEV_mute_keyboard(int tty, int *kb_mode)
|
||||||
|
{
|
||||||
|
char arg;
|
||||||
|
|
||||||
|
*kb_mode = 0; /* FIXME: Is this a sane default in case KDGKBMODE fails? */
|
||||||
|
if (!IS_CONSOLE(tty)) {
|
||||||
|
return SDL_SetError("Tried to mute an invalid tty");
|
||||||
|
}
|
||||||
|
ioctl(tty, KDGKBMODE, kb_mode); /* It's not fatal if this fails */
|
||||||
|
if (ioctl(tty, KDSKBMUTE, 1) && ioctl(tty, KDSKBMODE, K_OFF)) {
|
||||||
|
return SDL_SetError("EVDEV: Failed muting keyboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the keyboard mode for given tty */
|
||||||
|
static void SDL_EVDEV_unmute_keyboard(int tty, int kb_mode)
|
||||||
|
{
|
||||||
|
if (ioctl(tty, KDSKBMUTE, 0) && ioctl(tty, KDSKBMODE, kb_mode)) {
|
||||||
|
SDL_Log("EVDEV: Failed restoring keyboard mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read /sys/class/tty/tty0/active and open the tty */
|
||||||
|
static int SDL_EVDEV_get_active_tty()
|
||||||
|
{
|
||||||
|
int fd, len;
|
||||||
|
char ttyname[NAME_MAX + 1];
|
||||||
|
char ttypath[PATH_MAX+1] = "/dev/";
|
||||||
|
char arg;
|
||||||
|
|
||||||
|
fd = open("/sys/class/tty/tty0/active", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return SDL_SetError("Could not determine which tty is active");
|
||||||
|
}
|
||||||
|
|
||||||
|
len = read(fd, ttyname, NAME_MAX);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (len <= 0) {
|
||||||
|
return SDL_SetError("Could not read which tty is active");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ttyname[len-1] == '\n') {
|
||||||
|
ttyname[len-1] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ttyname[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_strlcat(ttypath, ttyname, PATH_MAX);
|
||||||
|
fd = open(ttypath, O_RDWR | O_NOCTTY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return SDL_SetError("Could not open tty: %s", ttypath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_CONSOLE(fd)) {
|
||||||
|
close(fd);
|
||||||
|
return SDL_SetError("Invalid tty obtained: %s", ttypath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_EVDEV_Init(void)
|
SDL_EVDEV_Init(void)
|
||||||
{
|
{
|
||||||
|
@ -403,6 +481,19 @@ SDL_EVDEV_Init(void)
|
||||||
|
|
||||||
/* We need a physical terminal (not PTS) to be able to translate key code to symbols via the kernel tables */
|
/* We need a physical terminal (not PTS) to be able to translate key code to symbols via the kernel tables */
|
||||||
_this->console_fd = SDL_EVDEV_get_console_fd();
|
_this->console_fd = SDL_EVDEV_get_console_fd();
|
||||||
|
|
||||||
|
/* Mute the keyboard so keystrokes only generate evdev events and do not leak through to the console */
|
||||||
|
_this->tty = STDIN_FILENO;
|
||||||
|
if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
|
||||||
|
/* stdin is not a tty, probably we were launched remotely, so we try to disable the active tty */
|
||||||
|
_this->tty = SDL_EVDEV_get_active_tty();
|
||||||
|
if (_this->tty >= 0) {
|
||||||
|
if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
|
||||||
|
close(_this->tty);
|
||||||
|
_this->tty = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_this->ref_count += 1;
|
_this->ref_count += 1;
|
||||||
|
@ -429,6 +520,12 @@ SDL_EVDEV_Quit(void)
|
||||||
if (_this->console_fd >= 0) {
|
if (_this->console_fd >= 0) {
|
||||||
close(_this->console_fd);
|
close(_this->console_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_this->tty >= 0) {
|
||||||
|
SDL_EVDEV_unmute_keyboard(_this->tty, _this->kb_mode);
|
||||||
|
close(_this->tty);
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove existing devices */
|
/* Remove existing devices */
|
||||||
while(_this->first != NULL) {
|
while(_this->first != NULL) {
|
||||||
SDL_EVDEV_device_removed(_this->first->path);
|
SDL_EVDEV_device_removed(_this->first->path);
|
||||||
|
|
|
@ -43,6 +43,8 @@ typedef struct SDL_EVDEV_PrivateData
|
||||||
int numdevices;
|
int numdevices;
|
||||||
int ref_count;
|
int ref_count;
|
||||||
int console_fd;
|
int console_fd;
|
||||||
|
int kb_mode;
|
||||||
|
int tty;
|
||||||
} SDL_EVDEV_PrivateData;
|
} SDL_EVDEV_PrivateData;
|
||||||
|
|
||||||
extern int SDL_EVDEV_Init(void);
|
extern int SDL_EVDEV_Init(void);
|
||||||
|
|
Loading…
Reference in New Issue