diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d7ae4d75d5f5..e23cd18016ba 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -869,9 +869,15 @@ static void ffs_user_copy_worker(struct work_struct *work) bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; if (io_data->read && ret > 0) { - kthread_use_mm(io_data->mm); - ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data); - kthread_unuse_mm(io_data->mm); + if (mmget_not_zero(io_data->mm)) { + kthread_use_mm(io_data->mm); + ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data); + kthread_unuse_mm(io_data->mm); + mmput(io_data->mm); + } else { + ret = -EFAULT; + } + mmdrop(io_data->mm); } io_data->kiocb->ki_complete(io_data->kiocb, ret); @@ -1274,16 +1280,20 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) kiocb->private = p; - if (p->aio) + if (p->aio) { + mmgrab(p->mm); kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); + } res = ffs_epfile_io(kiocb->ki_filp, p); if (res == -EIOCBQUEUED) return res; - if (p->aio) + if (p->aio) { + mmdrop(p->mm); kfree(p); - else + } else { *from = p->data; + } return res; } @@ -1318,14 +1328,17 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) kiocb->private = p; - if (p->aio) + if (p->aio) { + mmgrab(p->mm); kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); + } res = ffs_epfile_io(kiocb->ki_filp, p); if (res == -EIOCBQUEUED) return res; if (p->aio) { + mmdrop(p->mm); kfree(p->to_free); kfree(p); } else {