| From 7fafcfdf6377b18b2a726ea554d6e593ba44349f Mon Sep 17 00:00:00 2001 |
| From: "Yavuz, Tuba" <tuba@ece.ufl.edu> |
| Date: Fri, 23 Mar 2018 17:00:38 +0000 |
| Subject: USB: gadget: f_midi: fixing a possible double-free in f_midi |
| |
| From: Yavuz, Tuba <tuba@ece.ufl.edu> |
| |
| commit 7fafcfdf6377b18b2a726ea554d6e593ba44349f upstream. |
| |
| It looks like there is a possibility of a double-free vulnerability on an |
| error path of the f_midi_set_alt function in the f_midi driver. If the |
| path is feasible then free_ep_req gets called twice: |
| |
| req->complete = f_midi_complete; |
| err = usb_ep_queue(midi->out_ep, req, GFP_ATOMIC); |
| => ... |
| usb_gadget_giveback_request |
| => |
| f_midi_complete (CALLBACK) |
| (inside f_midi_complete, for various cases of status) |
| free_ep_req(ep, req); // first kfree |
| if (err) { |
| ERROR(midi, "%s: couldn't enqueue request: %d\n", |
| midi->out_ep->name, err); |
| free_ep_req(midi->out_ep, req); // second kfree |
| return err; |
| } |
| |
| The double-free possibility was introduced with commit ad0d1a058eac |
| ("usb: gadget: f_midi: fix leak on failed to enqueue out requests"). |
| |
| Found by MOXCAFE tool. |
| |
| Signed-off-by: Tuba Yavuz <tuba@ece.ufl.edu> |
| Fixes: ad0d1a058eac ("usb: gadget: f_midi: fix leak on failed to enqueue out requests") |
| Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/gadget/function/f_midi.c | 3 ++- |
| drivers/usb/gadget/u_f.h | 2 ++ |
| 2 files changed, 4 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/usb/gadget/function/f_midi.c |
| +++ b/drivers/usb/gadget/function/f_midi.c |
| @@ -389,7 +389,8 @@ static int f_midi_set_alt(struct usb_fun |
| if (err) { |
| ERROR(midi, "%s: couldn't enqueue request: %d\n", |
| midi->out_ep->name, err); |
| - free_ep_req(midi->out_ep, req); |
| + if (req->buf != NULL) |
| + free_ep_req(midi->out_ep, req); |
| return err; |
| } |
| } |
| --- a/drivers/usb/gadget/u_f.h |
| +++ b/drivers/usb/gadget/u_f.h |
| @@ -64,7 +64,9 @@ struct usb_request *alloc_ep_req(struct |
| /* Frees a usb_request previously allocated by alloc_ep_req() */ |
| static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req) |
| { |
| + WARN_ON(req->buf == NULL); |
| kfree(req->buf); |
| + req->buf = NULL; |
| usb_ep_free_request(ep, req); |
| } |
| |