Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: usbmon: end ugly tricks with DMA peeking

This patch fixes crashes when usbmon attempts to access GART aperture.
The old code attempted to take a bus address and convert it into a
virtual address, which clearly was impossible on systems with actual
IOMMUs. Let us not persist in this foolishness, and use transfer_buffer
in all cases instead.

I think downsides are negligible. The ones I see are:
- A driver may pass an address of one buffer down as transfer_buffer,
and entirely different entity mapped for DMA, resulting in misleading
output of usbmon. Note, however, that PIO based controllers would
do transfer the same data that usbmon sees here.
- Out of tree drivers may crash usbmon if they store garbage in
transfer_buffer. I inspected the in-tree drivers, and clarified
the documentation in comments.
- Drivers that use get_user_pages will not be possible to monitor.
I only found one driver with this problem (drivers/staging/rspiusb).
- Same happens with with usb_storage transferring from highmem, but
it works fine on 64-bit systems, so I think it's not a concern.
At least we don't crash anymore.

Why didn't we do this in 2.6.10? That's because back in those days
it was popular not to fill in transfer_buffer, so almost all
traffic would be invisible (e.g. all of HID was like that).
But now, the tree is almost 100% PIO friendly, so we can do the
right thing at last.

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Pete Zaitcev and committed by
Greg Kroah-Hartman
4e9e9200 f4e2332c

+15 -142
+1 -1
drivers/usb/mon/Makefile
··· 2 2 # Makefile for USB monitor 3 3 # 4 4 5 - usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o 5 + usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o 6 6 7 7 obj-$(CONFIG_USB_MON) += usbmon.o
+1 -11
drivers/usb/mon/mon_bin.c
··· 220 220 221 221 /* 222 222 * This is a "chunked memcpy". It does not manipulate any counters. 223 - * But it returns the new offset for repeated application. 224 223 */ 225 - unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, 224 + static void mon_copy_to_buff(const struct mon_reader_bin *this, 226 225 unsigned int off, const unsigned char *from, unsigned int length) 227 226 { 228 227 unsigned int step_len; ··· 246 247 from += step_len; 247 248 length -= step_len; 248 249 } 249 - return off; 250 250 } 251 251 252 252 /* ··· 398 400 unsigned int offset, struct urb *urb, unsigned int length) 399 401 { 400 402 401 - if (urb->dev->bus->uses_dma && 402 - (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { 403 - mon_dmapeek_vec(rp, offset, urb->transfer_dma, length); 404 - return 0; 405 - } 406 - 407 403 if (urb->transfer_buffer == NULL) 408 404 return 'Z'; 409 - 410 405 mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); 411 406 return 0; 412 407 } ··· 626 635 spin_lock_init(&rp->b_lock); 627 636 init_waitqueue_head(&rp->b_wait); 628 637 mutex_init(&rp->fetch_lock); 629 - 630 638 rp->b_size = BUFF_DFL; 631 639 632 640 size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE);
-95
drivers/usb/mon/mon_dma.c
··· 1 - /* 2 - * The USB Monitor, inspired by Dave Harding's USBMon. 3 - * 4 - * mon_dma.c: Library which snoops on DMA areas. 5 - * 6 - * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com) 7 - */ 8 - #include <linux/kernel.h> 9 - #include <linux/list.h> 10 - #include <linux/highmem.h> 11 - #include <asm/page.h> 12 - 13 - #include <linux/usb.h> /* Only needed for declarations in usb_mon.h */ 14 - #include "usb_mon.h" 15 - 16 - /* 17 - * PC-compatibles, are, fortunately, sufficiently cache-coherent for this. 18 - */ 19 - #if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */ 20 - #define MON_HAS_UNMAP 1 21 - 22 - #define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) 23 - 24 - char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) 25 - { 26 - struct page *pg; 27 - unsigned long flags; 28 - unsigned char *map; 29 - unsigned char *ptr; 30 - 31 - /* 32 - * On i386, a DMA handle is the "physical" address of a page. 33 - * In other words, the bus address is equal to physical address. 34 - * There is no IOMMU. 35 - */ 36 - pg = phys_to_page(dma_addr); 37 - 38 - /* 39 - * We are called from hardware IRQs in case of callbacks. 40 - * But we can be called from softirq or process context in case 41 - * of submissions. In such case, we need to protect KM_IRQ0. 42 - */ 43 - local_irq_save(flags); 44 - map = kmap_atomic(pg, KM_IRQ0); 45 - ptr = map + (dma_addr & (PAGE_SIZE-1)); 46 - memcpy(dst, ptr, len); 47 - kunmap_atomic(map, KM_IRQ0); 48 - local_irq_restore(flags); 49 - return 0; 50 - } 51 - 52 - void mon_dmapeek_vec(const struct mon_reader_bin *rp, 53 - unsigned int offset, dma_addr_t dma_addr, unsigned int length) 54 - { 55 - unsigned long flags; 56 - unsigned int step_len; 57 - struct page *pg; 58 - unsigned char *map; 59 - unsigned long page_off, page_len; 60 - 61 - local_irq_save(flags); 62 - while (length) { 63 - /* compute number of bytes we are going to copy in this page */ 64 - step_len = length; 65 - page_off = dma_addr & (PAGE_SIZE-1); 66 - page_len = PAGE_SIZE - page_off; 67 - if (page_len < step_len) 68 - step_len = page_len; 69 - 70 - /* copy data and advance pointers */ 71 - pg = phys_to_page(dma_addr); 72 - map = kmap_atomic(pg, KM_IRQ0); 73 - offset = mon_copy_to_buff(rp, offset, map + page_off, step_len); 74 - kunmap_atomic(map, KM_IRQ0); 75 - dma_addr += step_len; 76 - length -= step_len; 77 - } 78 - local_irq_restore(flags); 79 - } 80 - 81 - #endif /* __i386__ */ 82 - 83 - #ifndef MON_HAS_UNMAP 84 - char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) 85 - { 86 - return 'D'; 87 - } 88 - 89 - void mon_dmapeek_vec(const struct mon_reader_bin *rp, 90 - unsigned int offset, dma_addr_t dma_addr, unsigned int length) 91 - { 92 - ; 93 - } 94 - 95 - #endif /* MON_HAS_UNMAP */
-1
drivers/usb/mon/mon_main.c
··· 361 361 } 362 362 // MOD_INC_USE_COUNT(which_module?); 363 363 364 - 365 364 mutex_lock(&usb_bus_list_lock); 366 365 list_for_each_entry (ubus, &usb_bus_list, bus_list) { 367 366 mon_bus_init(ubus);
-14
drivers/usb/mon/mon_text.c
··· 150 150 return '>'; 151 151 } 152 152 153 - /* 154 - * The check to see if it's safe to poke at data has an enormous 155 - * number of corner cases, but it seems that the following is 156 - * more or less safe. 157 - * 158 - * We do not even try to look at transfer_buffer, because it can 159 - * contain non-NULL garbage in case the upper level promised to 160 - * set DMA for the HCD. 161 - */ 162 - if (urb->dev->bus->uses_dma && 163 - (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { 164 - return mon_dmapeek(ep->data, urb->transfer_dma, len); 165 - } 166 - 167 153 if (urb->transfer_buffer == NULL) 168 154 return 'Z'; /* '0' would be not as pretty. */ 169 155
-14
drivers/usb/mon/usb_mon.h
··· 65 65 void mon_bin_exit(void); 66 66 67 67 /* 68 - * DMA interface. 69 - * 70 - * XXX The vectored side needs a serious re-thinking. Abstracting vectors, 71 - * like in Paolo's original patch, produces a double pkmap. We need an idea. 72 - */ 73 - extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); 74 - 75 - struct mon_reader_bin; 76 - extern void mon_dmapeek_vec(const struct mon_reader_bin *rp, 77 - unsigned int offset, dma_addr_t dma_addr, unsigned int len); 78 - extern unsigned int mon_copy_to_buff(const struct mon_reader_bin *rp, 79 - unsigned int offset, const unsigned char *from, unsigned int len); 80 - 81 - /* 82 68 */ 83 69 extern struct mutex mon_lock; 84 70
+13 -6
include/linux/usb.h
··· 1036 1036 * @transfer_flags: A variety of flags may be used to affect how URB 1037 1037 * submission, unlinking, or operation are handled. Different 1038 1038 * kinds of URB can use different flags. 1039 - * @transfer_buffer: This identifies the buffer to (or from) which 1040 - * the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP 1041 - * is set). This buffer must be suitable for DMA; allocate it with 1039 + * @transfer_buffer: This identifies the buffer to (or from) which the I/O 1040 + * request will be performed unless URB_NO_TRANSFER_DMA_MAP is set 1041 + * (however, do not leave garbage in transfer_buffer even then). 1042 + * This buffer must be suitable for DMA; allocate it with 1042 1043 * kmalloc() or equivalent. For transfers to "in" endpoints, contents 1043 1044 * of this buffer will be modified. This buffer is used for the data 1044 1045 * stage of control transfers. ··· 1105 1104 * allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map(). 1106 1105 * When these transfer flags are provided, host controller drivers will 1107 1106 * attempt to use the dma addresses found in the transfer_dma and/or 1108 - * setup_dma fields rather than determining a dma address themselves. (Note 1109 - * that transfer_buffer and setup_packet must still be set because not all 1110 - * host controllers use DMA, nor do virtual root hubs). 1107 + * setup_dma fields rather than determining a dma address themselves. 1108 + * 1109 + * Note that transfer_buffer must still be set if the controller 1110 + * does not support DMA (as indicated by bus.uses_dma) and when talking 1111 + * to root hub. If you have to trasfer between highmem zone and the device 1112 + * on such controller, create a bounce buffer or bail out with an error. 1113 + * If transfer_buffer cannot be set (is in highmem) and the controller is DMA 1114 + * capable, assign NULL to it, so that usbmon knows not to use the value. 1115 + * The setup_packet must always be set, so it cannot be located in highmem. 1111 1116 * 1112 1117 * Initialization: 1113 1118 *