diff options
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r-- | kernel/time/ntp.c | 44 |
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; | |||
70 | static s64 time_freq; | 73 | static s64 time_freq; |
71 | 74 | ||
72 | /* time at last adjustment (secs): */ | 75 | /* time at last adjustment (secs): */ |
73 | static long time_reftime; | 76 | static time64_t time_reftime; |
74 | 77 | ||
75 | static long time_adjust; | 78 | static 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 | */ |
393 | int second_overflow(unsigned long secs) | 398 | int 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 |