Skip to content
Permalink
Browse files

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.
  • Loading branch information
gabomdq committed Oct 13, 2013
1 parent 074a1c4 commit e9d21339345223698304772c60ca1175b618dd6d
Showing with 103 additions and 1 deletion.
  1. +4 −1 README-raspberrypi.txt
  2. +97 −0 src/input/evdev/SDL_evdev.c
  3. +2 −0 src/input/evdev/SDL_evdev.h
@@ -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.


@@ -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"
@@ -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)
{
@@ -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;
@@ -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);
@@ -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);

0 comments on commit e9d2133

Please sign in to comment.