Commit 20dcda8d40db528865b1aa5053b39e0a803df693
Committed by
Greg Kroah-Hartman
1 parent
ab66a1f3cf
ntp: Fixup adjtimex freq validation on 32-bit systems
commit 29183a70b0b828500816bd794b3fe192fce89f73 upstream. Additional validation of adjtimex freq values to avoid potential multiplication overflows were added in commit 5e5aeb4367b (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: Josh Boyer <jwboyer@fedoraproject.org> Reported-by: George Joseph <george.joseph@fairview5.com> Tested-by: George Joseph <george.joseph@fairview5.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Peter 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: Ingo Molnar <mingo@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 7 additions and 3 deletions Side-by-side Diff
kernel/time/ntp.c
... | ... | @@ -633,10 +633,14 @@ |
633 | 633 | if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) |
634 | 634 | return -EPERM; |
635 | 635 | |
636 | - if (txc->modes & ADJ_FREQUENCY) { | |
637 | - if (LONG_MIN / PPM_SCALE > txc->freq) | |
636 | + /* | |
637 | + * Check for potential multiplication overflows that can | |
638 | + * only happen on 64-bit systems: | |
639 | + */ | |
640 | + if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) { | |
641 | + if (LLONG_MIN / PPM_SCALE > txc->freq) | |
638 | 642 | return -EINVAL; |
639 | - if (LONG_MAX / PPM_SCALE < txc->freq) | |
643 | + if (LLONG_MAX / PPM_SCALE < txc->freq) | |
640 | 644 | return -EINVAL; |
641 | 645 | } |
642 | 646 |