[PATCH 2/2] usb/gadget: fix printer memory leak

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

 



From: "wenlin.kang" <wenlin.kang@xxxxxxxxxxxxx>

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@xxxxxxxxxxxxx>
---
 drivers/usb/gadget/printer.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index f4b4fa8..1f15ad0 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -534,7 +534,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);
 		}
 	}
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux