Commit 869c5548 authored by Adrian Hunter's avatar Adrian Hunter Committed by Jens Axboe

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: default avatarHans de Goede <hdegoede@redhat.com>
Tested-by: default avatarHans de Goede <hdegoede@redhat.com>
Fixes: c2df40df ("drivers: use req op accessor")
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent f2791e7e
...@@ -2151,6 +2151,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment