diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2020-07-09 02:17:08 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2020-07-09 02:17:08 +0000 |
commit | 84c22f6ef8e0ca049952c783d1345cf6920ad019 (patch) | |
tree | 0f2cd5f524c5dc38740b88b99432875f89eb5d11 /lib/libc | |
parent | b602b71192993f5c4600a95e26c5569df015d74b (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.2 | 7 |
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 , |