summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2025-07-23 10:37:04 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-08-15 16:39:36 +0200
commit865ad8469fa24de1559f247d9426ab01e5ce3a56 (patch)
treee6024bc4a2bb9e481c97d087aa99b0530d72347a
parentb2f4e9dc5010514c12ebe0fab5269b4ca2700f89 (diff)
downloadlinux-865ad8469fa24de1559f247d9426ab01e5ce3a56.tar.gz
linux-865ad8469fa24de1559f247d9426ab01e5ce3a56.tar.bz2
linux-865ad8469fa24de1559f247d9426ab01e5ce3a56.zip
HID: core: Harden s32ton() against conversion to 0 bits
commit a6b87bfc2ab5bccb7ad953693c85d9062aef3fdd upstream. Testing by the syzbot fuzzer showed that the HID core gets a shift-out-of-bounds exception when it tries to convert a 32-bit quantity to a 0-bit quantity. Ideally this should never occur, but there are buggy devices and some might have a report field with size set to zero; we shouldn't reject the report or the device just because of that. Instead, harden the s32ton() routine so that it returns a reasonable result instead of crashing when it is called with the number of bits set to 0 -- the same as what snto32() does. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-usb/68753a08.050a0220.33d347.0008.GAE@google.com/ Tested-by: syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com Fixes: dde5845a529f ("[PATCH] Generic HID layer - code split") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/613a66cd-4309-4bce-a4f7-2905f9bce0c9@rowland.harvard.edu Signed-off-by: Benjamin Tissoires <bentiss@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hid/hid-core.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b31b8a2fd540..b9748366c6d6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -66,8 +66,12 @@ static s32 snto32(__u32 value, unsigned int n)
static u32 s32ton(__s32 value, unsigned int n)
{
- s32 a = value >> (n - 1);
+ s32 a;
+ if (!value || !n)
+ return 0;
+
+ a = value >> (n - 1);
if (a && a != -1)
return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
return value & ((1 << n) - 1);