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

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