Skip to content

Commit fcb0846

Browse files
committed
Merge: CVE-2025-38556: HID: core: Harden s32ton() against conversion to 0 bits
MR: https://gitlab.com/redhat/rhel/src/kernel/rhel-9/-/merge_requests/4392 JIRA: https://issues.redhat.com/browse/RHEL-111034 CVE: CVE-2025-38556 * ae9b956 HID: simplify snto32() * c653ffc HID: stop exporting hid_snto32() * a6b87bf HID: core: Harden s32ton() against conversion to 0 bits Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Approved-by: Bastien Nocera <bnocera@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents 666b3bb + 11f2703 commit fcb0846

File tree

3 files changed

+36
-45
lines changed

3 files changed

+36
-45
lines changed

drivers/hid/hid-core.c

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@ static int hid_ignore_special_drivers = 0;
4545
module_param_named(ignore_special_drivers, hid_ignore_special_drivers, int, 0600);
4646
MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle all devices by generic driver");
4747

48+
/*
49+
* Convert a signed n-bit integer to signed 32-bit integer.
50+
*/
51+
52+
static s32 snto32(__u32 value, unsigned int n)
53+
{
54+
if (!value || !n)
55+
return 0;
56+
57+
if (n > 32)
58+
n = 32;
59+
60+
return sign_extend32(value, n - 1);
61+
}
62+
63+
/*
64+
* Convert a signed 32-bit integer to a signed n-bit integer.
65+
*/
66+
67+
static u32 s32ton(__s32 value, unsigned int n)
68+
{
69+
s32 a;
70+
71+
if (!value || !n)
72+
return 0;
73+
74+
a = value >> (n - 1);
75+
if (a && a != -1)
76+
return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
77+
return value & ((1 << n) - 1);
78+
}
79+
4880
/*
4981
* Register a new report for a device.
5082
*/
@@ -425,7 +457,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
425457
* both this and the standard encoding. */
426458
raw_value = item_sdata(item);
427459
if (!(raw_value & 0xfffffff0))
428-
parser->global.unit_exponent = hid_snto32(raw_value, 4);
460+
parser->global.unit_exponent = snto32(raw_value, 4);
429461
else
430462
parser->global.unit_exponent = raw_value;
431463
return 0;
@@ -1317,46 +1349,6 @@ int hid_open_report(struct hid_device *device)
13171349
}
13181350
EXPORT_SYMBOL_GPL(hid_open_report);
13191351

1320-
/*
1321-
* Convert a signed n-bit integer to signed 32-bit integer. Common
1322-
* cases are done through the compiler, the screwed things has to be
1323-
* done by hand.
1324-
*/
1325-
1326-
static s32 snto32(__u32 value, unsigned n)
1327-
{
1328-
if (!value || !n)
1329-
return 0;
1330-
1331-
if (n > 32)
1332-
n = 32;
1333-
1334-
switch (n) {
1335-
case 8: return ((__s8)value);
1336-
case 16: return ((__s16)value);
1337-
case 32: return ((__s32)value);
1338-
}
1339-
return value & (1 << (n - 1)) ? value | (~0U << n) : value;
1340-
}
1341-
1342-
s32 hid_snto32(__u32 value, unsigned n)
1343-
{
1344-
return snto32(value, n);
1345-
}
1346-
EXPORT_SYMBOL_GPL(hid_snto32);
1347-
1348-
/*
1349-
* Convert a signed 32-bit integer to a signed n-bit integer.
1350-
*/
1351-
1352-
static u32 s32ton(__s32 value, unsigned n)
1353-
{
1354-
s32 a = value >> (n - 1);
1355-
if (a && a != -1)
1356-
return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
1357-
return value & ((1 << n) - 1);
1358-
}
1359-
13601352
/*
13611353
* Extract/implement a data field from/to a little endian report (bit array).
13621354
*

drivers/hid/hid-logitech-hidpp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3296,13 +3296,13 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
32963296
120);
32973297
}
32983298

3299-
v = hid_snto32(hid_field_extract(hdev, data+3, 0, 12), 12);
3299+
v = sign_extend32(hid_field_extract(hdev, data + 3, 0, 12), 11);
33003300
input_report_rel(hidpp->input, REL_X, v);
33013301

3302-
v = hid_snto32(hid_field_extract(hdev, data+3, 12, 12), 12);
3302+
v = sign_extend32(hid_field_extract(hdev, data + 3, 12, 12), 11);
33033303
input_report_rel(hidpp->input, REL_Y, v);
33043304

3305-
v = hid_snto32(data[6], 8);
3305+
v = sign_extend32(data[6], 7);
33063306
if (v != 0)
33073307
hidpp_scroll_counter_handle_scroll(hidpp->input,
33083308
&hidpp->vertical_wheel_counter, v);

include/linux/hid.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,6 @@ const struct hid_device_id *hid_match_device(struct hid_device *hdev,
972972
struct hid_driver *hdrv);
973973
bool hid_compare_device_paths(struct hid_device *hdev_a,
974974
struct hid_device *hdev_b, char separator);
975-
s32 hid_snto32(__u32 value, unsigned n);
976975
__u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
977976
unsigned offset, unsigned n);
978977

0 commit comments

Comments
 (0)