diff options
| author | Alan Stern <stern@rowland.harvard.edu> | 2025-12-03 11:24:50 +0000 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-12-07 06:12:45 +0900 |
| commit | 3c86548a20d7bc2861aa4de044991a327bebad1a (patch) | |
| tree | 9cceb68c6c111c594cbf06cc1dab04b324f3b6b1 | |
| parent | 66731f7ccb364d5d447f98dd2f02d015d31cc901 (diff) | |
HID: core: Harden s32ton() against conversion to 0 bits
[ Upstream commit a6b87bfc2ab5bccb7ad953693c85d9062aef3fdd ]
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>
[ s32ton() was moved by c653ffc28340 ("HID: stop exporting hid_snto32()").
Minor context change fixed. ]
Signed-off-by: Wenshan Lan <jetlan9@163.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/hid/hid-core.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ed65523d77c2..c8cca0c7ec67 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1354,7 +1354,12 @@ EXPORT_SYMBOL_GPL(hid_snto32); static u32 s32ton(__s32 value, unsigned 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); |
