aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/ntp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r--kernel/time/ntp.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 149cc8086aea..36f2ca09aa5e 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -16,8 +16,11 @@
16#include <linux/mm.h> 16#include <linux/mm.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/rtc.h> 18#include <linux/rtc.h>
19#include <linux/math64.h>
19 20
20#include "ntp_internal.h" 21#include "ntp_internal.h"
22#include "timekeeping_internal.h"
23
21 24
22/* 25/*
23 * NTP timekeeping variables: 26 * NTP timekeeping variables:
@@ -70,7 +73,7 @@ static long time_esterror = NTP_PHASE_LIMIT;
70static s64 time_freq; 73static s64 time_freq;
71 74
72/* time at last adjustment (secs): */ 75/* time at last adjustment (secs): */
73static long time_reftime; 76static time64_t time_reftime;
74 77
75static long time_adjust; 78static long time_adjust;
76 79
@@ -297,25 +300,27 @@ static void ntp_update_offset(long offset)
297 if (!(time_status & STA_PLL)) 300 if (!(time_status & STA_PLL))
298 return; 301 return;
299 302
300 if (!(time_status & STA_NANO)) 303 if (!(time_status & STA_NANO)) {
304 /* Make sure the multiplication below won't overflow */
305 offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);
301 offset *= NSEC_PER_USEC; 306 offset *= NSEC_PER_USEC;
307 }
302 308
303 /* 309 /*
304 * Scale the phase adjustment and 310 * Scale the phase adjustment and
305 * clamp to the operating range. 311 * clamp to the operating range.
306 */ 312 */
307 offset = min(offset, MAXPHASE); 313 offset = clamp(offset, -MAXPHASE, MAXPHASE);
308 offset = max(offset, -MAXPHASE);
309 314
310 /* 315 /*
311 * Select how the frequency is to be controlled 316 * Select how the frequency is to be controlled
312 * and in which mode (PLL or FLL). 317 * and in which mode (PLL or FLL).
313 */ 318 */
314 secs = get_seconds() - time_reftime; 319 secs = (long)(__ktime_get_real_seconds() - time_reftime);
315 if (unlikely(time_status & STA_FREQHOLD)) 320 if (unlikely(time_status & STA_FREQHOLD))
316 secs = 0; 321 secs = 0;
317 322
318 time_reftime = get_seconds(); 323 time_reftime = __ktime_get_real_seconds();
319 324
320 offset64 = offset; 325 offset64 = offset;
321 freq_adj = ntp_update_offset_fll(offset64, secs); 326 freq_adj = ntp_update_offset_fll(offset64, secs);
@@ -390,10 +395,11 @@ ktime_t ntp_get_next_leap(void)
390 * 395 *
391 * Also handles leap second processing, and returns leap offset 396 * Also handles leap second processing, and returns leap offset
392 */ 397 */
393int second_overflow(unsigned long secs) 398int second_overflow(time64_t secs)
394{ 399{
395 s64 delta; 400 s64 delta;
396 int leap = 0; 401 int leap = 0;
402 s32 rem;
397 403
398 /* 404 /*
399 * Leap second processing. If in leap-insert state at the end of the 405 * Leap second processing. If in leap-insert state at the end of the
@@ -404,19 +410,19 @@ int second_overflow(unsigned long secs)
404 case TIME_OK: 410 case TIME_OK:
405 if (time_status & STA_INS) { 411 if (time_status & STA_INS) {
406 time_state = TIME_INS; 412 time_state = TIME_INS;
407 ntp_next_leap_sec = secs + SECS_PER_DAY - 413 div_s64_rem(secs, SECS_PER_DAY, &rem);
408 (secs % SECS_PER_DAY); 414 ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
409 } else if (time_status & STA_DEL) { 415 } else if (time_status & STA_DEL) {
410 time_state = TIME_DEL; 416 time_state = TIME_DEL;
411 ntp_next_leap_sec = secs + SECS_PER_DAY - 417 div_s64_rem(secs + 1, SECS_PER_DAY, &rem);
412 ((secs+1) % SECS_PER_DAY); 418 ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
413 } 419 }
414 break; 420 break;
415 case TIME_INS: 421 case TIME_INS:
416 if (!(time_status & STA_INS)) { 422 if (!(time_status & STA_INS)) {
417 ntp_next_leap_sec = TIME64_MAX; 423 ntp_next_leap_sec = TIME64_MAX;
418 time_state = TIME_OK; 424 time_state = TIME_OK;
419 } else if (secs % SECS_PER_DAY == 0) { 425 } else if (secs == ntp_next_leap_sec) {
420 leap = -1; 426 leap = -1;
421 time_state = TIME_OOP; 427 time_state = TIME_OOP;
422 printk(KERN_NOTICE 428 printk(KERN_NOTICE
@@ -427,7 +433,7 @@ int second_overflow(unsigned long secs)
427 if (!(time_status & STA_DEL)) { 433 if (!(time_status & STA_DEL)) {
428 ntp_next_leap_sec = TIME64_MAX; 434 ntp_next_leap_sec = TIME64_MAX;
429 time_state = TIME_OK; 435 time_state = TIME_OK;
430 } else if ((secs + 1) % SECS_PER_DAY == 0) { 436 } else if (secs == ntp_next_leap_sec) {
431 leap = 1; 437 leap = 1;
432 ntp_next_leap_sec = TIME64_MAX; 438 ntp_next_leap_sec = TIME64_MAX;
433 time_state = TIME_WAIT; 439 time_state = TIME_WAIT;
@@ -590,7 +596,7 @@ static inline void process_adj_status(struct timex *txc, struct timespec64 *ts)
590 * reference time to current time. 596 * reference time to current time.
591 */ 597 */
592 if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) 598 if (!(time_status & STA_PLL) && (txc->status & STA_PLL))
593 time_reftime = get_seconds(); 599 time_reftime = __ktime_get_real_seconds();
594 600
595 /* only set allowed bits */ 601 /* only set allowed bits */
596 time_status &= STA_RONLY; 602 time_status &= STA_RONLY;
@@ -674,8 +680,14 @@ int ntp_validate_timex(struct timex *txc)
674 return -EINVAL; 680 return -EINVAL;
675 } 681 }
676 682
677 if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) 683 if (txc->modes & ADJ_SETOFFSET) {
678 return -EPERM; 684 /* In order to inject time, you gotta be super-user! */
685 if (!capable(CAP_SYS_TIME))
686 return -EPERM;
687
688 if (!timeval_inject_offset_valid(&txc->time))
689 return -EINVAL;
690 }
679 691
680 /* 692 /*
681 * Check for potential multiplication overflows that can 693 * Check for potential multiplication overflows that can