Jan Kara 44937a
From fb889bf5d394f9de2326e33a2a24e9aacafd1509 Mon Sep 17 00:00:00 2001
Jan Kara 44937a
From: Jan Kara <jack@suse.cz>
Jan Kara 44937a
Date: Tue, 21 Dec 2021 19:37:32 +0100
Jan Kara 44937a
Subject: [PATCH 2/9] bfq: Avoid merging queues with different parents
Jan Kara 44937a
References: bsc#1197926
Jan Kara 44937a
Patch-mainline: submitted, in linux-block tree
Jan Kara 44937a
Jan Kara 44937a
It can happen that the parent of a bfqq changes between the moment we
Jan Kara 44937a
decide two queues are worth to merge (and set bic->stable_merge_bfqq)
Jan Kara 44937a
and the moment bfq_setup_merge() is called. This can happen e.g. because
Jan Kara 44937a
the process submitted IO for a different cgroup and thus bfqq got
Jan Kara 44937a
reparented. It can even happen that the bfqq we are merging with has
Jan Kara 44937a
parent cgroup that is already offline and going to be destroyed in which
Jan Kara 44937a
case the merge can lead to use-after-free issues such as:
Jan Kara 44937a
Jan Kara 44937a
Bug: KASAN: use-after-free in __bfq_deactivate_entity+0x9cb/0xa50
Jan Kara 44937a
Read of size 8 at addr ffff88800693c0c0 by task runc:[2:INIT]/10544
Jan Kara 44937a
Jan Kara 44937a
Cpu: 0 PID: 10544 Comm: runc:[2:INIT] Tainted: G            E     5.15.2-0.g5fb85fd-default #1 openSUSE Tumbleweed (unreleased) f1f3b891c72369aebecd2e43e4641a6358867c70
Jan Kara 44937a
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a-rebuilt.opensuse.org 04/01/2014
Jan Kara 44937a
Call Trace:
Jan Kara 44937a
 <IRQ>
Jan Kara 44937a
 dump_stack_lvl+0x46/0x5a
Jan Kara 44937a
 print_address_description.constprop.0+0x1f/0x140
Jan Kara 44937a
 ? __bfq_deactivate_entity+0x9cb/0xa50
Jan Kara 44937a
 kasan_report.cold+0x7f/0x11b
Jan Kara 44937a
 ? __bfq_deactivate_entity+0x9cb/0xa50
Jan Kara 44937a
 __bfq_deactivate_entity+0x9cb/0xa50
Jan Kara 44937a
 ? update_curr+0x32f/0x5d0
Jan Kara 44937a
 bfq_deactivate_entity+0xa0/0x1d0
Jan Kara 44937a
 bfq_del_bfqq_busy+0x28a/0x420
Jan Kara 44937a
 ? resched_curr+0x116/0x1d0
Jan Kara 44937a
 ? bfq_requeue_bfqq+0x70/0x70
Jan Kara 44937a
 ? check_preempt_wakeup+0x52b/0xbc0
Jan Kara 44937a
 __bfq_bfqq_expire+0x1a2/0x270
Jan Kara 44937a
 bfq_bfqq_expire+0xd16/0x2160
Jan Kara 44937a
 ? try_to_wake_up+0x4ee/0x1260
Jan Kara 44937a
 ? bfq_end_wr_async_queues+0xe0/0xe0
Jan Kara 44937a
 ? _raw_write_unlock_bh+0x60/0x60
Jan Kara 44937a
 ? _raw_spin_lock_irq+0x81/0xe0
Jan Kara 44937a
 bfq_idle_slice_timer+0x109/0x280
Jan Kara 44937a
 ? bfq_dispatch_request+0x4870/0x4870
Jan Kara 44937a
 __hrtimer_run_queues+0x37d/0x700
Jan Kara 44937a
 ? enqueue_hrtimer+0x1b0/0x1b0
Jan Kara 44937a
 ? kvm_clock_get_cycles+0xd/0x10
Jan Kara 44937a
 ? ktime_get_update_offsets_now+0x6f/0x280
Jan Kara 44937a
 hrtimer_interrupt+0x2c8/0x740
Jan Kara 44937a
Jan Kara 44937a
Fix the problem by checking that the parent of the two bfqqs we are
Jan Kara 44937a
merging in bfq_setup_merge() is the same.
Jan Kara 44937a
Jan Kara 44937a
Link: https://lore.kernel.org/linux-block/20211125172809.GC19572@quack2.suse.cz/
Jan Kara 44937a
Cc: stable@vger.kernel.org
Jan Kara 44937a
Fixes: 430a67f9d616 ("block, bfq: merge bursts of newly-created queues")
Jan Kara 44937a
Tested-by: "yukuai (C)" <yukuai3@huawei.com>
Jan Kara 44937a
Signed-off-by: Jan Kara <jack@suse.cz>
Jan Kara 44937a
Jan Kara 44937a
---
Jan Kara 44937a
 block/bfq-iosched.c | 8 ++++++++
Jan Kara 44937a
 1 file changed, 8 insertions(+)
Jan Kara 44937a
Jan Kara 44937a
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
Jan Kara 44937a
index 6d122c28086e..7d00b21ebe5d 100644
Jan Kara 44937a
--- a/block/bfq-iosched.c
Jan Kara 44937a
+++ b/block/bfq-iosched.c
Jan Kara 44937a
@@ -2758,6 +2758,14 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
Jan Kara 44937a
 	if (process_refs == 0 || new_process_refs == 0)
Jan Kara 44937a
 		return NULL;
Jan Kara 44937a
 
Jan Kara 44937a
+	/*
Jan Kara 44937a
+	 * Make sure merged queues belong to the same parent. Parents could
Jan Kara 44937a
+	 * have changed since the time we decided the two queues are suitable
Jan Kara 44937a
+	 * for merging.
Jan Kara 44937a
+	 */
Jan Kara 44937a
+	if (new_bfqq->entity.parent != bfqq->entity.parent)
Jan Kara 44937a
+		return NULL;
Jan Kara 44937a
+
Jan Kara 44937a
 	bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d",
Jan Kara 44937a
 		new_bfqq->pid);
Jan Kara 44937a
 
Jan Kara 44937a
-- 
Jan Kara 44937a
2.34.1
Jan Kara 44937a