• G
    ubi: fix slab-out-of-bounds in ubi_eba_get_ldesc+0xfb/0x130 · 9ca291d9
    Guo Xuenan 提交于
    hulk inclusion
    category: bugfix
    bugzilla: 182980 https://gitee.com/openeuler/kernel/issues/I4DDEL
    
    -------------------------------------------------
    
    When using ioctl interface to resize ubi volume, ubi_resize_volume will
    resize eba table first, but not change vol->reserved_pebs in the same
    atomic context which may cause concurrency access eba table.
    
    For example, When user do shrink ubi volume A calling ubi_resize_volume,
    while the other thread is writing (volume B) and triggering wear-leveling,
    which may calling ubi_write_fastmap, under these circumstances, KASAN may
    report: slab-out-of-bounds in ubi_eba_get_ldesc+0xfb/0x130.
    
    The main work of this patch include:
    1. fix races in ubi_resize_volume and ubi_update_fastmap, to avoid
       eba_tbl read out of bounds. first, we make eba_tbl and reserved_pebs
       updating under the protect of vol->volumes_lock. second, rollback
       volume in case of resize failure. Also mention that for volume
       shrinking failure, since part of volume has been shrunk and unmapped,
       there is no need to recover {rsvd/avail}_pebs.
    2. fix some memleak in error path of ubi_resize_volume when destroy
       new_eba_tbl.
    
    BUG: KASAN: slab-out-of-bounds in ubi_eba_get_ldesc+0xfb/0x130 [ubi]
    Read of size 4 at addr ffff888013ff7170 by task kworker/u16:3/160
    CPU: 6 PID: 160 Comm: kworker/u16:3 Not tainted
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
    1.14.0-1.fc33 04/01/2014
    Workqueue: writeback wb_workfn (flush-ubifs_0_0)
    Call Trace:
     dump_stack+0x9c/0xcf
     print_address_description.constprop.0+0x1c/0x220
     kasan_report.cold+0x1f/0x37
     ubi_eba_get_ldesc+0xfb/0x130 [ubi]
     ubi_update_fastmap.cold+0x6be/0xc6b [ubi]
     ubi_wl_get_peb+0x2a2/0x580 [ubi]
     try_write_vid_and_data+0x9a/0x4d0 [ubi]
     ubi_eba_write_leb+0x780/0x1890 [ubi]
     ubi_leb_map+0x197/0x2c0 [ubi]
     ubifs_leb_map+0x139/0x240 [ubifs]
     ubifs_add_bud_to_log+0xb02/0xea0 [ubifs]
     make_reservation+0x860/0xb40 [ubifs]
     ubifs_jnl_write_data+0x461/0x9b0 [ubifs]
     do_writepage+0x375/0x550 [ubifs]
     ubifs_writepage+0x3a4/0x670 [ubifs]
     __writepage+0x61/0x160
     write_cache_pages+0x433/0xb70
     do_writepages+0x1ad/0x260
     __writeback_single_inode+0xb3/0x810
     writeback_sb_inodes+0x4d9/0xcc0
     __writeback_inodes_wb+0xc1/0x260
     wb_writeback+0x585/0x760
     wb_workfn+0x751/0xdb0
     process_one_work+0x6e5/0xf10
     worker_thread+0x5e1/0x10c0
     kthread+0x335/0x400
     ret_from_fork+0x1f/0x30
    
    Allocated by task 690:
     kasan_save_stack+0x1b/0x40
     __kasan_kmalloc.constprop.0+0xc2/0xd0
     ubi_eba_create_table+0x88/0x1a0 [ubi]
     ubi_resize_volume.cold+0x166/0xc75 [ubi]
     ubi_cdev_ioctl+0x57f/0x1aa0 [ubi]
     __x64_sys_ioctl+0x141/0x1a0
     do_syscall_64+0x2d/0x40
     entry_SYSCALL_64_after_hwframe+0x44/0xa9
    
    The following steps can used to reproduce:
    Process 1: write and trigger ubi wear-leveling
        ubimkvol /dev/ubi0 -s 5000MiB -N v1
        ubimkvol /dev/ubi0 -s 2000MiB -N v2
        ubimkvol /dev/ubi0 -s 10MiB -N v3
        mount -t ubifs /dev/ubi0_0 /mnt/ubifs
        while true;
        do
            filename=/mnt/ubifs/$((RANDOM))
            dd if=/dev/random of=${filename} bs=1M count=$((RANDOM % 1000))
            rm -rf ${filename}
            sync /mnt/ubifs/
        done
    
    Process 2: do random resize
        struct ubi_rsvol_req req;
        req.vol_id = 1;
        req.bytes = (rand() % 50) * 512KB;
        ioctl(fd, UBI_IOCRSVOL, &req);
    Reported-by: NHulk Robot <hulkci@huawei.com>
    Signed-off-by: NGuo Xuenan <guoxuenan@huawei.com>
    Reviewed-by: NZhang Xiaoxu <zhangxiaoxu5@huawei.com>
    Reviewed-by: NZhang Yi <yi.zhang@huawei.com>
    Signed-off-by: NChen Jun <chenjun102@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    9ca291d9
vmt.c 21.6 KB