joystick: Allow libudev to be disabled at runtime
Device enumeration via libudev can fail in a container for two reasons: * the netlink protocol between udevd and libudev is considered private, so there is no API guarantee that the version of libudev in a container will understand netlink messages from a dissimilar version of udevd on the host system; * the netlink protocol between udevd and libudev relies for security on being able to check the uid of each message, but in a container with a user namespace where host uid 0 is not mapped, the libudev client cannot distinguish between messages from host uid 0 and messages from a different, malicious user on the host To make this easier to experiment with, always compile the fallback code path even if libudev is disabled. libudev remains the default if enabled at compile time, but the fallback code path can be forced. Signed-off-by: Simon McVittie <smcv@collabora.com>
parent
72379ba510
commit
13e7d1a958
|
@ -84,6 +84,19 @@
|
|||
#define DEBUG_INPUT_EVENTS 1
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ENUMERATION_UNSET,
|
||||
ENUMERATION_LIBUDEV,
|
||||
ENUMERATION_FALLBACK
|
||||
} EnumerationMethod;
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
|
||||
#else
|
||||
const EnumerationMethod enumeration_method = ENUMERATION_FALLBACK;
|
||||
#endif
|
||||
|
||||
static int MaybeAddDevice(const char *path);
|
||||
#if SDL_USE_LIBUDEV
|
||||
static int MaybeRemoveDevice(const char *path);
|
||||
|
@ -108,10 +121,8 @@ static SDL_joylist_item *SDL_joylist = NULL;
|
|||
static SDL_joylist_item *SDL_joylist_tail = NULL;
|
||||
static int numjoysticks = 0;
|
||||
|
||||
#if !SDL_USE_LIBUDEV
|
||||
static Uint32 last_joy_detect_time;
|
||||
static time_t last_input_dir_mtime;
|
||||
#endif
|
||||
|
||||
#define test_bit(nr, addr) \
|
||||
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
|
||||
|
@ -147,15 +158,8 @@ IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, const char *nam
|
|||
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||
|
||||
static int
|
||||
IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
|
||||
GuessIsJoystick(int fd)
|
||||
{
|
||||
struct input_id inpid;
|
||||
Uint16 *guid16 = (Uint16 *)guid->data;
|
||||
char *name;
|
||||
char product_string[128];
|
||||
|
||||
#if !SDL_USE_LIBUDEV
|
||||
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
|
||||
unsigned long evbit[NBITS(EV_MAX)] = { 0 };
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
|
||||
|
@ -170,7 +174,22 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
|
|||
test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
|
||||
{
|
||||
struct input_id inpid;
|
||||
Uint16 *guid16 = (Uint16 *)guid->data;
|
||||
char *name;
|
||||
char product_string[128];
|
||||
|
||||
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
|
||||
if (enumeration_method == ENUMERATION_FALLBACK && !GuessIsJoystick(fd)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
||||
return 0;
|
||||
|
@ -484,11 +503,8 @@ static void SteamControllerDisconnectedCallback(int device_instance)
|
|||
}
|
||||
|
||||
static void
|
||||
LINUX_JoystickDetect(void)
|
||||
LINUX_FallbackJoystickDetect(void)
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_Poll();
|
||||
#else
|
||||
const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
|
||||
Uint32 now = SDL_GetTicks();
|
||||
|
||||
|
@ -519,7 +535,20 @@ LINUX_JoystickDetect(void)
|
|||
|
||||
last_joy_detect_time = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
LINUX_JoystickDetect(void)
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||
SDL_UDEV_Poll();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LINUX_FallbackJoystickDetect();
|
||||
}
|
||||
|
||||
HandlePendingRemovals();
|
||||
|
||||
|
@ -529,6 +558,17 @@ LINUX_JoystickDetect(void)
|
|||
static int
|
||||
LINUX_JoystickInit(void)
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
if (enumeration_method == ENUMERATION_UNSET) {
|
||||
if (SDL_getenv("SDL_JOYSTICK_DISABLE_UDEV") != NULL) {
|
||||
enumeration_method = ENUMERATION_FALLBACK;
|
||||
}
|
||||
else {
|
||||
enumeration_method = ENUMERATION_LIBUDEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* First see if the user specified one or more joysticks to use */
|
||||
if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
|
||||
char *envcopy, *envpath, *delim;
|
||||
|
@ -549,26 +589,30 @@ LINUX_JoystickInit(void)
|
|||
SteamControllerDisconnectedCallback);
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
return SDL_SetError("Could not initialize UDEV");
|
||||
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
return SDL_SetError("Could not initialize UDEV");
|
||||
}
|
||||
|
||||
/* Set up the udev callback */
|
||||
if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("Could not set up joystick <-> udev callback");
|
||||
}
|
||||
|
||||
/* Force a scan to build the initial device list */
|
||||
SDL_UDEV_Scan();
|
||||
}
|
||||
|
||||
/* Set up the udev callback */
|
||||
if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("Could not set up joystick <-> udev callback");
|
||||
}
|
||||
|
||||
/* Force a scan to build the initial device list */
|
||||
SDL_UDEV_Scan();
|
||||
#else
|
||||
/* Force immediate joystick detection */
|
||||
last_joy_detect_time = 0;
|
||||
last_input_dir_mtime = 0;
|
||||
|
||||
/* Report all devices currently present */
|
||||
LINUX_JoystickDetect();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Force immediate joystick detection */
|
||||
last_joy_detect_time = 0;
|
||||
last_input_dir_mtime = 0;
|
||||
|
||||
/* Report all devices currently present */
|
||||
LINUX_JoystickDetect();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1191,8 +1235,10 @@ LINUX_JoystickQuit(void)
|
|||
numjoysticks = 0;
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_DelCallback(joystick_udev_callback);
|
||||
SDL_UDEV_Quit();
|
||||
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||
SDL_UDEV_DelCallback(joystick_udev_callback);
|
||||
SDL_UDEV_Quit();
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_QuitSteamControllers();
|
||||
|
|
Loading…
Reference in New Issue