On Thu, Jul 02, 2020 at 08:27:58PM -0500, Scott Cheloha wrote:

> Hi,
> 
> When we recompute the scaling factor during tc_windup() there is an
> opportunity for arithmetic overflow/underflow when we add the NTP
> adjustment into the scale:
> 
>    649          scale = (u_int64_t)1 << 63;
>    650          scale += \
>    651              ((th->th_adjustment + th->th_counter->tc_freq_adj) / 
> 1024) * 2199;
>    652          scale /= th->th_counter->tc_frequency;
>    653          th->th_scale = scale * 2;
> 
> At lines 650 and 651, you will overflow/underflow if
> th->th_counter->tc_freq_adj is sufficiently positive/negative.
> 
> I don't like the idea of checking for that overflow during
> tc_windup().  We can pick a reasonable adjustment range and check for
> it during adjfreq(2) and that should be good enough.
> 
> My strawman proposal is a range of -500000000 to 500000000 parts per
> billion.  We could push the limits a bit, but half a billion seems
> like a nice round number to me.
> 
> On a perfect clock, this means you can effect a 0.5x slowdown or a
> 1.5x speedup via adjfreq(2), but no slower/faster.
> 
> I don't *think* ntpd(8) would ever reach such extreme adjustments
> through its algorithm.  I don't think this will break anyone's working
> setup.
> 
> (Maybe I'm wrong, though.  otto@?)

Right, ntpd is pretty conversative and won't do big adjustments.

        -Otto

> 
> Just so we're all clear that the math is sound, here's the result at
> the upper limit of the input range.  Note that adjtime(2) is capped at
> 5000PPM in ntp_update_second(), hence its value here.
> 
>       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;
>       /*    += (2168958484480000000) / 1024 * 2199; */
>       /*    += 4657753620480000000; */
> 
> 9223372036854775808 + 4657753620480000000 = 13881125657334775808,
> which less than 18446744073709551616, so we don't have overflow.
> 
> At the negative end of the input range, i.e.
> 
>       int64_t th_adjustment = (-5000 * 1000) << 32;
>       int64_t tc_freq_adj = -500000000LL << 32;
> 
> you have 9223372036854775808 - 4657753620480000000 = 4565618416374775808,
> so no underflow either.
> 
> Thoughts?
> 
> What is the best way to express this range in the documentation?  Do I
> say "parts per billion", or something else?
> 
> Index: sys/kern/kern_time.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_time.c,v
> retrieving revision 1.131
> diff -u -p -r1.131 kern_time.c
> --- sys/kern/kern_time.c      22 Jun 2020 18:25:57 -0000      1.131
> +++ sys/kern/kern_time.c      3 Jul 2020 00:57:49 -0000
> @@ -391,6 +391,9 @@ sys_settimeofday(struct proc *p, void *v
>       return (0);
>  }
>  
> +#define ADJFREQ_MAX (500000000LL << 32)
> +#define ADJFREQ_MIN (-500000000LL << 32)
> +
>  int
>  sys_adjfreq(struct proc *p, void *v, register_t *retval)
>  {
> @@ -408,6 +411,8 @@ sys_adjfreq(struct proc *p, void *v, reg
>                       return (error);
>               if ((error = copyin(freq, &f, sizeof(f))))
>                       return (error);
> +             if (f < ADJFREQ_MIN || f > ADJFREQ_MAX)
> +                     return (EINVAL);
>       }
>  
>       rw_enter(&tc_lock, (freq == NULL) ? RW_READ : RW_WRITE);
> Index: lib/libc/sys/adjfreq.2
> ===================================================================
> RCS file: /cvs/src/lib/libc/sys/adjfreq.2,v
> retrieving revision 1.7
> diff -u -p -r1.7 adjfreq.2
> --- lib/libc/sys/adjfreq.2    10 Sep 2015 17:55:21 -0000      1.7
> +++ lib/libc/sys/adjfreq.2    3 Jul 2020 00:57:49 -0000
> @@ -60,6 +60,10 @@ 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 -500000000 parts-per-billion or greater than 500000000
> +parts-per-billion.
>  .El
>  .Sh SEE ALSO
>  .Xr date 1 ,

Reply via email to