]>
Commit | Line | Data |
---|---|---|
14e9555d GKH |
1 | From 31e0456de5be379b10fea0fa94a681057114a96e Mon Sep 17 00:00:00 2001 |
2 | From: Alan Stern <stern@rowland.harvard.edu> | |
3 | Date: Tue, 7 May 2019 12:39:47 -0400 | |
4 | Subject: media: usb: siano: Fix general protection fault in smsusb | |
5 | ||
6 | From: Alan Stern <stern@rowland.harvard.edu> | |
7 | ||
8 | commit 31e0456de5be379b10fea0fa94a681057114a96e upstream. | |
9 | ||
10 | The syzkaller USB fuzzer found a general-protection-fault bug in the | |
11 | smsusb part of the Siano DVB driver. The fault occurs during probe | |
12 | because the driver assumes without checking that the device has both | |
13 | IN and OUT endpoints and the IN endpoint is ep1. | |
14 | ||
15 | By slightly rearranging the driver's initialization code, we can make | |
16 | the appropriate checks early on and thus avoid the problem. If the | |
17 | expected endpoints aren't present, the new code safely returns -ENODEV | |
18 | from the probe routine. | |
19 | ||
20 | Signed-off-by: Alan Stern <stern@rowland.harvard.edu> | |
21 | Reported-and-tested-by: syzbot+53f029db71c19a47325a@syzkaller.appspotmail.com | |
22 | CC: <stable@vger.kernel.org> | |
23 | Reviewed-by: Johan Hovold <johan@kernel.org> | |
24 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
25 | ||
26 | --- | |
27 | drivers/media/usb/siano/smsusb.c | 33 ++++++++++++++++++++------------- | |
28 | 1 file changed, 20 insertions(+), 13 deletions(-) | |
29 | ||
30 | --- a/drivers/media/usb/siano/smsusb.c | |
31 | +++ b/drivers/media/usb/siano/smsusb.c | |
32 | @@ -401,6 +401,7 @@ static int smsusb_init_device(struct usb | |
33 | struct smsusb_device_t *dev; | |
34 | void *mdev; | |
35 | int i, rc; | |
36 | + int in_maxp; | |
37 | ||
38 | /* create device object */ | |
39 | dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL); | |
40 | @@ -412,6 +413,24 @@ static int smsusb_init_device(struct usb | |
41 | dev->udev = interface_to_usbdev(intf); | |
42 | dev->state = SMSUSB_DISCONNECTED; | |
43 | ||
44 | + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { | |
45 | + struct usb_endpoint_descriptor *desc = | |
46 | + &intf->cur_altsetting->endpoint[i].desc; | |
47 | + | |
48 | + if (desc->bEndpointAddress & USB_DIR_IN) { | |
49 | + dev->in_ep = desc->bEndpointAddress; | |
50 | + in_maxp = usb_endpoint_maxp(desc); | |
51 | + } else { | |
52 | + dev->out_ep = desc->bEndpointAddress; | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep); | |
57 | + if (!dev->in_ep || !dev->out_ep) { /* Missing endpoints? */ | |
58 | + smsusb_term_device(intf); | |
59 | + return -ENODEV; | |
60 | + } | |
61 | + | |
62 | params.device_type = sms_get_board(board_id)->type; | |
63 | ||
64 | switch (params.device_type) { | |
65 | @@ -426,24 +445,12 @@ static int smsusb_init_device(struct usb | |
66 | /* fall-thru */ | |
67 | default: | |
68 | dev->buffer_size = USB2_BUFFER_SIZE; | |
69 | - dev->response_alignment = | |
70 | - le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - | |
71 | - sizeof(struct sms_msg_hdr); | |
72 | + dev->response_alignment = in_maxp - sizeof(struct sms_msg_hdr); | |
73 | ||
74 | params.flags |= SMS_DEVICE_FAMILY2; | |
75 | break; | |
76 | } | |
77 | ||
78 | - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { | |
79 | - if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN) | |
80 | - dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; | |
81 | - else | |
82 | - dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; | |
83 | - } | |
84 | - | |
85 | - pr_debug("in_ep = %02x, out_ep = %02x\n", | |
86 | - dev->in_ep, dev->out_ep); | |
87 | - | |
88 | params.device = &dev->udev->dev; | |
89 | params.usb_device = dev->udev; | |
90 | params.buffer_size = dev->buffer_size; |