Commit 06246b44 authored by John Stultz's avatar John Stultz Committed by Luis Henriques

ntp: Fixup adjtimex freq validation on 32-bit systems

commit 29183a70 upstream.

Additional validation of adjtimex freq values to avoid
potential multiplication overflows were added in commit
5e5aeb43 (time: adjtimex: Validate the ADJ_FREQUENCY values)

Unfortunately the patch used LONG_MAX/MIN instead of
LLONG_MAX/MIN, which was fine on 64-bit systems, but being
much smaller on 32-bit systems caused false positives
resulting in most direct frequency adjustments to fail w/
EINVAL.

ntpd only does direct frequency adjustments at startup, so
the issue was not as easily observed there, but other time
sync applications like ptpd and chrony were more effected by
the bug.

See bugs:

  https://bugzilla.kernel.org/show_bug.cgi?id=92481
  https://bugzilla.redhat.com/show_bug.cgi?id=1188074

This patch changes the checks to use LLONG_MAX for
clarity, and additionally the checks are disabled
on 32-bit systems since LLONG_MAX/PPM_SCALE is always
larger then the 32-bit long freq value, so multiplication
overflows aren't possible there.
Reported-by: default avatarJosh Boyer <jwboyer@fedoraproject.org>
Reported-by: default avatarGeorge Joseph <george.joseph@fairview5.com>
Tested-by: default avatarGeorge Joseph <george.joseph@fairview5.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Link: http://lkml.kernel.org/r/1423553436-29747-1-git-send-email-john.stultz@linaro.org
[ Prettified the changelog and the comments a bit. ]
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent e74cd063
...@@ -632,10 +632,14 @@ int ntp_validate_timex(struct timex *txc) ...@@ -632,10 +632,14 @@ int ntp_validate_timex(struct timex *txc)
if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
return -EPERM; return -EPERM;
if (txc->modes & ADJ_FREQUENCY) { /*
if (LONG_MIN / PPM_SCALE > txc->freq) * Check for potential multiplication overflows that can
* only happen on 64-bit systems:
*/
if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) {
if (LLONG_MIN / PPM_SCALE > txc->freq)
return -EINVAL; return -EINVAL;
if (LONG_MAX / PPM_SCALE < txc->freq) if (LLONG_MAX / PPM_SCALE < txc->freq)
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment