From: Dongwoo Lee Date: Fri, 22 Jan 2021 03:40:18 +0000 (+0900) Subject: usb: gadget: f_fs: Fix use-after-free for unbind with remaining io X-Git-Tag: accepted/tizen/unified/20210122.123002^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1bb1d541a20f521baabc6849145d72c09d95ed0a;p=platform%2Fkernel%2Flinux-rpi.git usb: gadget: f_fs: Fix use-after-free for unbind with remaining io If usb has stall, then there can be remaining submitted io and unbinding f_fs with the remaining io, there is use-after-free. Fix the use-after-free by checking endpoint after wait. This fixes following kasan warning: BUG: KASAN: use-after-free in ffs_epfile_io+0x654/0xb58 Read of size 4 at addr ffffffc0a44e65dc by task mtp-responder/5117 ... [] ffs_epfile_io+0x654/0xb58 [] ffs_epfile_read_iter+0x1ac/0x3e0 ... Allocated by task 3869: ... __kmalloc+0x234/0x760 _ffs_func_bind+0x264/0x7c8 ffs_func_bind+0xe8/0x650 usb_add_function+0x13c/0x378 ... Freed by task 3869: ... kfree+0xa4/0x750 ffs_func_unbind+0x150/0x248 purge_configs_funcs+0x1a0/0x310 ... Signed-off-by: Seung-Woo Kim [dwoo08.lee: cherry-picked from linux-amlogic commit 5dd3ffecd46f to prevent use-after-free when f_fs is unbound before all requests are over] Signed-off-by: Dongwoo Lee Change-Id: Idf2391c53ca0f90fc9484d725304b88fc57fa8a6 --- diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 6f0c28f..c8450fe 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1101,7 +1101,8 @@ retry_malloc: spin_unlock_irq(&epfile->ffs->eps_lock); - if (unlikely(wait_for_completion_interruptible(&done))) { + if (unlikely(wait_for_completion_interruptible(&done)) && + epfile->ep) { /* * To avoid race condition with ffs_epfile_io_complete, * dequeue the request first then check @@ -1113,6 +1114,12 @@ retry_malloc: interrupted = ep->status < 0; } + if (epfile->ep != ep) { + /* In the meantime, endpoint got disabled or changed. */ + ret = -ESHUTDOWN; + goto error_mutex; + } + if (interrupted) ret = -EINTR; else if (io_data->read && ep->status > 0)