From 1c3b63b8d818c6469317fceb2eb1285cba5d127a Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Tue, 2 Feb 2021 14:42:56 +0530 Subject: [PATCH] usb: f_fs: Avoid use-after-free of epfile Consider a case where ffs_func_eps_disable is called from ffs_func_disable as part of composition switch and at the same time ffs_epfile_release get called from userspace. ffs_epfile_release will free up the read buffer and call ffs_data_closed which in turn destroys ffs->epfiles and mark it as NULL. While this was happening the driver has already initialized the local epfile in ffs_func_eps_disable which is now freed and waiting to acquire the spinlock. Once spinlock is acquired the driver proceeds with the stale value of epfile and tries to free the already freed read buffer casuing use-after-free. Fix this race by assigning epfile under spin_lock from ffs_func_eps_disable. Change-Id: I9e1f376bb2212e8a8040f884514342c428098bdd Signed-off-by: Pratham Pratap --- drivers/usb/gadget/function/f_fs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 94a0d91fafa0..ecb6395eddd8 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2152,16 +2152,19 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) static void ffs_func_eps_disable(struct ffs_function *func) { - struct ffs_ep *ep = func->eps; struct ffs_data *ffs = func->ffs; - struct ffs_epfile *epfile = func->ffs->epfiles; - unsigned count = func->ffs->eps_count; + struct ffs_ep *ep; + struct ffs_epfile *epfile; + unsigned short count; unsigned long flags; ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state, func->ffs->setup_state, func->ffs->flags); spin_lock_irqsave(&func->ffs->eps_lock, flags); + count = func->ffs->eps_count; + epfile = func->ffs->epfiles; + ep = func->eps; while (count--) { /* pending requests get nuked */ if (likely(ep->ep))