Re: usb/gadget: use-after-free in gadgetfs_setup

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

 



On Mon, 12 Dec 2016, Andrey Konovalov wrote:

> > Can you also provide reproducers for the "GPF in
> > usb_gadget_unregister_driver" and the "warning in dummy_free_request"
> > tests?
> 
> Hi Alan,
> 
> I haven't managed to obtain a working reproducer, though the fuzzer
> hits it pretty often :(
> 
> Here is a syzkaller description of the program which triggers the
> crash (note that syzkaller can run each call concurrently):
> 
> mmap(&(0x7f0000000000/0x5000)=nil, (0x5000), 0x3, 0x32, 0xffffffffffffffff, 0x0)
> r0 = open$usb(&(0x7f0000000000)="2f6465762f6761646765742f64756d6d795f75646300",
> 0x602, 0x0)
> read$usb(r0, &(0x7f0000000000)="000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
> 0xcf)
> write$usb(r0, &(0x7f0000003000-0x28)={0x0, {0x9, 0x2, 0x12,
> 0xffffffffffffff9e, 0x83, 0x5, 0x80, 0x0}, {0x9, 0x4, 0x0, 0x0, 0x0,
> 0x0, 0x55, 0x4, 0x9}, {0x12, 0x1, 0x2, 0x8001, 0x8, 0x6, 0x0, 0x0,
> 0x2, 0x2, 0x0, 0x0, 0x7, 0x1}}, 0x28)
> read$usb(r0, &(0x7f0000004000-0xf)="000000000000000000000000", 0xc)
> read$usb(r0, &(0x7f0000004000)="00000000000000000000000000000000000000000000000000000000",
> 0x1c)
> 
> The second argument of write$usb (which is probably the most
> interesting call) is a structure of the following format:
> 
> usb_init {
>   tag const[0, int32]
>   config usb_config_descriptor
>   interface usb_interface_descriptor
>   device usb_device_descriptor
> } [packed]
> 
> usb_config_descriptor, usb_interface_descriptor and
> usb_device_descriptor correspond to kernel structures as defined in
> include/uapi/linux/usb/ch9.h
> 
> I noticed that both reports happen one after another on the same testcase.
> Below a part of the kernel log with both reports.
> 
> I hope some of that helps.

I'm still puzzled.  Can you try running the test with the diagnostic 
patch below?  The resulting kernel log ought to help pin down where the 
problem comes from.

Alan Stern



Index: usb-4.x/drivers/usb/gadget/udc/dummy_hcd.c
===================================================================
--- usb-4.x.orig/drivers/usb/gadget/udc/dummy_hcd.c
+++ usb-4.x/drivers/usb/gadget/udc/dummy_hcd.c
@@ -318,6 +318,7 @@ static void nuke(struct dummy *dum, stru
 		struct dummy_request	*req;
 
 		req = list_entry(ep->queue.next, struct dummy_request, queue);
+		pr_info("dummy: nuke %p ep %s\n", req, ep->ep.name);
 		list_del_init(&req->queue);
 		req->req.status = -ESHUTDOWN;
 
@@ -332,6 +333,8 @@ static void stop_activity(struct dummy *
 {
 	struct dummy_ep	*ep;
 
+	pr_info("dummy: stop_activity\n");
+
 	/* prevent any more requests */
 	dum->address = 0;
 
@@ -719,14 +722,17 @@ static int dummy_queue(struct usb_ep *_e
 		req->req.context = dum;
 		req->req.complete = fifo_complete;
 
+		pr_info("dummy: fake queue %p ep %s\n", req, _ep->name);
 		list_add_tail(&req->queue, &ep->queue);
 		spin_unlock(&dum->lock);
 		_req->actual = _req->length;
 		_req->status = 0;
 		usb_gadget_giveback_request(_ep, _req);
 		spin_lock(&dum->lock);
-	}  else
+	}  else {
+		pr_info("dummy: queue %p ep %s\n", req, _ep->name);
 		list_add_tail(&req->queue, &ep->queue);
+	}
 	spin_unlock_irqrestore(&dum->lock, flags);
 
 	/* real hardware would likely enable transfers here, in case
@@ -755,6 +761,7 @@ static int dummy_dequeue(struct usb_ep *
 	spin_lock(&dum->lock);
 	list_for_each_entry(req, &ep->queue, queue) {
 		if (&req->req == _req) {
+			pr_info("dummy: dequeue %p ep %s\n", req, _ep->name);
 			list_del_init(&req->queue);
 			_req->status = -ECONNRESET;
 			retval = 0;
@@ -1454,6 +1461,7 @@ top:
 
 		/* device side completion --> continuable */
 		if (req->req.status != -EINPROGRESS) {
+			pr_info("dummy: complete %p ep %s\n", req, ep->ep.name);
 			list_del_init(&req->queue);
 
 			spin_unlock(&dum->lock);
@@ -1827,6 +1835,7 @@ restart:
 			setup = *(struct usb_ctrlrequest *) urb->setup_packet;
 			/* paranoia, in case of stale queued data */
 			list_for_each_entry(req, &ep->queue, queue) {
+				pr_info("dummy: stale %p ep ep0\n", req);
 				list_del_init(&req->queue);
 				req->req.status = -EOVERFLOW;
 				dev_dbg(udc_dev(dum), "stale req = %p\n",

--
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