Skip to content

Commit 35c024f

Browse files
AlanSternwebgeek1234
authored andcommitted
HID: Fix assumption that devices have inputs
commit d9d4b1e46d9543a82c23f6df03f4ad697dab361b upstream. The syzbot fuzzer found a slab-out-of-bounds write bug in the hid-gaff driver. The problem is caused by the driver's assumption that the device must have an input report. While this will be true for all normal HID input devices, a suitably malicious device can violate the assumption. The same assumption is present in over a dozen other HID drivers. This patch fixes them by checking that the list of hid_inputs for the hid_device is nonempty before allowing it to be used. Reported-and-tested-by: [email protected] Signed-off-by: Alan Stern <[email protected]> CC: <[email protected]> Signed-off-by: Benjamin Tissoires <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Change-Id: I8586bda3757436223a2a40d5a9d10ec6f5b2affe
1 parent 5713f18 commit 35c024f

File tree

13 files changed

+117
-34
lines changed

13 files changed

+117
-34
lines changed

drivers/hid/hid-axff.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,20 @@ static int axff_init(struct hid_device *hid)
7575
{
7676
struct axff_device *axff;
7777
struct hid_report *report;
78-
struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
78+
struct hid_input *hidinput;
7979
struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
80-
struct input_dev *dev = hidinput->input;
80+
struct input_dev *dev;
8181
int field_count = 0;
8282
int i, j;
8383
int error;
8484

85+
if (list_empty(&hid->inputs)) {
86+
hid_err(hid, "no inputs found\n");
87+
return -ENODEV;
88+
}
89+
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
90+
dev = hidinput->input;
91+
8592
if (list_empty(report_list)) {
8693
hid_err(hid, "no output reports found\n");
8794
return -ENODEV;

drivers/hid/hid-dr.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,19 @@ static int drff_init(struct hid_device *hid)
8787
{
8888
struct drff_device *drff;
8989
struct hid_report *report;
90-
struct hid_input *hidinput = list_first_entry(&hid->inputs,
91-
struct hid_input, list);
90+
struct hid_input *hidinput;
9291
struct list_head *report_list =
9392
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
94-
struct input_dev *dev = hidinput->input;
93+
struct input_dev *dev;
9594
int error;
9695

96+
if (list_empty(&hid->inputs)) {
97+
hid_err(hid, "no inputs found\n");
98+
return -ENODEV;
99+
}
100+
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
101+
dev = hidinput->input;
102+
97103
if (list_empty(report_list)) {
98104
hid_err(hid, "no output reports found\n");
99105
return -ENODEV;

drivers/hid/hid-emsff.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,19 @@ static int emsff_init(struct hid_device *hid)
5959
{
6060
struct emsff_device *emsff;
6161
struct hid_report *report;
62-
struct hid_input *hidinput = list_first_entry(&hid->inputs,
63-
struct hid_input, list);
62+
struct hid_input *hidinput;
6463
struct list_head *report_list =
6564
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
66-
struct input_dev *dev = hidinput->input;
65+
struct input_dev *dev;
6766
int error;
6867

68+
if (list_empty(&hid->inputs)) {
69+
hid_err(hid, "no inputs found\n");
70+
return -ENODEV;
71+
}
72+
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
73+
dev = hidinput->input;
74+
6975
if (list_empty(report_list)) {
7076
hid_err(hid, "no output reports found\n");
7177
return -ENODEV;

drivers/hid/hid-gaff.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,20 @@ static int gaff_init(struct hid_device *hid)
7777
{
7878
struct gaff_device *gaff;
7979
struct hid_report *report;
80-
struct hid_input *hidinput = list_entry(hid->inputs.next,
81-
struct hid_input, list);
80+
struct hid_input *hidinput;
8281
struct list_head *report_list =
8382
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
8483
struct list_head *report_ptr = report_list;
85-
struct input_dev *dev = hidinput->input;
84+
struct input_dev *dev;
8685
int error;
8786

87+
if (list_empty(&hid->inputs)) {
88+
hid_err(hid, "no inputs found\n");
89+
return -ENODEV;
90+
}
91+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
92+
dev = hidinput->input;
93+
8894
if (list_empty(report_list)) {
8995
hid_err(hid, "no output reports found\n");
9096
return -ENODEV;

drivers/hid/hid-holtekff.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,19 @@ static int holtekff_init(struct hid_device *hid)
141141
{
142142
struct holtekff_device *holtekff;
143143
struct hid_report *report;
144-
struct hid_input *hidinput = list_entry(hid->inputs.next,
145-
struct hid_input, list);
144+
struct hid_input *hidinput;
146145
struct list_head *report_list =
147146
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
148-
struct input_dev *dev = hidinput->input;
147+
struct input_dev *dev;
149148
int error;
150149

150+
if (list_empty(&hid->inputs)) {
151+
hid_err(hid, "no inputs found\n");
152+
return -ENODEV;
153+
}
154+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
155+
dev = hidinput->input;
156+
151157
if (list_empty(report_list)) {
152158
hid_err(hid, "no output report found\n");
153159
return -ENODEV;

drivers/hid/hid-lg2ff.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,17 @@ int lg2ff_init(struct hid_device *hid)
6262
{
6363
struct lg2ff_device *lg2ff;
6464
struct hid_report *report;
65-
struct hid_input *hidinput = list_entry(hid->inputs.next,
66-
struct hid_input, list);
67-
struct input_dev *dev = hidinput->input;
65+
struct hid_input *hidinput;
66+
struct input_dev *dev;
6867
int error;
6968

69+
if (list_empty(&hid->inputs)) {
70+
hid_err(hid, "no inputs found\n");
71+
return -ENODEV;
72+
}
73+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
74+
dev = hidinput->input;
75+
7076
/* Check that the report looks ok */
7177
report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
7278
if (!report)

drivers/hid/hid-lg3ff.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,19 @@ static const signed short ff3_joystick_ac[] = {
129129

130130
int lg3ff_init(struct hid_device *hid)
131131
{
132-
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
133-
struct input_dev *dev = hidinput->input;
132+
struct hid_input *hidinput;
133+
struct input_dev *dev;
134134
const signed short *ff_bits = ff3_joystick_ac;
135135
int error;
136136
int i;
137137

138+
if (list_empty(&hid->inputs)) {
139+
hid_err(hid, "no inputs found\n");
140+
return -ENODEV;
141+
}
142+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
143+
dev = hidinput->input;
144+
138145
/* Check that the report looks ok */
139146
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
140147
return -ENODEV;

drivers/hid/hid-lg4ff.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,8 +1261,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc
12611261

12621262
int lg4ff_init(struct hid_device *hid)
12631263
{
1264-
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1265-
struct input_dev *dev = hidinput->input;
1264+
struct hid_input *hidinput;
1265+
struct input_dev *dev;
12661266
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
12671267
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
12681268
const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
@@ -1274,6 +1274,13 @@ int lg4ff_init(struct hid_device *hid)
12741274
int mmode_ret, mmode_idx = -1;
12751275
u16 real_product_id;
12761276

1277+
if (list_empty(&hid->inputs)) {
1278+
hid_err(hid, "no inputs found\n");
1279+
return -ENODEV;
1280+
}
1281+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1282+
dev = hidinput->input;
1283+
12771284
/* Check that the report looks ok */
12781285
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
12791286
return -1;

drivers/hid/hid-lgff.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
127127

128128
int lgff_init(struct hid_device* hid)
129129
{
130-
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
131-
struct input_dev *dev = hidinput->input;
130+
struct hid_input *hidinput;
131+
struct input_dev *dev;
132132
const signed short *ff_bits = ff_joystick;
133133
int error;
134134
int i;
135135

136+
if (list_empty(&hid->inputs)) {
137+
hid_err(hid, "no inputs found\n");
138+
return -ENODEV;
139+
}
140+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
141+
dev = hidinput->input;
142+
136143
/* Check that the report looks ok */
137144
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
138145
return -ENODEV;

drivers/hid/hid-logitech-hidpp.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,8 +1229,8 @@ static void hidpp_ff_destroy(struct ff_device *ff)
12291229
static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
12301230
{
12311231
struct hid_device *hid = hidpp->hid_dev;
1232-
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1233-
struct input_dev *dev = hidinput->input;
1232+
struct hid_input *hidinput;
1233+
struct input_dev *dev;
12341234
const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
12351235
const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
12361236
struct ff_device *ff;
@@ -1239,6 +1239,13 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
12391239
int error, j, num_slots;
12401240
u8 version;
12411241

1242+
if (list_empty(&hid->inputs)) {
1243+
hid_err(hid, "no inputs found\n");
1244+
return -ENODEV;
1245+
}
1246+
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1247+
dev = hidinput->input;
1248+
12421249
if (!dev) {
12431250
hid_err(hid, "Struct input_dev not set!\n");
12441251
return -EINVAL;

0 commit comments

Comments
 (0)