Skip to content

Commit 9b0cb77

Browse files
bvanasscheaxboe
authored andcommitted
loop: Fix use-after-free issues
do_req_filebacked() calls blk_mq_complete_request() synchronously or asynchronously when using asynchronous I/O unless memory allocation fails. Hence, modify loop_handle_cmd() such that it does not dereference 'cmd' nor 'rq' after do_req_filebacked() finished unless we are sure that the request has not yet been completed. This patch fixes the following kernel crash: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000054 Call trace: css_put.42938+0x1c/0x1ac loop_process_work+0xc8c/0xfd4 loop_rootcg_workfn+0x24/0x34 process_one_work+0x244/0x558 worker_thread+0x400/0x8fc kthread+0x16c/0x1e0 ret_from_fork+0x10/0x20 Cc: Christoph Hellwig <[email protected]> Cc: Ming Lei <[email protected]> Cc: Jan Kara <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Dan Schatzberg <[email protected]> Fixes: c74d40e ("loop: charge i/o to mem and blk cg") Fixes: bc07c10 ("block: loop: support DIO & AIO") Signed-off-by: Bart Van Assche <[email protected]> Reviewed-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 34e0a27 commit 9b0cb77

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

drivers/block/loop.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,35 +1859,44 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
18591859

18601860
static void loop_handle_cmd(struct loop_cmd *cmd)
18611861
{
1862+
struct cgroup_subsys_state *cmd_blkcg_css = cmd->blkcg_css;
1863+
struct cgroup_subsys_state *cmd_memcg_css = cmd->memcg_css;
18621864
struct request *rq = blk_mq_rq_from_pdu(cmd);
18631865
const bool write = op_is_write(req_op(rq));
18641866
struct loop_device *lo = rq->q->queuedata;
18651867
int ret = 0;
18661868
struct mem_cgroup *old_memcg = NULL;
1869+
const bool use_aio = cmd->use_aio;
18671870

18681871
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
18691872
ret = -EIO;
18701873
goto failed;
18711874
}
18721875

1873-
if (cmd->blkcg_css)
1874-
kthread_associate_blkcg(cmd->blkcg_css);
1875-
if (cmd->memcg_css)
1876+
if (cmd_blkcg_css)
1877+
kthread_associate_blkcg(cmd_blkcg_css);
1878+
if (cmd_memcg_css)
18761879
old_memcg = set_active_memcg(
1877-
mem_cgroup_from_css(cmd->memcg_css));
1880+
mem_cgroup_from_css(cmd_memcg_css));
18781881

1882+
/*
1883+
* do_req_filebacked() may call blk_mq_complete_request() synchronously
1884+
* or asynchronously if using aio. Hence, do not touch 'cmd' after
1885+
* do_req_filebacked() has returned unless we are sure that 'cmd' has
1886+
* not yet been completed.
1887+
*/
18791888
ret = do_req_filebacked(lo, rq);
18801889

1881-
if (cmd->blkcg_css)
1890+
if (cmd_blkcg_css)
18821891
kthread_associate_blkcg(NULL);
18831892

1884-
if (cmd->memcg_css) {
1893+
if (cmd_memcg_css) {
18851894
set_active_memcg(old_memcg);
1886-
css_put(cmd->memcg_css);
1895+
css_put(cmd_memcg_css);
18871896
}
18881897
failed:
18891898
/* complete non-aio request */
1890-
if (!cmd->use_aio || ret) {
1899+
if (!use_aio || ret) {
18911900
if (ret == -EOPNOTSUPP)
18921901
cmd->ret = ret;
18931902
else

0 commit comments

Comments
 (0)