Bug 2052502 - Fix out-of-bounds read in LinuxGamepad by sizing key_map/abs_map with KEY_CNT/ABS_CNT (Coverity CID 1585304) r=cmartin
key_map/abs_map were sized [KEY_MAX]/[ABS_MAX], but evdev admits EV_KEY codes up to KEY_MAX inclusive, so event.code == KEY_MAX read one past the end. Size the arrays and population loops with KEY_CNT/ABS_CNT (matching keyBits/absBits), and bound the untrusted event.code before indexing key_map. Differential Revision: https://phabricator.services.mozilla.com/D310336
This commit is contained in:
committed by
sledru@mozilla.com
parent
46c79bdb29
commit
b514f97e4d
@@ -61,11 +61,18 @@ struct Gamepad {
|
||||
guint source_id = UINT_MAX;
|
||||
char idstring[256] = {0};
|
||||
char devpath[PATH_MAX] = {0};
|
||||
uint8_t key_map[KEY_MAX] = {0};
|
||||
uint8_t abs_map[ABS_MAX] = {0};
|
||||
uint8_t key_map[KEY_CNT] = {0};
|
||||
uint8_t abs_map[ABS_CNT] = {0};
|
||||
std::unordered_map<uint16_t, input_absinfo> abs_info;
|
||||
};
|
||||
|
||||
// evdev admits key/abs codes up to KEY_MAX/ABS_MAX inclusive, so the maps must
|
||||
// have KEY_CNT/ABS_CNT (== *_MAX + 1) entries to index every valid code.
|
||||
static_assert(sizeof(Gamepad::key_map) > KEY_MAX,
|
||||
"key_map must hold every valid EV_KEY code (0..KEY_MAX)");
|
||||
static_assert(sizeof(Gamepad::abs_map) > ABS_MAX,
|
||||
"abs_map must hold every valid EV_ABS code (0..ABS_MAX)");
|
||||
|
||||
static inline bool LoadAbsInfo(int fd, Gamepad* gamepad, uint16_t code) {
|
||||
input_absinfo info{0};
|
||||
if (ioctl(fd, EVIOCGABS(code), &info) < 0) {
|
||||
@@ -224,7 +231,7 @@ void LinuxGamepadService::AddDevice(struct udev_device* dev) {
|
||||
}
|
||||
|
||||
// Now, go through the non-semantic buttons and handle them as extras
|
||||
for (uint16_t key = 0; key < KEY_MAX; key++) {
|
||||
for (uint16_t key = 0; key < KEY_CNT; key++) {
|
||||
// Skip standard buttons
|
||||
if (gamepad->isStandardGamepad &&
|
||||
std::find(kStandardButtons.begin(), kStandardButtons.end(), key) !=
|
||||
@@ -250,7 +257,7 @@ void LinuxGamepadService::AddDevice(struct udev_device* dev) {
|
||||
LoadAbsInfo(fd, gamepad.get(), ABS_HAT0Y);
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < ABS_MAX; ++i) {
|
||||
for (uint16_t i = 0; i < ABS_CNT; ++i) {
|
||||
if (gamepad->isStandardGamepad &&
|
||||
(std::find(kStandardAxes.begin(), kStandardAxes.end(), i) !=
|
||||
kStandardAxes.end() ||
|
||||
@@ -488,6 +495,11 @@ gboolean LinuxGamepadService::OnGamepadData(GIOChannel* source,
|
||||
|
||||
switch (event.type) {
|
||||
case EV_KEY:
|
||||
// event.code comes from the device and is untrusted; bound it before
|
||||
// indexing key_map.
|
||||
if (event.code >= KEY_CNT) {
|
||||
continue;
|
||||
}
|
||||
if (gamepad->isStandardGamepad) {
|
||||
if (gamepad->key_map[event.code] == 255) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user