aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/usbip
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/usbip')
-rw-r--r--drivers/usb/usbip/stub_rx.c51
-rw-r--r--drivers/usb/usbip/stub_tx.c7
-rw-r--r--drivers/usb/usbip/usbip_common.h1
-rw-r--r--drivers/usb/usbip/vhci_sysfs.c25
4 files changed, 65 insertions, 19 deletions
diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
index 536e037f541f..493ac2928391 100644
--- a/drivers/usb/usbip/stub_rx.c
+++ b/drivers/usb/usbip/stub_rx.c
@@ -322,23 +322,34 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
322 return priv; 322 return priv;
323} 323}
324 324
325static int get_pipe(struct stub_device *sdev, int epnum, int dir) 325static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu)
326{ 326{
327 struct usb_device *udev = sdev->udev; 327 struct usb_device *udev = sdev->udev;
328 struct usb_host_endpoint *ep; 328 struct usb_host_endpoint *ep;
329 struct usb_endpoint_descriptor *epd = NULL; 329 struct usb_endpoint_descriptor *epd = NULL;
330 int epnum = pdu->base.ep;
331 int dir = pdu->base.direction;
332
333 if (epnum < 0 || epnum > 15)
334 goto err_ret;
330 335
331 if (dir == USBIP_DIR_IN) 336 if (dir == USBIP_DIR_IN)
332 ep = udev->ep_in[epnum & 0x7f]; 337 ep = udev->ep_in[epnum & 0x7f];
333 else 338 else
334 ep = udev->ep_out[epnum & 0x7f]; 339 ep = udev->ep_out[epnum & 0x7f];
335 if (!ep) { 340 if (!ep)
336 dev_err(&sdev->udev->dev, "no such endpoint?, %d\n", 341 goto err_ret;
337 epnum);
338 BUG();
339 }
340 342
341 epd = &ep->desc; 343 epd = &ep->desc;
344
345 /* validate transfer_buffer_length */
346 if (pdu->u.cmd_submit.transfer_buffer_length > INT_MAX) {
347 dev_err(&sdev->udev->dev,
348 "CMD_SUBMIT: -EMSGSIZE transfer_buffer_length %d\n",
349 pdu->u.cmd_submit.transfer_buffer_length);
350 return -1;
351 }
352
342 if (usb_endpoint_xfer_control(epd)) { 353 if (usb_endpoint_xfer_control(epd)) {
343 if (dir == USBIP_DIR_OUT) 354 if (dir == USBIP_DIR_OUT)
344 return usb_sndctrlpipe(udev, epnum); 355 return usb_sndctrlpipe(udev, epnum);
@@ -361,15 +372,31 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
361 } 372 }
362 373
363 if (usb_endpoint_xfer_isoc(epd)) { 374 if (usb_endpoint_xfer_isoc(epd)) {
375 /* validate packet size and number of packets */
376 unsigned int maxp, packets, bytes;
377
378 maxp = usb_endpoint_maxp(epd);
379 maxp *= usb_endpoint_maxp_mult(epd);
380 bytes = pdu->u.cmd_submit.transfer_buffer_length;
381 packets = DIV_ROUND_UP(bytes, maxp);
382
383 if (pdu->u.cmd_submit.number_of_packets < 0 ||
384 pdu->u.cmd_submit.number_of_packets > packets) {
385 dev_err(&sdev->udev->dev,
386 "CMD_SUBMIT: isoc invalid num packets %d\n",
387 pdu->u.cmd_submit.number_of_packets);
388 return -1;
389 }
364 if (dir == USBIP_DIR_OUT) 390 if (dir == USBIP_DIR_OUT)
365 return usb_sndisocpipe(udev, epnum); 391 return usb_sndisocpipe(udev, epnum);
366 else 392 else
367 return usb_rcvisocpipe(udev, epnum); 393 return usb_rcvisocpipe(udev, epnum);
368 } 394 }
369 395
396err_ret:
370 /* NOT REACHED */ 397 /* NOT REACHED */
371 dev_err(&sdev->udev->dev, "get pipe, epnum %d\n", epnum); 398 dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum);
372 return 0; 399 return -1;
373} 400}
374 401
375static void masking_bogus_flags(struct urb *urb) 402static void masking_bogus_flags(struct urb *urb)
@@ -433,7 +460,10 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
433 struct stub_priv *priv; 460 struct stub_priv *priv;
434 struct usbip_device *ud = &sdev->ud; 461 struct usbip_device *ud = &sdev->ud;
435 struct usb_device *udev = sdev->udev; 462 struct usb_device *udev = sdev->udev;
436 int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); 463 int pipe = get_pipe(sdev, pdu);
464
465 if (pipe == -1)
466 return;
437 467
438 priv = stub_priv_alloc(sdev, pdu); 468 priv = stub_priv_alloc(sdev, pdu);
439 if (!priv) 469 if (!priv)
@@ -452,7 +482,8 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
452 } 482 }
453 483
454 /* allocate urb transfer buffer, if needed */ 484 /* allocate urb transfer buffer, if needed */
455 if (pdu->u.cmd_submit.transfer_buffer_length > 0) { 485 if (pdu->u.cmd_submit.transfer_buffer_length > 0 &&
486 pdu->u.cmd_submit.transfer_buffer_length <= INT_MAX) {
456 priv->urb->transfer_buffer = 487 priv->urb->transfer_buffer =
457 kzalloc(pdu->u.cmd_submit.transfer_buffer_length, 488 kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
458 GFP_KERNEL); 489 GFP_KERNEL);
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
index b18bce96c212..53172b1f6257 100644
--- a/drivers/usb/usbip/stub_tx.c
+++ b/drivers/usb/usbip/stub_tx.c
@@ -167,6 +167,13 @@ static int stub_send_ret_submit(struct stub_device *sdev)
167 memset(&pdu_header, 0, sizeof(pdu_header)); 167 memset(&pdu_header, 0, sizeof(pdu_header));
168 memset(&msg, 0, sizeof(msg)); 168 memset(&msg, 0, sizeof(msg));
169 169
170 if (urb->actual_length > 0 && !urb->transfer_buffer) {
171 dev_err(&sdev->udev->dev,
172 "urb: actual_length %d transfer_buffer null\n",
173 urb->actual_length);
174 return -1;
175 }
176
170 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) 177 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
171 iovnum = 2 + urb->number_of_packets; 178 iovnum = 2 + urb->number_of_packets;
172 else 179 else
diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
index e5de35c8c505..473fb8a87289 100644
--- a/drivers/usb/usbip/usbip_common.h
+++ b/drivers/usb/usbip/usbip_common.h
@@ -256,6 +256,7 @@ struct usbip_device {
256 /* lock for status */ 256 /* lock for status */
257 spinlock_t lock; 257 spinlock_t lock;
258 258
259 int sockfd;
259 struct socket *tcp_socket; 260 struct socket *tcp_socket;
260 261
261 struct task_struct *tcp_rx; 262 struct task_struct *tcp_rx;
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
index e78f7472cac4..091f76b7196d 100644
--- a/drivers/usb/usbip/vhci_sysfs.c
+++ b/drivers/usb/usbip/vhci_sysfs.c
@@ -17,15 +17,20 @@
17 17
18/* 18/*
19 * output example: 19 * output example:
20 * hub port sta spd dev socket local_busid 20 * hub port sta spd dev sockfd local_busid
21 * hs 0000 004 000 00000000 c5a7bb80 1-2.3 21 * hs 0000 004 000 00000000 3 1-2.3
22 * ................................................ 22 * ................................................
23 * ss 0008 004 000 00000000 d8cee980 2-3.4 23 * ss 0008 004 000 00000000 4 2-3.4
24 * ................................................ 24 * ................................................
25 * 25 *
26 * IP address can be retrieved from a socket pointer address by looking 26 * Output includes socket fd instead of socket pointer address to avoid
27 * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a 27 * leaking kernel memory address in:
28 * port number and its peer IP address. 28 * /sys/devices/platform/vhci_hcd.0/status and in debug output.
29 * The socket pointer address is not used at the moment and it was made
30 * visible as a convenient way to find IP address from socket pointer
31 * address by looking up /proc/net/{tcp,tcp6}. As this opens a security
32 * hole, the change is made to use sockfd instead.
33 *
29 */ 34 */
30static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev) 35static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev)
31{ 36{
@@ -39,8 +44,8 @@ static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vd
39 if (vdev->ud.status == VDEV_ST_USED) { 44 if (vdev->ud.status == VDEV_ST_USED) {
40 *out += sprintf(*out, "%03u %08x ", 45 *out += sprintf(*out, "%03u %08x ",
41 vdev->speed, vdev->devid); 46 vdev->speed, vdev->devid);
42 *out += sprintf(*out, "%16p %s", 47 *out += sprintf(*out, "%u %s",
43 vdev->ud.tcp_socket, 48 vdev->ud.sockfd,
44 dev_name(&vdev->udev->dev)); 49 dev_name(&vdev->udev->dev));
45 50
46 } else { 51 } else {
@@ -160,7 +165,8 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
160 char *s = out; 165 char *s = out;
161 166
162 /* 167 /*
163 * Half the ports are for SPEED_HIGH and half for SPEED_SUPER, thus the * 2. 168 * Half the ports are for SPEED_HIGH and half for SPEED_SUPER,
169 * thus the * 2.
164 */ 170 */
165 out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers); 171 out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers);
166 return out - s; 172 return out - s;
@@ -366,6 +372,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
366 372
367 vdev->devid = devid; 373 vdev->devid = devid;
368 vdev->speed = speed; 374 vdev->speed = speed;
375 vdev->ud.sockfd = sockfd;
369 vdev->ud.tcp_socket = socket; 376 vdev->ud.tcp_socket = socket;
370 vdev->ud.status = VDEV_ST_NOTASSIGNED; 377 vdev->ud.status = VDEV_ST_NOTASSIGNED;
371 378