mmc: fix use-after-free of struct request
We call mmc_req_is_special() after having processed a request, but
it could be freed after that. Check that ahead of time, and use
the cached value.
Reported-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Fixes: c2df40dfb8
("drivers: use req op accessor")
Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
f2791e7ead
commit
869c554808
@ -2151,6 +2151,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
|
|||||||
struct mmc_card *card = md->queue.card;
|
struct mmc_card *card = md->queue.card;
|
||||||
struct mmc_host *host = card->host;
|
struct mmc_host *host = card->host;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
bool req_is_special = mmc_req_is_special(req);
|
||||||
|
|
||||||
if (req && !mq->mqrq_prev->req)
|
if (req && !mq->mqrq_prev->req)
|
||||||
/* claim host only for the first request */
|
/* claim host only for the first request */
|
||||||
@ -2191,8 +2192,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
|
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || req_is_special)
|
||||||
mmc_req_is_special(req))
|
|
||||||
/*
|
/*
|
||||||
* Release host when there are no more requests
|
* Release host when there are no more requests
|
||||||
* and after special request(discard, flush) is done.
|
* and after special request(discard, flush) is done.
|
||||||
|
@ -65,6 +65,8 @@ static int mmc_queue_thread(void *d)
|
|||||||
spin_unlock_irq(q->queue_lock);
|
spin_unlock_irq(q->queue_lock);
|
||||||
|
|
||||||
if (req || mq->mqrq_prev->req) {
|
if (req || mq->mqrq_prev->req) {
|
||||||
|
bool req_is_special = mmc_req_is_special(req);
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
mq->issue_fn(mq, req);
|
mq->issue_fn(mq, req);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@ -80,7 +82,7 @@ static int mmc_queue_thread(void *d)
|
|||||||
* has been finished. Do not assign it to previous
|
* has been finished. Do not assign it to previous
|
||||||
* request.
|
* request.
|
||||||
*/
|
*/
|
||||||
if (mmc_req_is_special(req))
|
if (req_is_special)
|
||||||
mq->mqrq_cur->req = NULL;
|
mq->mqrq_cur->req = NULL;
|
||||||
|
|
||||||
mq->mqrq_prev->brq.mrq.data = NULL;
|
mq->mqrq_prev->brq.mrq.data = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user