Skip to content

Commit ecfe88a

Browse files
author
Ming Lei
committed
loop: Fix use-after-free issues
JIRA: https://issues.redhat.com/browse/RHEL-87488 commit 9b0cb77 Author: Bart Van Assche <bvanassche@acm.org> Date: Tue Mar 14 11:21:54 2023 -0700 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 <hch@lst.de> Cc: Ming Lei <ming.lei@redhat.com> Cc: Jan Kara <jack@suse.cz> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Dan Schatzberg <schatzberg.dan@gmail.com> Fixes: c74d40e ("loop: charge i/o to mem and blk cg") Fixes: bc07c10 ("block: loop: support DIO & AIO") Signed-off-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20230314182155.80625-1-bvanassche@acm.org Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Ming Lei <ming.lei@redhat.com>
1 parent d7ed855 commit ecfe88a

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
@@ -1902,35 +1902,44 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
19021902

19031903
static void loop_handle_cmd(struct loop_cmd *cmd)
19041904
{
1905+
struct cgroup_subsys_state *cmd_blkcg_css = cmd->blkcg_css;
1906+
struct cgroup_subsys_state *cmd_memcg_css = cmd->memcg_css;
19051907
struct request *rq = blk_mq_rq_from_pdu(cmd);
19061908
const bool write = op_is_write(req_op(rq));
19071909
struct loop_device *lo = rq->q->queuedata;
19081910
int ret = 0;
19091911
struct mem_cgroup *old_memcg = NULL;
1912+
const bool use_aio = cmd->use_aio;
19101913

19111914
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
19121915
ret = -EIO;
19131916
goto failed;
19141917
}
19151918

1916-
if (cmd->blkcg_css)
1917-
kthread_associate_blkcg(cmd->blkcg_css);
1918-
if (cmd->memcg_css)
1919+
if (cmd_blkcg_css)
1920+
kthread_associate_blkcg(cmd_blkcg_css);
1921+
if (cmd_memcg_css)
19191922
old_memcg = set_active_memcg(
1920-
mem_cgroup_from_css(cmd->memcg_css));
1923+
mem_cgroup_from_css(cmd_memcg_css));
19211924

1925+
/*
1926+
* do_req_filebacked() may call blk_mq_complete_request() synchronously
1927+
* or asynchronously if using aio. Hence, do not touch 'cmd' after
1928+
* do_req_filebacked() has returned unless we are sure that 'cmd' has
1929+
* not yet been completed.
1930+
*/
19221931
ret = do_req_filebacked(lo, rq);
19231932

1924-
if (cmd->blkcg_css)
1933+
if (cmd_blkcg_css)
19251934
kthread_associate_blkcg(NULL);
19261935

1927-
if (cmd->memcg_css) {
1936+
if (cmd_memcg_css) {
19281937
set_active_memcg(old_memcg);
1929-
css_put(cmd->memcg_css);
1938+
css_put(cmd_memcg_css);
19301939
}
19311940
failed:
19321941
/* complete non-aio request */
1933-
if (!cmd->use_aio || ret) {
1942+
if (!use_aio || ret) {
19341943
if (ret == -EOPNOTSUPP)
19351944
cmd->ret = ret;
19361945
else

0 commit comments

Comments
 (0)