svn commit: r359758 - head/lib/libc/sys

Konstantin Belousov kib at FreeBSD.org
Thu Apr 9 23:22:36 UTC 2020


Author: kib
Date: Thu Apr  9 23:22:35 2020
New Revision: 359758
URL: https://svnweb.freebsd.org/changeset/base/359758

Log:
  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

Modified:
  head/lib/libc/sys/__vdso_gettimeofday.c

Modified: head/lib/libc/sys/__vdso_gettimeofday.c
==============================================================================
--- head/lib/libc/sys/__vdso_gettimeofday.c	Thu Apr  9 23:11:19 2020	(r359757)
+++ head/lib/libc/sys/__vdso_gettimeofday.c	Thu Apr  9 23:22:35 2020	(r359758)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/time.h>
 #include <sys/vdso.h>
 #include <errno.h>
+#include <strings.h>
 #include <time.h>
 #include <machine/atomic.h>
 #include "libc_private.h"
@@ -62,7 +63,8 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk
 {
 	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
 			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);
 


More information about the svn-src-head mailing list