Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] blk: fix dangling pointer access in __elv_add_request

cfq's add_req_fn callback may invoke q->request_fn directly and
depending on low-level driver used and timing, a queued request may be
finished & deallocated before add_req_fn callback returns. So,
__elv_add_request must not access rq after it's passed to add_req_fn
callback.

This patch moves rq_mergeable test above add_req_fn(). This may
result in q->last_merge pointing to REQ_NOMERGE request if add_req_fn
callback sets it but as RQ_NOMERGE is checked again when blk layer
actually tries to merge requests, this does not cause any problem.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Tejun Heo and committed by
Linus Torvalds
ca23509f 6c2af71f

+6 -1
+6 -1
drivers/block/elevator.c
··· 369 369 case ELEVATOR_INSERT_SORT: 370 370 BUG_ON(!blk_fs_request(rq)); 371 371 rq->flags |= REQ_SORTED; 372 - q->elevator->ops->elevator_add_req_fn(q, rq); 373 372 if (q->last_merge == NULL && rq_mergeable(rq)) 374 373 q->last_merge = rq; 374 + /* 375 + * Some ioscheds (cfq) run q->request_fn directly, so 376 + * rq cannot be accessed after calling 377 + * elevator_add_req_fn. 378 + */ 379 + q->elevator->ops->elevator_add_req_fn(q, rq); 375 380 break; 376 381 377 382 default: