summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorwenlin.kang <wenlin.kang@windriver.com>2014-01-08 07:22:12 +0100
committerFelipe Balbi <balbi@ti.com>2014-02-18 17:52:54 +0100
commit7e98f60003df98026edd66916f282501eee075c4 (patch)
tree739639a6fa0b36b350fe829edf43694bf0426a77 /drivers/usb/gadget
parentusb: gadget: printer: fix possible deadlock (diff)
downloadlinux-7e98f60003df98026edd66916f282501eee075c4.tar.xz
linux-7e98f60003df98026edd66916f282501eee075c4.zip
usb: gadget: printer: fix memory leak
When read data from g_printer, we see a Segmentation fault. eg: Unable to handle kernel paging request at virtual address bf048000 pgd = cf038000 [bf048000] *pgd=8e8cf811, *pte=00000000, *ppte=00000000 Internal error: Oops: 7 [#1] PREEMPT ARM Modules linked in: bluetooth rfcomm g_printer CPU: 0 Not tainted (3.4.43-WR5.0.1.9_standard #1) PC is at __copy_to_user_std+0x310/0x3a8 LR is at 0x4c808010 pc : [<c036e990>] lr : [<4c808010>] psr: 20000013 sp : cf883ea8 ip : 80801018 fp : cf883f24 r10: bf04706c r9 : 18a21205 r8 : 21953888 r7 : 201588aa r6 : 5109aa16 r5 : 0705aaa2 r4 : 5140aa8a r3 : 0000004c r2 : 00000fdc r1 : bf048000 r0 : bef5fc3c Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 8f038019 DAC: 00000015 Process g_printer_test. (pid: 661, stack limit = 0xcf8822e8) Stack: (0xcf883ea8 to 0xcf884000) 3ea0: bf047068 00001fff bef5ecb9 cf882000 00001fff bef5ecb9 3ec0: 00001fff 00000000 cf2e8724 bf044d3c 80000013 80000013 00000001 bf04706c 3ee0: cf883f24 cf883ef0 c012e5ac c0324388 c007c8ac c0046298 00008180 cf29b900 3f00: 00002000 bef5ecb8 cf883f68 00000003 cf882000 cf29b900 cf883f54 cf883f28 3f20: c012ea08 bf044b0c c000eb88 00000000 cf883f7c 00000000 00000000 00002000 3f40: bef5ecb8 00000003 cf883fa4 cf883f58 c012eae8 c012e960 00000001 bef60cb8 3f60: 000000a8 c000eb88 00000000 00000000 cf883fa4 00000000 c014329c 00000000 3f80: 000000d4 41af63f0 00000003 c000eb88 cf882000 00000000 00000000 cf883fa8 3fa0: c000e920 c012eaa4 00000000 000000d4 00000003 bef5ecb8 00002000 bef5ecb8 3fc0: 00000000 000000d4 41af63f0 00000003 b6f534c0 00000000 419f9000 00000000 3fe0: 00000000 bef5ecac 000086d9 41a986bc 60000010 00000003 0109608a 0088828a Code: f5d1f07c e8b100f0 e1a03c2e e2522020 (e8b15300) ---[ end trace 97e2618e250e3377 ]--- Segmentation fault The root cause is the dev->rx_buffers list has been broken. When we call printer_read(), the following call tree is triggered: printer_read() | +---setup_rx_reqs(req) | | | +---usb_ep_queue(req) | | | | | +---... | | | | | +---rx_complete(req). | | | +---add the req to dev->rx_reqs_active | +---while(!list_empty(&dev->rx_buffers))) The route happens when we don't use DMA or fail to start DMA in USB driver. We can see: in the case, in rx_complete() it will add the req to dev->rx_buffers. meanwhile we see that we will also add the req to dev->rx_reqs_active after usb_ep_queue() return, so this adding will break the dev->rx_buffers out. After, when we call list_empty() to check dev->rx_buffers in while(), due to can't check correctly dev->rx_buffers, so the Segmentation fault occurs when copy_to_user() is called. Signed-off-by: wenlin.kang <wenlin.kang@windriver.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/printer.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 96ffdac330b5..0fd459e724be 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -435,7 +435,9 @@ setup_rx_reqs(struct printer_dev *dev)
DBG(dev, "rx submit --> %d\n", error);
list_add(&req->list, &dev->rx_reqs);
break;
- } else {
+ }
+ /* if the req is empty, then add it into dev->rx_reqs_active. */
+ else if (list_empty(&req->list)) {
list_add(&req->list, &dev->rx_reqs_active);
}
}