• Xiao Ni's avatar
    md: Move alloc/free acct bioset in to personality · 0c031fd3
    Xiao Ni authored
    bioset acct is only needed for raid0 and raid5. Therefore, md_run only
    allocates it for raid0 and raid5. However, this does not cover
    personality takeover, which may cause uninitialized bioset. For example,
    the following repro steps:
    
      mdadm -CR /dev/md0 -l1 -n2 /dev/loop0 /dev/loop1
      mdadm --wait /dev/md0
      mkfs.xfs /dev/md0
      mdadm /dev/md0 --grow -l5
      mount /dev/md0 /mnt
    
    causes panic like:
    
    [  225.933939] BUG: kernel NULL pointer dereference, address: 0000000000000000
    [  225.934903] #PF: supervisor instruction fetch in kernel mode
    [  225.935639] #PF: error_code(0x0010) - not-present page
    [  225.936361] PGD 0 P4D 0
    [  225.936677] Oops: 0010 [#1] PREEMPT SMP DEBUG_PAGEALLOC KASAN PTI
    [  225.937525] CPU: 27 PID: 1133 Comm: mount Not tainted 5.16.0-rc3+ #706
    [  225.938416] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-2.module_el8.4.0+547+a85d02ba 04/01/2014
    [  225.939922] RIP: 0010:0x0
    [  225.940289] Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6.
    [  225.941196] RSP: 0018:ffff88815897eff0 EFLAGS: 00010246
    [  225.941897] RAX: 0000000000000000 RBX: 0000000000092800 RCX: ffffffff81370a39
    [  225.942813] RDX: dffffc0000000000 RSI: 0000000000000000 RDI: 0000000000092800
    [  225.943772] RBP: 1ffff1102b12fe04 R08: fffffbfff0b43c01 R09: fffffbfff0b43c01
    [  225.944807] R10: ffffffff85a1e007 R11: fffffbfff0b43c00 R12: ffff88810eaaaf58
    [  225.945757] R13: 0000000000000000 R14: ffff88810eaaafb8 R15: ffff88815897f040
    [  225.946709] FS:  00007ff3f2505080(0000) GS:ffff888fb5e00000(0000) knlGS:0000000000000000
    [  225.947814] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    [  225.948556] CR2: ffffffffffffffd6 CR3: 000000015aa5a006 CR4: 0000000000370ee0
    [  225.949537] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    [  225.950455] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    [  225.951414] Call Trace:
    [  225.951787]  <TASK>
    [  225.952120]  mempool_alloc+0xe5/0x250
    [  225.952625]  ? mempool_resize+0x370/0x370
    [  225.953187]  ? rcu_read_lock_sched_held+0xa1/0xd0
    [  225.953862]  ? rcu_read_lock_bh_held+0xb0/0xb0
    [  225.954464]  ? sched_clock_cpu+0x15/0x120
    [  225.955019]  ? find_held_lock+0xac/0xd0
    [  225.955564]  bio_alloc_bioset+0x1ed/0x2a0
    [  225.956080]  ? lock_downgrade+0x3a0/0x3a0
    [  225.956644]  ? bvec_alloc+0xc0/0xc0
    [  225.957135]  bio_clone_fast+0x19/0x80
    [  225.957651]  raid5_make_request+0x1370/0x1b70
    [  225.958286]  ? sched_clock_cpu+0x15/0x120
    [  225.958797]  ? __lock_acquire+0x8b2/0x3510
    [  225.959339]  ? raid5_get_active_stripe+0xce0/0xce0
    [  225.959986]  ? lock_is_held_type+0xd8/0x130
    [  225.960528]  ? rcu_read_lock_sched_held+0xa1/0xd0
    [  225.961135]  ? rcu_read_lock_bh_held+0xb0/0xb0
    [  225.961703]  ? sched_clock_cpu+0x15/0x120
    [  225.962232]  ? lock_release+0x27a/0x6c0
    [  225.962746]  ? do_wait_intr_irq+0x130/0x130
    [  225.963302]  ? lock_downgrade+0x3a0/0x3a0
    [  225.963815]  ? lock_release+0x6c0/0x6c0
    [  225.964348]  md_handle_request+0x342/0x530
    [  225.964888]  ? set_in_sync+0x170/0x170
    [  225.965397]  ? blk_queue_split+0x133/0x150
    [  225.965988]  ? __blk_queue_split+0x8b0/0x8b0
    [  225.966524]  ? submit_bio_checks+0x3b2/0x9d0
    [  225.967069]  md_submit_bio+0x127/0x1c0
    [...]
    
    Fix this by moving alloc/free of acct bioset to pers->run and pers->free.
    
    While we are on this, properly handle md_integrity_register() error in
    raid0_run().
    
    Fixes: daee2024 (md: check level before create and exit io_acct_set)
    Cc: stable@vger.kernel.org
    Acked-by: default avatarGuoqing Jiang <guoqing.jiang@linux.dev>
    Signed-off-by: default avatarXiao Ni <xni@redhat.com>
    Signed-off-by: default avatarSong Liu <song@kernel.org>
    0c031fd3
md.c 260 KB