Blame SOURCES/block-block-bfq-fix-use-after-free-in-bfq_idle_slice.patch

ebf353
From 85e1ebd935f809b165daccae23144de5611989f3 Mon Sep 17 00:00:00 2001
ebf353
From: Artem Savkov <asavkov@redhat.com>
ebf353
Date: Mon, 25 May 2020 09:29:32 +0200
ebf353
Subject: [KPATCH 8.2 BZ1835538 PATCH] [block] block, bfq: fix use-after-free in
ebf353
 bfq_idle_slice_timer_body
ebf353
ebf353
Kernels:
ebf353
4.18.0-193.el8
ebf353
4.18.0-193.1.2.el8_2
ebf353
ebf353
Changes since last build:
ebf353
arches: x86_64 ppc64le
ebf353
bfq-iosched.o: changed function: bfq_idle_slice_timer
ebf353
---------------------------
ebf353
ebf353
Modifications: none
ebf353
ebf353
commit 9bc03301d07fb521f7566e6b5054eb27968a5e88
ebf353
Author: Ming Lei <ming.lei@redhat.com>
ebf353
Date:   Wed Apr 15 13:16:30 2020 -0400
ebf353
ebf353
    [block] block, bfq: fix use-after-free in bfq_idle_slice_timer_body
ebf353
ebf353
    Message-id: <20200415131630.2708071-12-ming.lei@redhat.com>
ebf353
    Patchwork-id: 302228
ebf353
    Patchwork-instance: patchwork
ebf353
    O-Subject: [RHEL8.3 11/11] block, bfq: fix use-after-free in bfq_idle_slice_timer_body
ebf353
    Bugzilla: 1835532
ebf353
    Z-Bugzilla: 1835531
ebf353
    CVE: CVE-2020-12657
ebf353
    RH-Acked-by: Vivek Goyal <vgoyal@redhat.com>
ebf353
    RH-Acked-by: Ewan Milne <emilne@redhat.com>
ebf353
ebf353
    From: Zhiqiang Liu <liuzhiqiang26@huawei.com>
ebf353
ebf353
    BZ: 1823596
ebf353
ebf353
    commit 2f95fa5c955d0a9987ffdc3a095e2f4e62c5f2a9
ebf353
    Author: Zhiqiang Liu <liuzhiqiang26@huawei.com>
ebf353
    Date:   Thu Mar 19 19:18:13 2020 +0800
ebf353
ebf353
        block, bfq: fix use-after-free in bfq_idle_slice_timer_body
ebf353
ebf353
        In bfq_idle_slice_timer func, bfqq = bfqd->in_service_queue is
ebf353
        not in bfqd-lock critical section. The bfqq, which is not
ebf353
        equal to NULL in bfq_idle_slice_timer, may be freed after passing
ebf353
        to bfq_idle_slice_timer_body. So we will access the freed memory.
ebf353
ebf353
        In addition, considering the bfqq may be in race, we should
ebf353
        firstly check whether bfqq is in service before doing something
ebf353
        on it in bfq_idle_slice_timer_body func. If the bfqq in race is
ebf353
        not in service, it means the bfqq has been expired through
ebf353
        __bfq_bfqq_expire func, and wait_request flags has been cleared in
ebf353
        __bfq_bfqd_reset_in_service func. So we do not need to re-clear the
ebf353
        wait_request of bfqq which is not in service.
ebf353
ebf353
        KASAN log is given as follows:
ebf353
        [13058.354613] ==================================================================
ebf353
        [13058.354640] BUG: KASAN: use-after-free in bfq_idle_slice_timer+0xac/0x290
ebf353
        [13058.354644] Read of size 8 at addr ffffa02cf3e63f78 by task fork13/19767
ebf353
        [13058.354646]
ebf353
        [13058.354655] CPU: 96 PID: 19767 Comm: fork13
ebf353
        [13058.354661] Call trace:
ebf353
        [13058.354667]  dump_backtrace+0x0/0x310
ebf353
        [13058.354672]  show_stack+0x28/0x38
ebf353
        [13058.354681]  dump_stack+0xd8/0x108
ebf353
        [13058.354687]  print_address_description+0x68/0x2d0
ebf353
        [13058.354690]  kasan_report+0x124/0x2e0
ebf353
        [13058.354697]  __asan_load8+0x88/0xb0
ebf353
        [13058.354702]  bfq_idle_slice_timer+0xac/0x290
ebf353
        [13058.354707]  __hrtimer_run_queues+0x298/0x8b8
ebf353
        [13058.354710]  hrtimer_interrupt+0x1b8/0x678
ebf353
        [13058.354716]  arch_timer_handler_phys+0x4c/0x78
ebf353
        [13058.354722]  handle_percpu_devid_irq+0xf0/0x558
ebf353
        [13058.354731]  generic_handle_irq+0x50/0x70
ebf353
        [13058.354735]  __handle_domain_irq+0x94/0x110
ebf353
        [13058.354739]  gic_handle_irq+0x8c/0x1b0
ebf353
        [13058.354742]  el1_irq+0xb8/0x140
ebf353
        [13058.354748]  do_wp_page+0x260/0xe28
ebf353
        [13058.354752]  __handle_mm_fault+0x8ec/0x9b0
ebf353
        [13058.354756]  handle_mm_fault+0x280/0x460
ebf353
        [13058.354762]  do_page_fault+0x3ec/0x890
ebf353
        [13058.354765]  do_mem_abort+0xc0/0x1b0
ebf353
        [13058.354768]  el0_da+0x24/0x28
ebf353
        [13058.354770]
ebf353
        [13058.354773] Allocated by task 19731:
ebf353
        [13058.354780]  kasan_kmalloc+0xe0/0x190
ebf353
        [13058.354784]  kasan_slab_alloc+0x14/0x20
ebf353
        [13058.354788]  kmem_cache_alloc_node+0x130/0x440
ebf353
        [13058.354793]  bfq_get_queue+0x138/0x858
ebf353
        [13058.354797]  bfq_get_bfqq_handle_split+0xd4/0x328
ebf353
        [13058.354801]  bfq_init_rq+0x1f4/0x1180
ebf353
        [13058.354806]  bfq_insert_requests+0x264/0x1c98
ebf353
        [13058.354811]  blk_mq_sched_insert_requests+0x1c4/0x488
ebf353
        [13058.354818]  blk_mq_flush_plug_list+0x2d4/0x6e0
ebf353
        [13058.354826]  blk_flush_plug_list+0x230/0x548
ebf353
        [13058.354830]  blk_finish_plug+0x60/0x80
ebf353
        [13058.354838]  read_pages+0xec/0x2c0
ebf353
        [13058.354842]  __do_page_cache_readahead+0x374/0x438
ebf353
        [13058.354846]  ondemand_readahead+0x24c/0x6b0
ebf353
        [13058.354851]  page_cache_sync_readahead+0x17c/0x2f8
ebf353
        [13058.354858]  generic_file_buffered_read+0x588/0xc58
ebf353
        [13058.354862]  generic_file_read_iter+0x1b4/0x278
ebf353
        [13058.354965]  ext4_file_read_iter+0xa8/0x1d8 [ext4]
ebf353
        [13058.354972]  __vfs_read+0x238/0x320
ebf353
        [13058.354976]  vfs_read+0xbc/0x1c0
ebf353
        [13058.354980]  ksys_read+0xdc/0x1b8
ebf353
        [13058.354984]  __arm64_sys_read+0x50/0x60
ebf353
        [13058.354990]  el0_svc_common+0xb4/0x1d8
ebf353
        [13058.354994]  el0_svc_handler+0x50/0xa8
ebf353
        [13058.354998]  el0_svc+0x8/0xc
ebf353
        [13058.354999]
ebf353
        [13058.355001] Freed by task 19731:
ebf353
        [13058.355007]  __kasan_slab_free+0x120/0x228
ebf353
        [13058.355010]  kasan_slab_free+0x10/0x18
ebf353
        [13058.355014]  kmem_cache_free+0x288/0x3f0
ebf353
        [13058.355018]  bfq_put_queue+0x134/0x208
ebf353
        [13058.355022]  bfq_exit_icq_bfqq+0x164/0x348
ebf353
        [13058.355026]  bfq_exit_icq+0x28/0x40
ebf353
        [13058.355030]  ioc_exit_icq+0xa0/0x150
ebf353
        [13058.355035]  put_io_context_active+0x250/0x438
ebf353
        [13058.355038]  exit_io_context+0xd0/0x138
ebf353
        [13058.355045]  do_exit+0x734/0xc58
ebf353
        [13058.355050]  do_group_exit+0x78/0x220
ebf353
        [13058.355054]  __wake_up_parent+0x0/0x50
ebf353
        [13058.355058]  el0_svc_common+0xb4/0x1d8
ebf353
        [13058.355062]  el0_svc_handler+0x50/0xa8
ebf353
        [13058.355066]  el0_svc+0x8/0xc
ebf353
        [13058.355067]
ebf353
        [13058.355071] The buggy address belongs to the object at ffffa02cf3e63e70#012 which belongs to the cache bfq_queue of size 464
ebf353
        [13058.355075] The buggy address is located 264 bytes inside of#012 464-byte region [ffffa02cf3e63e70, ffffa02cf3e64040)
ebf353
        [13058.355077] The buggy address belongs to the page:
ebf353
        [13058.355083] page:ffff7e80b3cf9800 count:1 mapcount:0 mapping:ffff802db5c90780 index:0xffffa02cf3e606f0 compound_mapcount: 0
ebf353
        [13058.366175] flags: 0x2ffffe0000008100(slab|head)
ebf353
        [13058.370781] raw: 2ffffe0000008100 ffff7e80b53b1408 ffffa02d730c1c90 ffff802db5c90780
ebf353
        [13058.370787] raw: ffffa02cf3e606f0 0000000000370023 00000001ffffffff 0000000000000000
ebf353
        [13058.370789] page dumped because: kasan: bad access detected
ebf353
        [13058.370791]
ebf353
        [13058.370792] Memory state around the buggy address:
ebf353
        [13058.370797]  ffffa02cf3e63e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fb fb
ebf353
        [13058.370801]  ffffa02cf3e63e80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ebf353
        [13058.370805] >ffffa02cf3e63f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ebf353
        [13058.370808]                                                                 ^
ebf353
        [13058.370811]  ffffa02cf3e63f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ebf353
        [13058.370815]  ffffa02cf3e64000: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ebf353
        [13058.370817] ==================================================================
ebf353
        [13058.370820] Disabling lock debugging due to kernel taint
ebf353
ebf353
        Here, we directly pass the bfqd to bfq_idle_slice_timer_body func.
ebf353
        --
ebf353
        V2->V3: rewrite the comment as suggested by Paolo Valente
ebf353
        V1->V2: add one comment, and add Fixes and Reported-by tag.
ebf353
ebf353
        Fixes: aee69d78d ("block, bfq: introduce the BFQ-v0 I/O scheduler as an extra scheduler")
ebf353
        Acked-by: Paolo Valente <paolo.valente@linaro.org>
ebf353
        Reported-by: Wang Wang <wangwang2@huawei.com>
ebf353
        Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
ebf353
        Signed-off-by: Feilong Lin <linfeilong@huawei.com>
ebf353
        Signed-off-by: Jens Axboe <axboe@kernel.dk>
ebf353
ebf353
    Signed-off-by: Ming Lei <ming.lei@redhat.com>
ebf353
    Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
ebf353
ebf353
Signed-off-by: Artem Savkov <asavkov@redhat.com>
ebf353
Acked-by: Julien Thierry <jthierry@redhat.com>
ebf353
Acked-by: Yannick Cote <ycote@redhat.com>
ebf353
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
ebf353
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
ebf353
---
ebf353
 block/bfq-iosched.c | 16 ++++++++++++----
ebf353
 1 file changed, 12 insertions(+), 4 deletions(-)
ebf353
ebf353
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
ebf353
index 9b492dfb7602..be2c1708c82d 100644
ebf353
--- a/block/bfq-iosched.c
ebf353
+++ b/block/bfq-iosched.c
ebf353
@@ -6188,20 +6188,28 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
ebf353
 	return bfqq;
ebf353
 }
ebf353
 
ebf353
-static void bfq_idle_slice_timer_body(struct bfq_queue *bfqq)
ebf353
+static void
ebf353
+bfq_idle_slice_timer_body(struct bfq_data *bfqd, struct bfq_queue *bfqq)
ebf353
 {
ebf353
-	struct bfq_data *bfqd = bfqq->bfqd;
ebf353
 	enum bfqq_expiration reason;
ebf353
 	unsigned long flags;
ebf353
 
ebf353
 	spin_lock_irqsave(&bfqd->lock, flags);
ebf353
-	bfq_clear_bfqq_wait_request(bfqq);
ebf353
 
ebf353
+	/*
ebf353
+	 * Considering that bfqq may be in race, we should firstly check
ebf353
+	 * whether bfqq is in service before doing something on it. If
ebf353
+	 * the bfqq in race is not in service, it has already been expired
ebf353
+	 * through __bfq_bfqq_expire func and its wait_request flags has
ebf353
+	 * been cleared in __bfq_bfqd_reset_in_service func.
ebf353
+	 */
ebf353
 	if (bfqq != bfqd->in_service_queue) {
ebf353
 		spin_unlock_irqrestore(&bfqd->lock, flags);
ebf353
 		return;
ebf353
 	}
ebf353
 
ebf353
+	bfq_clear_bfqq_wait_request(bfqq);
ebf353
+
ebf353
 	if (bfq_bfqq_budget_timeout(bfqq))
ebf353
 		/*
ebf353
 		 * Also here the queue can be safely expired
ebf353
@@ -6246,7 +6254,7 @@ static enum hrtimer_restart bfq_idle_slice_timer(struct hrtimer *timer)
ebf353
 	 * early.
ebf353
 	 */
ebf353
 	if (bfqq)
ebf353
-		bfq_idle_slice_timer_body(bfqq);
ebf353
+		bfq_idle_slice_timer_body(bfqd, bfqq);
ebf353
 
ebf353
 	return HRTIMER_NORESTART;
ebf353
 }
ebf353
-- 
ebf353
2.21.3
ebf353