mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
USB: gadget: ffs: fix mm lifetime handling
io_data stores a pointer to the submitting task's mm_struct, but does not currently hold a reference to it while async requests are pending. This can result in a use-after-free if the task exits before completion handling finishes. Take a reference with mmgrab() when queuing the read request and release it with mmdrop() on request completion. Reported-by: Gabriel Prostitis <prostitisgabriel@gmail.com> Signed-off-by: Gabriel Prostitis <prostitisgabriel@gmail.com> Link: https://patch.msgid.link/20260601-mm-uaf-fix-v2-1-3c942a707bce@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
3a1c90aeb9
commit
5eb5c72c72
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user