• Baokun Li's avatar
    ext4: fix uninitialized ratelimit_state->lock access in __ext4_fill_super() · b4b4fda3
    Baokun Li authored
    In the following concurrency we will access the uninitialized rs->lock:
    
    ext4_fill_super
      ext4_register_sysfs
       // sysfs registered msg_ratelimit_interval_ms
                                 // Other processes modify rs->interval to
                                 // non-zero via msg_ratelimit_interval_ms
      ext4_orphan_cleanup
        ext4_msg(sb, KERN_INFO, "Errors on filesystem, "
          __ext4_msg
            ___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state)
              if (!rs->interval)  // do nothing if interval is 0
                return 1;
              raw_spin_trylock_irqsave(&rs->lock, flags)
                raw_spin_trylock(lock)
                  _raw_spin_trylock
                    __raw_spin_trylock
                      spin_acquire(&lock->dep_map, 0, 1, _RET_IP_)
                        lock_acquire
                          __lock_acquire
                            register_lock_class
                              assign_lock_key
                                dump_stack();
      ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
        raw_spin_lock_init(&rs->lock);
        // init rs->lock here
    
    and get the following dump_stack:
    
    =========================================================
    INFO: trying to register non-static key.
    The code is fine but needs lockdep annotation, or maybe
    you didn't initialize this object before use?
    turning off the locking correctness validator.
    CPU: 12 PID: 753 Comm: mount Tainted: G E 6.7.0-rc6-next-20231222 #504
    [...]
    Call Trace:
     dump_stack_lvl+0xc5/0x170
     dump_stack+0x18/0x30
     register_lock_class+0x740/0x7c0
     __lock_acquire+0x69/0x13a0
     lock_acquire+0x120/0x450
     _raw_spin_trylock+0x98/0xd0
     ___ratelimit+0xf6/0x220
     __ext4_msg+0x7f/0x160 [ext4]
     ext4_orphan_cleanup+0x665/0x740 [ext4]
     __ext4_fill_super+0x21ea/0x2b10 [ext4]
     ext4_fill_super+0x14d/0x360 [ext4]
    [...]
    =========================================================
    
    Normally interval is 0 until s_msg_ratelimit_state is initialized, so
    ___ratelimit() does nothing. But registering sysfs precedes initializing
    rs->lock, so it is possible to change rs->interval to a non-zero value
    via the msg_ratelimit_interval_ms interface of sysfs while rs->lock is
    uninitialized, and then a call to ext4_msg triggers the problem by
    accessing an uninitialized rs->lock. Therefore register sysfs after all
    initializations are complete to avoid such problems.
    Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
    Reviewed-by: default avatarJan Kara <jack@suse.cz>
    Link: https://lore.kernel.org/r/20240102133730.1098120-1-libaokun1@huawei.comSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    b4b4fda3
super.c 206 KB