diff options
| author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2018-07-13 10:13:50 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2018-07-17 09:33:47 -0400 |
| commit | 08a8a7cf14595f95d5cbb28ef5c15c56a6255fb4 (patch) | |
| tree | 7b51d919ff29ee607b2229bd69f6a9059975c131 /drivers/hid | |
| parent | ba6b055e0f3b4ff4942e4ab273260affcfad9bff (diff) | |
HID: core: do not upper bound the collection stack
Looks like 4 was sufficient until now. However, the Surface Dial needs
a stack of 5 and simply fails at probing.
Dynamically add HID_COLLECTION_STACK_SIZE to the size of the stack if
we hit the upper bound.
Checkpatch complains about bare unsigned, so converting those to
'unsigned int' in struct hid_parser
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/hid-core.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3942ee61bd1c..5de6f18c9bf7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
| 128 | 128 | ||
| 129 | usage = parser->local.usage[0]; | 129 | usage = parser->local.usage[0]; |
| 130 | 130 | ||
| 131 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { | 131 | if (parser->collection_stack_ptr == parser->collection_stack_size) { |
| 132 | hid_err(parser->device, "collection stack overflow\n"); | 132 | unsigned int *collection_stack; |
| 133 | return -EINVAL; | 133 | unsigned int new_size = parser->collection_stack_size + |
| 134 | HID_COLLECTION_STACK_SIZE; | ||
| 135 | |||
| 136 | collection_stack = krealloc(parser->collection_stack, | ||
| 137 | new_size * sizeof(unsigned int), | ||
| 138 | GFP_KERNEL); | ||
| 139 | if (!collection_stack) | ||
| 140 | return -ENOMEM; | ||
| 141 | |||
| 142 | parser->collection_stack = collection_stack; | ||
| 143 | parser->collection_stack_size = new_size; | ||
| 134 | } | 144 | } |
| 135 | 145 | ||
| 136 | if (parser->device->maxcollection == parser->device->collection_size) { | 146 | if (parser->device->maxcollection == parser->device->collection_size) { |
| @@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid) | |||
| 840 | break; | 850 | break; |
| 841 | } | 851 | } |
| 842 | 852 | ||
| 853 | kfree(parser->collection_stack); | ||
| 843 | vfree(parser); | 854 | vfree(parser); |
| 844 | return 0; | 855 | return 0; |
| 845 | } | 856 | } |
