Skip to content
  • Kefeng Wang's avatar
    hpet: Fix division by zero in hpet_time_div() · 0c7d37f4
    Kefeng Wang authored
    
    
    The base value in do_div() called by hpet_time_div() is truncated from
    unsigned long to uint32_t, resulting in a divide-by-zero exception.
    
    UBSAN: Undefined behaviour in ../drivers/char/hpet.c:572:2
    division by zero
    CPU: 1 PID: 23682 Comm: syz-executor.3 Not tainted 4.4.184.x86_64+ #4
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
     0000000000000000 b573382df1853d00 ffff8800a3287b98 ffffffff81ad7561
     ffff8800a3287c00 ffffffff838b35b0 ffffffff838b3860 ffff8800a3287c20
     0000000000000000 ffff8800a3287bb0 ffffffff81b8f25e ffffffff838b35a0
    Call Trace:
     [<ffffffff81ad7561>] __dump_stack lib/dump_stack.c:15 [inline]
     [<ffffffff81ad7561>] dump_stack+0xc1/0x120 lib/dump_stack.c:51
     [<ffffffff81b8f25e>] ubsan_epilogue+0x12/0x8d lib/ubsan.c:166
     [<ffffffff81b900cb>] __ubsan_handle_divrem_overflow+0x282/0x2c8 lib/ubsan.c:262
     [<ffffffff823560dd>] hpet_time_div drivers/char/hpet.c:572 [inline]
     [<ffffffff823560dd>] hpet_ioctl_common drivers/char/hpet.c:663 [inline]
     [<ffffffff823560dd>] hpet_ioctl_common.cold+0xa8/0xad drivers/char/hpet.c:577
     [<ffffffff81e63d56>] hpet_ioctl+0xc6/0x180 drivers/char/hpet.c:676
     [<ffffffff81711590>] vfs_ioctl fs/ioctl.c:43 [inline]
     [<ffffffff81711590>] file_ioctl fs/ioctl.c:470 [inline]
     [<ffffffff81711590>] do_vfs_ioctl+0x6e0/0xf70 fs/ioctl.c:605
     [<ffffffff81711eb4>] SYSC_ioctl fs/ioctl.c:622 [inline]
     [<ffffffff81711eb4>] SyS_ioctl+0x94/0xc0 fs/ioctl.c:613
     [<ffffffff82846003>] tracesys_phase2+0x90/0x95
    
    The main C reproducer autogenerated by syzkaller,
    
      syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
      memcpy((void*)0x20000100, "/dev/hpet\000", 10);
      syscall(__NR_openat, 0xffffffffffffff9c, 0x20000100, 0, 0);
      syscall(__NR_ioctl, r[0], 0x40086806, 0x40000000000000);
    
    Fix it by using div64_ul().
    
    Signed-off-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
    Signed-off-by: default avatarZhang HongJun <zhanghongjun2@huawei.com>
    Cc: stable <stable@vger.kernel.org>
    Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
    Link: https://lore.kernel.org/r/20190711132757.130092-1-wangkefeng.wang@huawei.com
    
    
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    0c7d37f4