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>
This commit is contained in:
wenlin.kang 2014-01-08 14:22:12 +08:00 committed by Felipe Balbi
parent 2c2b04253b
commit 7e98f60003

View File

@ -435,7 +435,9 @@ setup_rx_reqs(struct printer_dev *dev)
DBG(dev, "rx submit --> %d\n", error); DBG(dev, "rx submit --> %d\n", error);
list_add(&req->list, &dev->rx_reqs); list_add(&req->list, &dev->rx_reqs);
break; 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); list_add(&req->list, &dev->rx_reqs_active);
} }
} }