[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] usbback: copy only filled buffers to guest


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-linux-2.6.18-xen <patchbot@xxxxxxx>
  • Date: Tue, 10 Mar 2015 13:44:03 +0000
  • Delivery-date: Tue, 10 Mar 2015 13:44:10 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Juergen Gross <jgross@xxxxxxxx>
# Date 1425994647 -3600
# Node ID 72387b3c2252e38b55ff2c943388c32f0ae338e6
# Parent  a8382d70a4a6205bd0fe67f04717ff32b3ed9605
usbback: copy only filled buffers to guest

Copy only filled buffers to guest in usbback.

After finishing a read I/O don't copy the complete I/O buffer to the
guest, but only the parts which were filled by the I/O. Otherwise Dom0
kernel data might leak into the guest.

Note that this includes dropping the urb->status == 0 check because it
was wrong: There are status != 0 cases where some data has already been
written to the buffer (e.g. in case of exact length requested and only
part of the buffer filled). The actual_length is always correct and
will be 0 if no data has been transferred.

This is CVE-2015-0777.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Committed-by: Jan Beulich <jbeulich@xxxxxxxx>
---


diff -r a8382d70a4a6 -r 72387b3c2252 drivers/xen/usbback/usbback.c
--- a/drivers/xen/usbback/usbback.c     Tue Mar 10 14:06:26 2015 +0100
+++ b/drivers/xen/usbback/usbback.c     Tue Mar 10 14:37:27 2015 +0100
@@ -197,16 +197,29 @@ static void fast_flush_area(pending_req_
 }
 
 static void copy_buff_to_pages(void *buff, pending_req_t *pending_req,
-               int start, int nr_pages)
+                              unsigned int start, unsigned int nr_pages,
+                              unsigned int offset, unsigned int length)
 {
-       unsigned long copied = 0;
-       int i;
+       const struct pending_req_segment *seg = pending_req->seg + start;
+       unsigned int i, off, len, buf_off = 0;
 
-       for (i = start; i < start + nr_pages; i++) {
-               memcpy((void *) vaddr(pending_req, i) + 
pending_req->seg[i].offset,
-                       buff + copied,
-                       pending_req->seg[i].length);
-               copied += pending_req->seg[i].length;
+       for (i = start; i < start + nr_pages; i++, seg++) {
+               len = seg->length;
+               off = seg->offset;
+               if (buf_off + len > offset) {
+                       if (buf_off < offset) {
+                               len -= offset - buf_off;
+                               off += offset - buf_off;
+                               buf_off += offset - buf_off;
+                       }
+                       if (buf_off + len > offset + length)
+                               len -= offset + length - buf_off;
+                       memcpy((void *)vaddr(pending_req, i) + off,
+                              buff + buf_off, len);
+               }
+               buf_off += len;
+               if (buf_off >= offset + length)
+                       break;
        }
 }
 
@@ -320,17 +333,39 @@ static void usbbk_do_response(pending_re
                notify_remote_via_irq(usbif->irq);
 }
 
+static void usbbk_copy_isoc_to_pages(struct urb *urb)
+{
+       pending_req_t *pending_req = urb->context;
+       struct usb_iso_packet_descriptor *isoc = &urb->iso_frame_desc[0];
+       unsigned int n_isoc = urb->number_of_packets;
+
+       copy_buff_to_pages(isoc, pending_req,
+                          pending_req->nr_buffer_segs,
+                          pending_req->nr_extra_segs, 0,
+                          n_isoc * sizeof(*isoc));
+
+       if (!usb_pipein(urb->pipe))
+               return;
+
+       while (n_isoc--) {
+               copy_buff_to_pages(pending_req->buffer,
+                                  pending_req, 0,
+                                  pending_req->nr_buffer_segs,
+                                  isoc->offset, isoc->actual_length);
+               isoc++;
+       }
+}
+
 static void usbbk_urb_complete(struct urb *urb, struct pt_regs *regs)
 {
        pending_req_t *pending_req = (pending_req_t *)urb->context;
 
-       if (usb_pipein(urb->pipe) && urb->status == 0 && urb->actual_length > 0)
+       if (usb_pipeisoc(urb->pipe))
+               usbbk_copy_isoc_to_pages(urb);
+       else if (usb_pipein(urb->pipe) && urb->actual_length > 0)
                copy_buff_to_pages(pending_req->buffer, pending_req,
-                                       0, pending_req->nr_buffer_segs);
-
-       if (usb_pipeisoc(urb->pipe))
-               copy_buff_to_pages(&urb->iso_frame_desc[0], pending_req,
-                                       pending_req->nr_buffer_segs, 
pending_req->nr_extra_segs);
+                                  0, pending_req->nr_buffer_segs,
+                                  0, urb->actual_length);
 
        barrier();
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.