linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] hpet: Fix division by zero in hpet_time_div()
@ 2019-07-11 11:26 Kefeng Wang
  2019-07-11 12:32 ` Arnd Bergmann
  0 siblings, 1 reply; 3+ messages in thread
From: Kefeng Wang @ 2019-07-11 11:26 UTC (permalink / raw)
  To: Clemens Ladisch, Arnd Bergmann, Greg Kroah-Hartman, linux-kernel
  Cc: wangkefeng.wang

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: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Zhang HongJun <zhanghongjun2@huawei.com>
---
 drivers/char/hpet.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5c39f20378b8..dd52b63b62db 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -567,7 +567,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
 	unsigned long long m;
 
 	m = hpets->hp_tick_freq + (dis >> 1);
-	do_div(m, dis);
+	div64_ul(m, dis);
 	return (unsigned long)m;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] hpet: Fix division by zero in hpet_time_div()
  2019-07-11 11:26 [PATCH] hpet: Fix division by zero in hpet_time_div() Kefeng Wang
@ 2019-07-11 12:32 ` Arnd Bergmann
  2019-07-11 13:21   ` Kefeng Wang
  0 siblings, 1 reply; 3+ messages in thread
From: Arnd Bergmann @ 2019-07-11 12:32 UTC (permalink / raw)
  To: Kefeng Wang
  Cc: Clemens Ladisch, Greg Kroah-Hartman, Linux Kernel Mailing List

On Thu, Jul 11, 2019 at 1:20 PM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
> 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.

Good catch!

> --- a/drivers/char/hpet.c
> +++ b/drivers/char/hpet.c
> @@ -567,7 +567,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
>         unsigned long long m;
>
>         m = hpets->hp_tick_freq + (dis >> 1);
> -       do_div(m, dis);
> +       div64_ul(m, dis);
>         return (unsigned long)m;
>  }

This still looks wrong to me: div64_ul() unlike do_div() does not
modify its argument, so you have to assign the output like

       return div64_ul(m, dis);

       Arnd

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hpet: Fix division by zero in hpet_time_div()
  2019-07-11 12:32 ` Arnd Bergmann
@ 2019-07-11 13:21   ` Kefeng Wang
  0 siblings, 0 replies; 3+ messages in thread
From: Kefeng Wang @ 2019-07-11 13:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Clemens Ladisch, Greg Kroah-Hartman, Linux Kernel Mailing List



On 2019/7/11 20:32, Arnd Bergmann wrote:
> On Thu, Jul 11, 2019 at 1:20 PM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>> 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.
> 
> Good catch!
> 
>> --- a/drivers/char/hpet.c
>> +++ b/drivers/char/hpet.c
>> @@ -567,7 +567,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
>>         unsigned long long m;
>>
>>         m = hpets->hp_tick_freq + (dis >> 1);
>> -       do_div(m, dis);
>> +       div64_ul(m, dis);
>>         return (unsigned long)m;
>>  }
> 
> This still looks wrong to me: div64_ul() unlike do_div() does not
> modify its argument, so you have to assign the output like
> 
>        return div64_ul(m, dis);

right, should check div64_ul more carefully, will resend v2, thanks

> 
>        Arnd
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-07-11 13:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-11 11:26 [PATCH] hpet: Fix division by zero in hpet_time_div() Kefeng Wang
2019-07-11 12:32 ` Arnd Bergmann
2019-07-11 13:21   ` Kefeng Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).