linux-stable/block
Yu Kuai 1dd81337f3 block, bfq: fix null pointer dereference in bfq_bio_bfqg()
[ Upstream commit f02be9002c ]

Out test found a following problem in kernel 5.10, and the same problem
should exist in mainline:

BUG: kernel NULL pointer dereference, address: 0000000000000094
PGD 0 P4D 0
Oops: 0000 [#1] SMP
CPU: 7 PID: 155 Comm: kworker/7:1 Not tainted 5.10.0-01932-g19e0ace2ca1d-dirty 4
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-b4
Workqueue: kthrotld blk_throtl_dispatch_work_fn
RIP: 0010:bfq_bio_bfqg+0x52/0xc0
Code: 94 00 00 00 00 75 2e 48 8b 40 30 48 83 05 35 06 c8 0b 01 48 85 c0 74 3d 4b
RSP: 0018:ffffc90001a1fba0 EFLAGS: 00010002
RAX: ffff888100d60400 RBX: ffff8881132e7000 RCX: 0000000000000000
RDX: 0000000000000017 RSI: ffff888103580a18 RDI: ffff888103580a18
RBP: ffff8881132e7000 R08: 0000000000000000 R09: ffffc90001a1fe10
R10: 0000000000000a20 R11: 0000000000034320 R12: 0000000000000000
R13: ffff888103580a18 R14: ffff888114447000 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff88881fdc0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000094 CR3: 0000000100cdb000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 bfq_bic_update_cgroup+0x3c/0x350
 ? ioc_create_icq+0x42/0x270
 bfq_init_rq+0xfd/0x1060
 bfq_insert_requests+0x20f/0x1cc0
 ? ioc_create_icq+0x122/0x270
 blk_mq_sched_insert_requests+0x86/0x1d0
 blk_mq_flush_plug_list+0x193/0x2a0
 blk_flush_plug_list+0x127/0x170
 blk_finish_plug+0x31/0x50
 blk_throtl_dispatch_work_fn+0x151/0x190
 process_one_work+0x27c/0x5f0
 worker_thread+0x28b/0x6b0
 ? rescuer_thread+0x590/0x590
 kthread+0x153/0x1b0
 ? kthread_flush_work+0x170/0x170
 ret_from_fork+0x1f/0x30
Modules linked in:
CR2: 0000000000000094
---[ end trace e2e59ac014314547 ]---
RIP: 0010:bfq_bio_bfqg+0x52/0xc0
Code: 94 00 00 00 00 75 2e 48 8b 40 30 48 83 05 35 06 c8 0b 01 48 85 c0 74 3d 4b
RSP: 0018:ffffc90001a1fba0 EFLAGS: 00010002
RAX: ffff888100d60400 RBX: ffff8881132e7000 RCX: 0000000000000000
RDX: 0000000000000017 RSI: ffff888103580a18 RDI: ffff888103580a18
RBP: ffff8881132e7000 R08: 0000000000000000 R09: ffffc90001a1fe10
R10: 0000000000000a20 R11: 0000000000034320 R12: 0000000000000000
R13: ffff888103580a18 R14: ffff888114447000 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff88881fdc0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000094 CR3: 0000000100cdb000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

Root cause is quite complex:

1) use bfq elevator for the test device.
2) create a cgroup CG
3) config blk throtl in CG

   blkg_conf_prep
    blkg_create

4) create a thread T1 and issue async io in CG:

   bio_init
    bio_associate_blkg
   ...
   submit_bio
    submit_bio_noacct
     blk_throtl_bio -> io is throttled
     // io submit is done

5) switch elevator:

   bfq_exit_queue
    blkcg_deactivate_policy
     list_for_each_entry(blkg, &q->blkg_list, q_node)
      blkg->pd[] = NULL
      // bfq policy is removed

5) thread t1 exist, then remove the cgroup CG:

   blkcg_unpin_online
    blkcg_destroy_blkgs
     blkg_destroy
      list_del_init(&blkg->q_node)
      // blkg is removed from queue list

6) switch elevator back to bfq

 bfq_init_queue
  bfq_create_group_hierarchy
   blkcg_activate_policy
    list_for_each_entry_reverse(blkg, &q->blkg_list)
     // blkg is removed from list, hence bfq policy is still NULL

7) throttled io is dispatched to bfq:

 bfq_insert_requests
  bfq_init_rq
   bfq_bic_update_cgroup
    bfq_bio_bfqg
     bfqg = blkg_to_bfqg(blkg)
     // bfqg is NULL because bfq policy is NULL

The problem is only possible in bfq because only bfq can be deactivated and
activated while queue is online, while others can only be deactivated while
the device is removed.

Fix the problem in bfq by checking if blkg is online before calling
blkg_to_bfqg().

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20221108103434.2853269-1-yukuai1@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-12-02 17:43:01 +01:00
..
partitions block: don't add partitions if GD_SUPPRESS_PART_SCAN is set 2022-09-03 11:29:03 -06:00
Kconfig block: remove "select BLK_RQ_IO_DATA_LEN" from BLK_CGROUP_IOCOST dependency 2022-06-29 08:35:57 -06:00
Kconfig.iosched block: only build the icq tracking code when needed 2021-12-16 10:59:02 -07:00
Makefile blk-cgroup: move blkcg_{get,set}_fc_appid out of line 2022-05-02 14:06:20 -06:00
badblocks.c block/badblocks: Remove redundant assignments 2022-04-23 07:15:26 -06:00
bdev.c block: stop using bdevname in bdev_write_inode 2022-07-14 10:27:56 -06:00
bfq-cgroup.c block, bfq: fix null pointer dereference in bfq_bio_bfqg() 2022-12-02 17:43:01 +01:00
bfq-iosched.c block/bfq: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
bfq-iosched.h block/bfq: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
bfq-wf2q.c block: bfq: Fix kernel-doc headers 2022-06-27 06:29:12 -06:00
bio-integrity.c block: pass struct queue_limits to the bio splitting helpers 2022-08-02 21:08:53 -06:00
bio.c bio: safeguard REQ_ALLOC_CACHE bio put 2022-11-10 18:17:26 +01:00
blk-cgroup-fc-appid.c blk-cgroup: move blkcg_{get,set}_fc_appid out of line 2022-05-02 14:06:20 -06:00
blk-cgroup-rwstat.c blk-cgroup: Fix the recursive blkg rwstat 2021-03-05 11:32:15 -07:00
blk-cgroup-rwstat.h block: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
blk-cgroup.c blk-cgroup: properly pin the parent in blkcg_css_online 2022-11-26 09:27:51 +01:00
blk-cgroup.h blk-cgroup: Use atomic{,64}_try_cmpxchg 2022-07-12 15:46:03 -06:00
blk-core.c block: make dma_alignment a stacking queue_limit 2022-11-26 09:27:40 +01:00
blk-crypto-fallback.c block: remove superfluous calls to blkcg_bio_issue_init 2022-05-04 18:29:52 -06:00
blk-crypto-internal.h blk-crypto: show crypto capabilities in sysfs 2022-02-28 06:40:23 -07:00
blk-crypto-profile.c blk-crypto: remove blk_crypto_unregister() 2021-11-29 06:38:51 -07:00
blk-crypto-sysfs.c blk-crypto: show crypto capabilities in sysfs 2022-02-28 06:40:23 -07:00
blk-crypto.c blk-crypto: show crypto capabilities in sysfs 2022-02-28 06:40:23 -07:00
blk-flush.c block: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
blk-ia-ranges.c block: simplify disk_set_independent_access_ranges 2022-06-29 08:36:46 -06:00
blk-integrity.c blk-crypto: remove blk_crypto_unregister() 2021-11-29 06:38:51 -07:00
blk-ioc.c block: fix default IO priority handling again 2022-06-27 06:29:12 -06:00
blk-iocost.c block: don't allow the same type rq_qos add more than once 2022-07-20 06:44:14 -06:00
blk-iolatency.c block: don't allow the same type rq_qos add more than once 2022-07-20 06:44:14 -06:00
blk-ioprio.c blk-ioprio: Convert from rqos policy to direct call 2022-06-27 06:29:12 -06:00
blk-ioprio.h blk-ioprio: Convert from rqos policy to direct call 2022-06-27 06:29:12 -06:00
blk-lib.c blk-lib: fix blkdev_issue_secure_erase 2022-09-15 00:25:17 -06:00
blk-map.c block: convert to advancing variants of iov_iter_get_pages{,_alloc}() 2022-08-08 22:37:22 -04:00
blk-merge.c block: pass struct queue_limits to the bio splitting helpers 2022-08-02 21:08:53 -06:00
blk-mq-cpumap.c blk-mq: remove the calling of local_memory_node() 2020-10-20 07:08:17 -06:00
blk-mq-debugfs-zoned.c block: move zone related fields to struct gendisk 2022-07-06 06:46:26 -06:00
blk-mq-debugfs.c block: add missing request flags to debugfs code 2022-09-09 05:57:52 -06:00
blk-mq-debugfs.h block: remove per-disk debugfs files in blk_unregister_queue 2022-06-17 07:31:05 -06:00
blk-mq-pci.c
blk-mq-rdma.c
blk-mq-sched.c block: serialize all debugfs operations using q->debugfs_mutex 2022-06-17 07:31:05 -06:00
blk-mq-sched.h block: move blk_mq_sched_assign_ioc to blk-ioc.c 2021-11-29 06:41:29 -07:00
blk-mq-sysfs.c blk-mq: cleanup disk sysfs registration 2022-06-28 11:32:42 -06:00
blk-mq-tag.c blk-mq: Drop local variable for reserved tag 2022-07-06 06:33:53 -06:00
blk-mq-tag.h blk-mq: blk_mq_tag_busy is no need to return a value 2022-06-27 06:29:12 -06:00
blk-mq-virtio.c blk-mq: Fix typo in comment 2020-03-17 20:55:21 +01:00
blk-mq.c block: blk_add_rq_to_plug(): clear stale 'last' after flush 2022-11-26 09:27:19 +01:00
blk-mq.h block: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
blk-pm.c scsi: block: pm: Always set request queue runtime active in blk_post_runtime_resume() 2021-12-22 23:38:29 -05:00
blk-pm.h block: Remove unused blk_pm_*() function definitions 2021-02-22 06:33:48 -07:00
blk-rq-qos.c block/rq_qos: Use atomic_try_cmpxchg in atomic_inc_below 2022-07-12 14:38:52 -06:00
blk-rq-qos.h block: don't allow the same type rq_qos add more than once 2022-07-20 06:44:14 -06:00
blk-settings.c block: make dma_alignment a stacking queue_limit 2022-11-26 09:27:40 +01:00
blk-stat.c block: make queue stat accounting a reference 2021-12-14 17:23:05 -07:00
blk-stat.h block: make queue stat accounting a reference 2021-12-14 17:23:05 -07:00
blk-sysfs.c block: move ->bio_split to the gendisk 2022-08-02 21:08:49 -06:00
blk-throttle.c blk-throttle: prevent overflow while calculating wait time 2022-10-21 12:39:22 +02:00
blk-throttle.h blk-throttle: fix that io throttle can only work for single bio 2022-10-21 12:37:54 +02:00
blk-timeout.c block: blk-timeout: delete duplicated word 2020-07-31 16:29:47 -06:00
blk-wbt.c blk-wbt: fix that 'rwb->wc' is always set to 1 in wbt_init() 2022-10-21 12:39:28 +02:00
blk-wbt.h blk-wbt: remove wbt_track stub 2022-03-31 12:58:38 -06:00
blk-zoned.c treewide: Rename enum req_opf into enum req_op 2022-07-14 12:14:30 -06:00
blk.h blk-mq: use quiesced elevator switch when reinitializing queues 2022-10-21 12:39:25 +02:00
bounce.c block: change the blk_queue_bounce calling convention 2022-08-02 17:22:54 -06:00
bsg-lib.c blk-mq: Drop blk_mq_ops.timeout 'reserved' arg 2022-07-06 06:33:53 -06:00
bsg.c scsi: core: bsg: Remove usage of the deprecated ida_simple_xxx() API 2022-06-21 21:22:51 -04:00
disk-events.c block: remove genhd.h 2022-02-02 07:49:59 -07:00
elevator.c blk-mq: use quiesced elevator switch when reinitializing queues 2022-10-21 12:39:25 +02:00
elevator.h block: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
fops.c new iov_iter flavour - ITER_UBUF 2022-08-08 22:37:15 -04:00
genhd.c block: Fix possible memory leak for rq_wb on add_disk failure 2022-11-10 18:17:29 +01:00
holder.c block: remove WARN_ON() from bd_link_disk_holder 2022-06-23 07:48:05 -06:00
ioctl.c block: replace blkdev_nr_zones with bdev_nr_zones 2022-07-06 06:46:26 -06:00
ioprio.c block: Fix handling of tasks without ioprio in ioprio_get(2) 2022-06-27 06:29:12 -06:00
kyber-iosched.c block/kyber: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
mq-deadline.c block/mq-deadline: Use the new blk_opf_t type 2022-07-14 12:14:30 -06:00
opal_proto.h
sed-opal.c block: sed-opal: kmalloc the cmd/resp buffers 2022-11-26 09:27:29 +01:00
t10-pi.c block: add pi for extended integrity 2022-03-07 12:48:35 -07:00