summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2020-07-09 02:17:08 +0000
committercheloha <cheloha@cvs.openbsd.org>2020-07-09 02:17:08 +0000
commit84c22f6ef8e0ca049952c783d1345cf6920ad019 (patch)
tree0f2cd5f524c5dc38740b88b99432875f89eb5d11 /lib/libc
parentb602b71192993f5c4600a95e26c5569df015d74b (diff)
adjfreq(2): limit adjustment to [-500000, +500000] ppm
When we recompute the scaling factor during tc_windup() there is an opportunity for arithmetic overflow if the active timecounter's adjfreq(2) adjustment is too large. If we limit the adjustment to [-500000, +500000] ppm the statement in question cannot overflow. In particular, we are concerned with the following bit of code: scale = (u_int64_t)1 << 63; scale += \ ((th->th_adjustment + th->th_counter->tc_freq_adj) / 1024) * 2199; scale /= th->th_counter->tc_frequency; th->th_scale = scale * 2; where scale is an int64_t. Overflow when we do: scale += (...) / 1024 * 2199; as th->th_counter->tc_freq_adj is currently unbounded. th->th_adjustment is limited to [-5000ppm, 5000ppm]. To see that overflow is prevented with the new bounds, consider the new edge case where th->th_counter->tc_freq_adj is 500000ppm and th->th_adjustment is 5000ppm. Both are of type int64_t. We have: int64_t th_adjustment = (5000 * 1000) << 32; /* 21474836480000000 */ int64_t tc_freq_adj = 500000000LL << 32; /* 2147483648000000000 */ scale = (u_int64_t)1 << 63; /* 9223372036854775808 */ scale += (th_adjustment + tc_freq_adj) / 1024 * 2199; /* scale += 2168958484480000000 / 1024 * 2199; */ /* scale += 4657753620480000000; */ 9223372036854775808 + 4657753620480000000 = 13881125657334775808, which less than 18446744073709551616, so we don't have overflow. On the opposite end, if th->th_counter->tc_freq_adj is -500000ppm and th->th_adjustment is -5000ppm we would have -4657753620480000000. 9223372036854775808 - 4657753620480000000 = 4565618416374775808. Again, no overflow. 500000ppm and -500000ppm are extreme adjustments. otto@ says ntpd(8) would never arrive at them naturally, so we are not at risk of breaking a working setup by imposing these restrictions. Documentation input from kettenis@. No complaints from otto@.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/sys/adjfreq.27
1 files changed, 5 insertions, 2 deletions
diff --git a/lib/libc/sys/adjfreq.2 b/lib/libc/sys/adjfreq.2
index 8bc38a8e5c5..183e65c6f08 100644
--- a/lib/libc/sys/adjfreq.2
+++ b/lib/libc/sys/adjfreq.2
@@ -1,4 +1,4 @@
-.\" $OpenBSD: adjfreq.2,v 1.7 2015/09/10 17:55:21 schwarze Exp $
+.\" $OpenBSD: adjfreq.2,v 1.8 2020/07/09 02:17:07 cheloha Exp $
.\"
.\" Copyright (c) 2006 Otto Moerbeek
.\"
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: September 10 2015 $
+.Dd $Mdocdate: July 9 2020 $
.Dt ADJFREQ 2
.Os
.Sh NAME
@@ -60,6 +60,9 @@ The
.Fa freq
argument is non-null and the process's effective user ID is not that
of the superuser.
+.It Bq Er EINVAL
+.Fa freq
+is less than -500000 ppm or greater than 500000 ppm.
.El
.Sh SEE ALSO
.Xr date 1 ,