When calling into hid_map_usage(), the passed event code is blindly stored as is, even if it doesn't fit in the associated bitmap. This event code can come from a variety of sources, including devices masquerading as input devices, only a bit more "programmable". Instead of taking the raw event code, sanitize it to the actual bitmap size and output a warning to let the user know. While we're at it, sanitize the hid_usage structure if the type isn't known, conveniently placing a NULL pointer as the bitmap in order to catch unexpected uses. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Marc Zyngier <maz@xxxxxxxxxx> --- include/linux/hid.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/linux/hid.h b/include/linux/hid.h index 875f71132b14..4cd87d0ec023 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -966,9 +966,6 @@ static inline void hid_map_usage(struct hid_input *hidinput, { struct input_dev *input = hidinput->input; - usage->type = type; - usage->code = c; - switch (type) { case EV_ABS: *bit = input->absbit; @@ -986,7 +983,20 @@ static inline void hid_map_usage(struct hid_input *hidinput, *bit = input->ledbit; *max = LED_MAX; break; + default: + *bit = NULL; + *max = 0; + usage->code = 0; + usage->type = 0; + return; } + + usage->type = type; + usage->code = c & *max; + + if (unlikely(usage->code != c)) + pr_warn_ratelimited("%s: Truncated code %d to %d for type %d\n", + input->name, c, usage->code, type); } /** @@ -1000,7 +1010,8 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput, __u8 type, __u16 c) { hid_map_usage(hidinput, usage, bit, max, type, c); - clear_bit(c, *bit); + if (*bit) + clear_bit(usage->code, *bit); } /** -- 2.27.0