From 09bae0a02343d49e7ee97b78a13a36d84880d250 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 9 Apr 2020 23:22:35 +0000 Subject: [PATCH] libc: Fix possible overflow in binuptime(). This is an application of the kernel overflow fix from r357948 to userspace, based on the algorithm developed by Bruce Evans. To keep the ABI of the vds_timekeep stable, instead of adding the large_delta member, MSB of both multipliers are added to quickly estimate the overflow. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- lib/libc/sys/__vdso_gettimeofday.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/libc/sys/__vdso_gettimeofday.c b/lib/libc/sys/__vdso_gettimeofday.c index 3749e0473af2..32c416a54392 100644 --- a/lib/libc/sys/__vdso_gettimeofday.c +++ b/lib/libc/sys/__vdso_gettimeofday.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include "libc_private.h" @@ -62,7 +63,8 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) { struct vdso_timehands *th; uint32_t curr, gen; - u_int delta; + uint64_t scale, x; + u_int delta, scale_bits; int error; do { @@ -78,7 +80,19 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) continue; if (error != 0) return (error); - bintime_addx(bt, th->th_scale * delta); + scale = th->th_scale; +#ifdef _LP64 + scale_bits = ffsl(scale); +#else + scale_bits = ffsll(scale); +#endif + if (__predict_false(scale_bits + fls(delta) > 63)) { + x = (scale >> 32) * delta; + scale &= 0xffffffff; + bt->sec += x >> 32; + bintime_addx(bt, x << 32); + } + bintime_addx(bt, scale * delta); if (abs) bintime_add(bt, &th->th_boottime);