Skip to content

Commit

Permalink
Prevent keystrokes from leaking through to the console when using evdev.
Browse files Browse the repository at this point in the history
This uses the same method Weston and X use. Sadly, to be fully effective when
launching remotely, this needs root permissions.
  • Loading branch information
gabomdq committed Oct 13, 2013
1 parent 074a1c4 commit e9d2133
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
5 changes: 4 additions & 1 deletion README-raspberrypi.txt
Expand Up @@ -148,5 +148,8 @@ this determining the CAPS LOCK behavior:
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.


97 changes: 97 additions & 0 deletions src/input/evdev/SDL_evdev.c
Expand Up @@ -45,6 +45,18 @@ static _THIS = NULL;
#include <linux/keyboard.h>
#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_assert.h"
#include "SDL_endian.h"
Expand Down Expand Up @@ -370,6 +382,72 @@ static int SDL_EVDEV_get_console_fd(void)
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
SDL_EVDEV_Init(void)
{
Expand Down Expand Up @@ -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 */
_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;
Expand All @@ -429,6 +520,12 @@ SDL_EVDEV_Quit(void)
if (_this->console_fd >= 0) {
close(_this->console_fd);
}

if (_this->tty >= 0) {
SDL_EVDEV_unmute_keyboard(_this->tty, _this->kb_mode);
close(_this->tty);
}

/* Remove existing devices */
while(_this->first != NULL) {
SDL_EVDEV_device_removed(_this->first->path);
Expand Down
2 changes: 2 additions & 0 deletions src/input/evdev/SDL_evdev.h
Expand Up @@ -43,6 +43,8 @@ typedef struct SDL_EVDEV_PrivateData
int numdevices;
int ref_count;
int console_fd;
int kb_mode;
int tty;
} SDL_EVDEV_PrivateData;

extern int SDL_EVDEV_Init(void);
Expand Down

0 comments on commit e9d2133

Please sign in to comment.