@@ -95,7 +95,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
return NULL;
}
- field = kzalloc((sizeof(struct hid_field) +
+ field = kvzalloc((sizeof(struct hid_field) +
usages * sizeof(struct hid_usage) +
3 * usages * sizeof(unsigned int)), GFP_KERNEL);
if (!field)
@@ -661,7 +661,7 @@ static void hid_free_report(struct hid_report *report)
kfree(report->field_entries);
for (n = 0; n < report->maxfield; n++)
- kfree(report->field[n]);
+ kvfree(report->field[n]);
kfree(report);
}
There are devices which deliver buggy HID descriptors, repoting Usage Maximum for particular Usage Page of max value (0xFFFF). By decision of kernel HID subsystem developers such number will be limited to arbitrary value of HID_MAX_USAGES (12288), and the following log will be printed to warn about such condition: "kernel: hid-generic 0005:057A:0087.001A: ignoring exceeding usage max" but still the amount of memory allocated for HID_MAX_USAGES modified value can be quite high as for kmalloc allocation. On some systems with limited memory (seen in ARM based embedded system), in high memory pressure condition an attempt to kmalloc() such value can fail. As a consequence this HID Usage Page will not parsed, so will not be handled and the events will be ignored. From the user perspective part of the input described with this Usage Page simply will not work, which is a severe condition. Change of kzalloc to kvzalloc makes sure that this allocation will not fail. Example of the kernel callstack when allocation fails for reference: kernel: kworker/1:1: page allocation failure: order:7, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/, mems_allowed=0 Workqueue: events uhid_device_add_worker Call trace: dump_backtrace+0x0/0x1b4 show_stack+0x24/0x30 dump_stack+0xac/0x10c warn_alloc+0xd8/0x158 __alloc_pages_slowpath+0x2e0/0x914 __alloc_pages_nodemask+0x1b0/0x278 kmalloc_order+0x30/0x7c kmalloc_order_trace+0x3c/0xd4 __kmalloc+0x50/0x188 hid_add_field+0x160/0x250 hid_parser_main+0x220/0x25c hid_open_report+0x138/0x278 hid_generic_probe+0x40/0x5c hid_device_probe+0x130/0x154 really_probe+0x274/0x3f0 driver_probe_device+0x118/0x128 __device_attach_driver+0xc4/0x108 bus_for_each_drv+0xa4/0xc8 __device_attach+0xf4/0x17c device_initial_probe+0x24/0x30 bus_probe_device+0x38/0x98 device_add+0x4a0/0x578 hid_add_device+0x100/0x294 uhid_device_add_worker+0x28/0x70 process_one_work+0x19c/0x294 worker_thread+0x1e4/0x274 kthread+0xdc/0xec ret_from_fork+0x10/0x18 Signed-off-by: Marcin Mikula <marcin@helix.pl> --- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)