]>
Commit | Line | Data |
---|---|---|
c55ac56b GKH |
1 | From 4f65245f2d178b9cba48350620d76faa4a098841 Mon Sep 17 00:00:00 2001 |
2 | From: "Gustavo A. R. Silva" <gustavo@embeddedor.com> | |
3 | Date: Fri, 29 Jun 2018 17:08:44 -0500 | |
4 | Subject: HID: hiddev: fix potential Spectre v1 | |
5 | ||
6 | From: Gustavo A. R. Silva <gustavo@embeddedor.com> | |
7 | ||
8 | commit 4f65245f2d178b9cba48350620d76faa4a098841 upstream. | |
9 | ||
10 | uref->field_index, uref->usage_index, finfo.field_index and cinfo.index can be | |
11 | indirectly controlled by user-space, hence leading to a potential exploitation | |
12 | of the Spectre variant 1 vulnerability. | |
13 | ||
14 | This issue was detected with the help of Smatch: | |
15 | ||
16 | drivers/hid/usbhid/hiddev.c:473 hiddev_ioctl_usage() warn: potential spectre issue 'report->field' (local cap) | |
17 | drivers/hid/usbhid/hiddev.c:477 hiddev_ioctl_usage() warn: potential spectre issue 'field->usage' (local cap) | |
18 | drivers/hid/usbhid/hiddev.c:757 hiddev_ioctl() warn: potential spectre issue 'report->field' (local cap) | |
19 | drivers/hid/usbhid/hiddev.c:801 hiddev_ioctl() warn: potential spectre issue 'hid->collection' (local cap) | |
20 | ||
21 | Fix this by sanitizing such structure fields before using them to index | |
22 | report->field, field->usage and hid->collection | |
23 | ||
24 | Notice that given that speculation windows are large, the policy is | |
25 | to kill the speculation on the first load and not worry if it can be | |
26 | completed with a dependent load/store [1]. | |
27 | ||
28 | [1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 | |
29 | ||
30 | Cc: stable@vger.kernel.org | |
31 | Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> | |
32 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | |
33 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
34 | ||
35 | --- | |
36 | drivers/hid/usbhid/hiddev.c | 11 +++++++++++ | |
37 | 1 file changed, 11 insertions(+) | |
38 | ||
39 | --- a/drivers/hid/usbhid/hiddev.c | |
40 | +++ b/drivers/hid/usbhid/hiddev.c | |
41 | @@ -35,6 +35,7 @@ | |
42 | #include <linux/hiddev.h> | |
43 | #include <linux/compat.h> | |
44 | #include <linux/vmalloc.h> | |
45 | +#include <linux/nospec.h> | |
46 | #include "usbhid.h" | |
47 | ||
48 | #ifdef CONFIG_USB_DYNAMIC_MINORS | |
49 | @@ -478,10 +479,14 @@ static noinline int hiddev_ioctl_usage(s | |
50 | ||
51 | if (uref->field_index >= report->maxfield) | |
52 | goto inval; | |
53 | + uref->field_index = array_index_nospec(uref->field_index, | |
54 | + report->maxfield); | |
55 | ||
56 | field = report->field[uref->field_index]; | |
57 | if (uref->usage_index >= field->maxusage) | |
58 | goto inval; | |
59 | + uref->usage_index = array_index_nospec(uref->usage_index, | |
60 | + field->maxusage); | |
61 | ||
62 | uref->usage_code = field->usage[uref->usage_index].hid; | |
63 | ||
64 | @@ -508,6 +513,8 @@ static noinline int hiddev_ioctl_usage(s | |
65 | ||
66 | if (uref->field_index >= report->maxfield) | |
67 | goto inval; | |
68 | + uref->field_index = array_index_nospec(uref->field_index, | |
69 | + report->maxfield); | |
70 | ||
71 | field = report->field[uref->field_index]; | |
72 | ||
73 | @@ -761,6 +768,8 @@ static long hiddev_ioctl(struct file *fi | |
74 | ||
75 | if (finfo.field_index >= report->maxfield) | |
76 | break; | |
77 | + finfo.field_index = array_index_nospec(finfo.field_index, | |
78 | + report->maxfield); | |
79 | ||
80 | field = report->field[finfo.field_index]; | |
81 | memset(&finfo, 0, sizeof(finfo)); | |
82 | @@ -801,6 +810,8 @@ static long hiddev_ioctl(struct file *fi | |
83 | ||
84 | if (cinfo.index >= hid->maxcollection) | |
85 | break; | |
86 | + cinfo.index = array_index_nospec(cinfo.index, | |
87 | + hid->maxcollection); | |
88 | ||
89 | cinfo.type = hid->collection[cinfo.index].type; | |
90 | cinfo.usage = hid->collection[cinfo.index].usage; |