Skip to content
Snippets Groups Projects
  1. Sep 29, 2022
  2. Sep 26, 2022
    • Baokun Li's avatar
      ext4: fix use-after-free in ext4_ext_shift_extents · ae52ee4a
      Baokun Li authored
      hulk inclusion
      category: bugfix
      bugzilla: 187600, https://gitee.com/openeuler/kernel/issues/I5SV2U
      
      
      CVE: NA
      
      --------------------------------
      
      If the starting position of our insert range happens to be in the hole
      between the two ext4_extent_idx, because the lblk of the ext4_extent in
      the previous ext4_extent_idx is always less than the start, which leads
      to the "extent" variable access across the boundary, the following UAF is
      triggered:
      
      ==================================================================
      BUG: KASAN: use-after-free in ext4_ext_shift_extents+0x257/0x790
      Read of size 4 at addr ffff88819807a008 by task fallocate/8010
      CPU: 3 PID: 8010 Comm: fallocate Tainted: G            E     5.10.0+ #492
      Call Trace:
       dump_stack+0x7d/0xa3
       print_address_description.constprop.0+0x1e/0x220
       kasan_report.cold+0x67/0x7f
       ext4_ext_shift_extents+0x257/0x790
       ext4_insert_range+0x5b6/0x700
       ext4_fallocate+0x39e/0x3d0
       vfs_fallocate+0x26f/0x470
       ksys_fallocate+0x3a/0x70
       __x64_sys_fallocate+0x4f/0x60
       do_syscall_64+0x33/0x40
       entry_SYSCALL_64_after_hwframe+0x44/0xa9
      ==================================================================
      
      For right shifts, we can divide them into the following situations:
      
      1. When the first ee_block of ext4_extent_idx is greater than or equal to
         start, make right shifts directly from the first ee_block.
          1) If it is greater than start, we need to continue searching in the
             previous ext4_extent_idx.
          2) If it is equal to start, we can exit the loop (iterator=NULL).
      
      2. When the first ee_block of ext4_extent_idx is less than start, then
         traverse from the last extent to find the first extent whose ee_block
         is less than start.
          1) If extent is still the last extent after traversal, it means that
             the last ee_block of ext4_extent_idx is less than start, that is,
             start is located in the hole between idx and (idx+1), so we can
             exit the loop directly (break) without right shifts.
          2) Otherwise, make right shifts at the corresponding position of the
             found extent, and then exit the loop (iterator=NULL).
      
      Fixes: 331573fe ("ext4: Add support FALLOC_FL_INSERT_RANGE for fallocate")
      Cc: stable@vger.kernel.org
      Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      ae52ee4a
    • Zhihao Cheng's avatar
      quota: Add more checking after reading from quota file · f66997d9
      Zhihao Cheng authored
      hulk inclusion
      category: bugfix
      bugzilla: 187046, https://gitee.com/openeuler/kernel/issues/I5QH0X
      
      
      CVE: NA
      
      --------------------------------
      
      It would be better to do more sanity checking (eg. dqdh_entries,
      block no.) for the content read from quota file, which can prevent
      corrupting the quota file.
      
      Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
      Reviewed-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      f66997d9
    • Zhihao Cheng's avatar
      quota: Replace all block number checking with helper function · 1e9a49cf
      Zhihao Cheng authored
      hulk inclusion
      category: bugfix
      bugzilla: 187046, https://gitee.com/openeuler/kernel/issues/I5QH0X
      
      
      CVE: NA
      
      --------------------------------
      
      Cleanup all block checking places, replace them with helper function
      do_check_range().
      
      Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
      Reviewed-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Reviewed-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      1e9a49cf
    • Zhihao Cheng's avatar
      quota: Check next/prev free block number after reading from quota file · 6c27d754
      Zhihao Cheng authored
      hulk inclusion
      category: bugfix
      bugzilla: 187046, https://gitee.com/openeuler/kernel/issues/I5QH0X
      CVE: NA
      
      --------------------------------
      
      Following process:
       Init: v2_read_file_info: <3> dqi_free_blk 0 dqi_free_entry 5 dqi_blks 6
      
       Step 1. chown bin f_a -> dquot_acquire -> v2_write_dquot:
        qtree_write_dquot
         do_insert_tree
          find_free_dqentry
           get_free_dqblk
            write_blk(info->dqi_blocks) // info->dqi_blocks = 6, failure. The
      	   content in physical block (corresponding to blk 6) is random.
      
       Step 2. chown root f_a -> dquot_transfer -> dqput_all -> dqput ->
               ext4_release_dquot -> v2_release_dquot -> qtree_delete_dquot:
        dquot_release
         remove_tree
          free_dqentry
           put_free_dqblk(6)
            info->dqi_free_blk = blk    // info->dqi_free_blk = 6
      
       Step 3. drop cache (buffer head for block 6 is released)
      
       Step 4. chown bin f_b -> dquot_acquire -> commit_dqblk -> v2_write_dquot:
        qtree_write_dquot
         do_insert_tree
          find_free_dqentry
           get_free_dqblk
            dh = (struct qt_disk_dqdbheader *)buf
            blk = info->dqi_free_blk     // 6
            ret = read_blk(info, blk, buf)  // The content of buf is random
            info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free)  // random blk
      
       Step 5. chown bin f_c -> notify_change -> ext4_setattr -> dquot_transfer:
        dquot = dqget -> acquire_dquot -> ext4_acquire_dquot -> dquot_acquire ->
                commit_dqblk -> v2_write_dquot -> dq_insert_tree:
         do_insert_tree
          find_free_dqentry
           get_free_dqblk
            blk = info->dqi_free_blk    // If blk < 0 and blk is not an error
      				     code, it will be returned as dquot
      
        transfer_to[USRQUOTA] = dquot  // A random negative value
        __dquot_transfer(transfer_to)
         dquot_add_inodes(transfer_to[cnt])
          spin_lock(&dquot->dq_dqb_lock)  // page fault
      
      , which will lead to kernel page fault:
       Quota error (device sda): qtree_write_dquot: Error -8000 occurred
       while creating quota
       BUG: unable to handle page fault for address: ffffffffffffe120
       #PF: supervisor write access in kernel mode
       #PF: error_code(0x0002) - not-present page
       Oops: 0002 [#1] PREEMPT SMP
       CPU: 0 PID: 5974 Comm: chown Not tainted 6.0.0-rc1-00004
       Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
       RIP: 0010:_raw_spin_lock+0x3a/0x90
       Call Trace:
        dquot_add_inodes+0x28/0x270
        __dquot_transfer+0x377/0x840
        dquot_transfer+0xde/0x540
        ext4_setattr+0x405/0x14d0
        notify_change+0x68e/0x9f0
        chown_common+0x300/0x430
        __x64_sys_fchownat+0x29/0x40
      
      In order to avoid accessing invalid quota memory address, this patch adds
      block number checking of next/prev free block read from quota file.
      
      Fetch a reproducer in [Link].
      
      Link: https://bugzilla.kernel.org/show_bug.cgi?id=216372
      
      
      Fixes: 1da177e4 ("Linux-2.6.12-rc2")
      Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
      Reviewed-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      6c27d754
  3. Sep 20, 2022
  4. Sep 07, 2022
  5. Sep 06, 2022
  6. Aug 27, 2022
    • Pavel Shilovsky's avatar
      CIFS: Fix retry mid list corruption on reconnects · 28b546c6
      Pavel Shilovsky authored
      mainline inclusion
      from mainline-v5.4-rc5
      commit abe57073
      category: bugfix
      bugzilla: 24367, https://gitee.com/openeuler/kernel/issues/I5OE1W
      
      
      CVE: NA
      
      --------------------------------
      
      When the client hits reconnect it iterates over the mid
      pending queue marking entries for retry and moving them
      to a temporary list to issue callbacks later without holding
      GlobalMid_Lock. In the same time there is no guarantee that
      mids can't be removed from the temporary list or even
      freed completely by another thread. It may cause a temporary
      list corruption:
      
      [  430.454897] list_del corruption. prev->next should be ffff98d3a8f316c0, but was 2e885cb266355469
      [  430.464668] ------------[ cut here ]------------
      [  430.466569] kernel BUG at lib/list_debug.c:51!
      [  430.468476] invalid opcode: 0000 [#1] SMP PTI
      [  430.470286] CPU: 0 PID: 13267 Comm: cifsd Kdump: loaded Not tainted 5.4.0-rc3+ #19
      [  430.473472] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
      [  430.475872] RIP: 0010:__list_del_entry_valid.cold+0x31/0x55
      ...
      [  430.510426] Call Trace:
      [  430.511500]  cifs_reconnect+0x25e/0x610 [cifs]
      [  430.513350]  cifs_readv_from_socket+0x220/0x250 [cifs]
      [  430.515464]  cifs_read_from_socket+0x4a/0x70 [cifs]
      [  430.517452]  ? try_to_wake_up+0x212/0x650
      [  430.519122]  ? cifs_small_buf_get+0x16/0x30 [cifs]
      [  430.521086]  ? allocate_buffers+0x66/0x120 [cifs]
      [  430.523019]  cifs_demultiplex_thread+0xdc/0xc30 [cifs]
      [  430.525116]  kthread+0xfb/0x130
      [  430.526421]  ? cifs_handle_standard+0x190/0x190 [cifs]
      [  430.528514]  ? kthread_park+0x90/0x90
      [  430.530019]  ret_from_fork+0x35/0x40
      
      Fix this by obtaining extra references for mids being retried
      and marking them as MID_DELETED which indicates that such a mid
      has been dequeued from the pending list.
      
      Also move mid cleanup logic from DeleteMidQEntry to
      _cifs_mid_q_entry_release which is called when the last reference
      to a particular mid is put. This allows to avoid any use-after-free
      of response buffers.
      
      The patch needs to be backported to stable kernels. A stable tag
      is not mentioned below because the patch doesn't apply cleanly
      to any actively maintained stable kernel.
      
      Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
      Reviewed-and-tested-by: default avatarDavid Wysochanski <dwysocha@redhat.com>
      Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
      Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
      
      conflicts:
      	fs/cifs/connect.c
      	fs/cifs/transport.c
      
      Signed-off-by: default avatarChenXiaoSong <chenxiaosong2@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      28b546c6
  7. Aug 08, 2022
  8. Aug 05, 2022
  9. Aug 04, 2022
    • Zhihao Cheng's avatar
      io-wq: Switch io_wqe_worker's fs before releasing request · b56e6431
      Zhihao Cheng authored
      hulk inclusion
      category: bugfix
      bugzilla: 187369, https://gitee.com/openeuler/kernel/issues/I5K66O
      
      
      CVE: NA
      
      --------------------------------
      
      Following process triggers an use-after-free problem while iterating
      every process's fs:
      
      main
         fd = setup_iouring
         fork => main'                      // task->fs->users = 1
         submit(fd, STATX, async)
           id->fs = current->fs
           req->work.identity = id
          io_submit_sqes
           ...
            io_grab_identity
             id = req->work.identity
             id->fs->users++               // fs->users = 2
      
      io_wqe_worker
          current->fs = work->identity->fs
          io_req_clean_work
            fs = req->work.identity->fs
            --fs->users                    // fs->user = 1
      
      main' exit
          exit_fs
           --fs->users                     // fs->user = 0
           free_fs_struct(fs)              // FREE fs
      
      pivot_root
      chroot_fs_refs
       do_each_thread(g, p) {
        fs = p->fs                // io_wqe_worker->fs
        if (fs)
          spin_lock(&fs->lock)    // UAF!
       }
      
      io_wqe_worker
          io_worker_exit
           __io_worker_unuse
            if (current->fs != worker->restore_fs)
              current->fs = worker->restore_fs
      
      Task's fs_struct is used in do_work() and destroyed in free_work(),
      this problem can be fixed by switching io_wqe_worker's fs before
      releasing request.
      
      Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      b56e6431
  10. Jul 28, 2022
  11. Jul 25, 2022
  12. Jul 22, 2022
  13. Jul 20, 2022
    • Baokun Li's avatar
      ext4: fix race condition between ext4_ioctl_setflags and ext4_fiemap · b8493652
      Baokun Li authored
      hulk inclusion
      category: bugfix
      bugzilla: 187222, https://gitee.com/openeuler/kernel/issues/I5H3KE
      
      
      CVE: NA
      
      --------------------------------
      
      Hulk Robot reported a BUG:
      
      ==================================================================
      kernel BUG at fs/ext4/extents_status.c:762!
      invalid opcode: 0000 [#1] SMP KASAN PTI
      [...]
      Call Trace:
       ext4_cache_extents+0x238/0x2f0
       ext4_find_extent+0x785/0xa40
       ext4_fiemap+0x36d/0xe90
       do_vfs_ioctl+0x6af/0x1200
      [...]
      ==================================================================
      
      Above issue may happen as follows:
      -------------------------------------
                 cpu1		    cpu2
      _____________________|_____________________
      do_vfs_ioctl
       ext4_ioctl
        ext4_ioctl_setflags
         ext4_ind_migrate
                              do_vfs_ioctl
                               ioctl_fiemap
                                ext4_fiemap
                                 ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)
                                 ext4_fill_fiemap_extents
          down_write(&EXT4_I(inode)->i_data_sem);
          ext4_ext_check_inode
          ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS)
          memset(ei->i_data, 0, sizeof(ei->i_data))
          up_write(&EXT4_I(inode)->i_data_sem);
                                  down_read(&EXT4_I(inode)->i_data_sem);
                                  ext4_find_extent
                                   ext4_cache_extents
                                    ext4_es_cache_extent
                                     BUG_ON(end < lblk)
      
      We can easily reproduce this problem with the syzkaller testcase:
      ```
      02:37:07 executing program 3:
      r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x26e1, 0x0)
      ioctl$FS_IOC_FSSETXATTR(r0, 0x40086602, &(0x7f0000000080)={0x17e})
      mkdirat(0xffffffffffffff9c, &(0x7f00000000c0)='./file1\x00', 0x1ff)
      r1 = openat(0xffffffffffffff9c, &(0x7f0000000100)='./file1\x00', 0x0, 0x0)
      ioctl$FS_IOC_FIEMAP(r1, 0xc020660b, &(0x7f0000000180)={0x0, 0x1, 0x0, 0xef3, 0x6, []}) (async, rerun: 32)
      ioctl$FS_IOC_FSSETXATTR(r1, 0x40086602, &(0x7f0000000140)={0x17e}) (rerun: 32)
      ```
      
      To solve this issue, we use __generic_block_fiemap() instead of
      generic_block_fiemap() and add inode_lock_shared to avoid race condition.
      
      Reported-by: default avatarHulk Robot <hulkci@huawei.com>
      Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
      Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      b8493652
  14. Jul 14, 2022
    • 余快's avatar
      Revert "block: rename bd_invalidated" · 13879644
      余快 authored
      hulk inclusion
      category: bugfix
      bugzilla: 187190, https://gitee.com/src-openeuler/kernel/issues/I5GWOV
      
      
      CVE: NA
      
      --------------------------------
      
      This reverts commit b6113052.
      
      Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
      Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      13879644
    • 余快's avatar
      Revert "block: move the NEED_PART_SCAN flag to struct gendisk" · acc38712
      余快 authored
      hulk inclusion
      category: bugfix
      bugzilla: 187190, https://gitee.com/src-openeuler/kernel/issues/I5GWOV
      
      
      CVE: NA
      
      --------------------------------
      
      This reverts commit b2f0e44f.
      
      Because it will introduce following problem in ltp zram tests:
      
      BUG: unable to handle kernel NULL pointer dereference at 0000000000000600
      PGD 0 P4D 0
      Oops: 0002 [#1] SMP PTI
      CPU: 28 PID: 172121 Comm: sh Kdump: loaded Tainted: G           OE    --------- -  - 4.18.0+ #2
      Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 5.15 05/21/2019
      RIP: 0010:flush_disk+0x1d/0x50
      RSP: 0018:ffffaf14a516fe20 EFLAGS: 00010246
      RAX: 0000000000000000 RBX: ffff899e26bac380 RCX: 0000000000000000
      RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff899e26bac380
      RBP: ffff899e26bac380 R08: 00000000000006a9 R09: 0000000000000004
      R10: ffff89cd878ff440 R11: 0000000000000001 R12: 0000000000000000
      R13: ffff899e26bac398 R14: ffffaf14a516ff00 R15: ffff89cd8709c3e0
      FS:  00007f78d6840740(0000) GS:ffff89fcbf480000(0000) knlGS:0000000000000000
      CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: 0000000000000600 CR3: 000000308afc0002 CR4: 00000000001606e0
      Call Trace:
       revalidate_disk+0x57/0x80
       reset_store+0xaf/0x120 [zram]
       kernfs_fop_write+0x10f/0x190
       vfs_write+0xad/0x1a0
       ksys_write+0x52/0xc0
       do_syscall_64+0x5d/0x1d0
       entry_SYSCALL_64_after_hwframe+0x65/0xca
      
      This is because "bdev->bd_disk" is not ensured to exist, just convert
      "set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags)" to
      "set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state)" is wrong.
      
      The reason to backport it is that commit 2a57456c8973 ("block:
      Fix warning in bd_link_disk_holder()") has a regression that part scan
      is disabled in device_add_disk(), and this problem will be fixed in
      later patch.
      
      Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
      Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
      Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
      acc38712
  15. Jul 08, 2022