mirror of https://github.com/encounter/SDL.git
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>
This commit is contained in:
parent
72379ba510
commit
13e7d1a958
|
@ -84,6 +84,19 @@
|
||||||
#define DEBUG_INPUT_EVENTS 1
|
#define DEBUG_INPUT_EVENTS 1
|
||||||
#endif
|
#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);
|
static int MaybeAddDevice(const char *path);
|
||||||
#if SDL_USE_LIBUDEV
|
#if SDL_USE_LIBUDEV
|
||||||
static int MaybeRemoveDevice(const char *path);
|
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 SDL_joylist_item *SDL_joylist_tail = NULL;
|
||||||
static int numjoysticks = 0;
|
static int numjoysticks = 0;
|
||||||
|
|
||||||
#if !SDL_USE_LIBUDEV
|
|
||||||
static Uint32 last_joy_detect_time;
|
static Uint32 last_joy_detect_time;
|
||||||
static time_t last_input_dir_mtime;
|
static time_t last_input_dir_mtime;
|
||||||
#endif
|
|
||||||
|
|
||||||
#define test_bit(nr, addr) \
|
#define test_bit(nr, addr) \
|
||||||
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
|
(((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 */
|
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||||
|
|
||||||
static int
|
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 evbit[NBITS(EV_MAX)] = { 0 };
|
||||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||||
unsigned long absbit[NBITS(ABS_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))) {
|
test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
|
||||||
return 0;
|
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) {
|
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -484,11 +503,8 @@ static void SteamControllerDisconnectedCallback(int device_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 */
|
const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
|
||||||
Uint32 now = SDL_GetTicks();
|
Uint32 now = SDL_GetTicks();
|
||||||
|
|
||||||
|
@ -519,7 +535,20 @@ LINUX_JoystickDetect(void)
|
||||||
|
|
||||||
last_joy_detect_time = now;
|
last_joy_detect_time = now;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LINUX_JoystickDetect(void)
|
||||||
|
{
|
||||||
|
#if SDL_USE_LIBUDEV
|
||||||
|
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||||
|
SDL_UDEV_Poll();
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
LINUX_FallbackJoystickDetect();
|
||||||
|
}
|
||||||
|
|
||||||
HandlePendingRemovals();
|
HandlePendingRemovals();
|
||||||
|
|
||||||
|
@ -529,6 +558,17 @@ LINUX_JoystickDetect(void)
|
||||||
static int
|
static int
|
||||||
LINUX_JoystickInit(void)
|
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 */
|
/* First see if the user specified one or more joysticks to use */
|
||||||
if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
|
if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
|
||||||
char *envcopy, *envpath, *delim;
|
char *envcopy, *envpath, *delim;
|
||||||
|
@ -549,6 +589,7 @@ LINUX_JoystickInit(void)
|
||||||
SteamControllerDisconnectedCallback);
|
SteamControllerDisconnectedCallback);
|
||||||
|
|
||||||
#if SDL_USE_LIBUDEV
|
#if SDL_USE_LIBUDEV
|
||||||
|
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||||
if (SDL_UDEV_Init() < 0) {
|
if (SDL_UDEV_Init() < 0) {
|
||||||
return SDL_SetError("Could not initialize UDEV");
|
return SDL_SetError("Could not initialize UDEV");
|
||||||
}
|
}
|
||||||
|
@ -561,14 +602,17 @@ LINUX_JoystickInit(void)
|
||||||
|
|
||||||
/* Force a scan to build the initial device list */
|
/* Force a scan to build the initial device list */
|
||||||
SDL_UDEV_Scan();
|
SDL_UDEV_Scan();
|
||||||
#else
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
/* Force immediate joystick detection */
|
/* Force immediate joystick detection */
|
||||||
last_joy_detect_time = 0;
|
last_joy_detect_time = 0;
|
||||||
last_input_dir_mtime = 0;
|
last_input_dir_mtime = 0;
|
||||||
|
|
||||||
/* Report all devices currently present */
|
/* Report all devices currently present */
|
||||||
LINUX_JoystickDetect();
|
LINUX_JoystickDetect();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1191,8 +1235,10 @@ LINUX_JoystickQuit(void)
|
||||||
numjoysticks = 0;
|
numjoysticks = 0;
|
||||||
|
|
||||||
#if SDL_USE_LIBUDEV
|
#if SDL_USE_LIBUDEV
|
||||||
|
if (enumeration_method == ENUMERATION_LIBUDEV) {
|
||||||
SDL_UDEV_DelCallback(joystick_udev_callback);
|
SDL_UDEV_DelCallback(joystick_udev_callback);
|
||||||
SDL_UDEV_Quit();
|
SDL_UDEV_Quit();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_QuitSteamControllers();
|
SDL_QuitSteamControllers();
|
||||||
|
|
Loading…
Reference in New Issue