diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 4 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 37 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 4 | 
3 files changed, 38 insertions, 7 deletions
| diff --git a/kernel/fork.c b/kernel/fork.c index 3bd2280d79f6..2c8857e12855 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -455,8 +455,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 455 | if (retval) | 455 | if (retval) | 
| 456 | goto out; | 456 | goto out; | 
| 457 | 457 | ||
| 458 | if (file && uprobe_mmap(tmp)) | 458 | if (file) | 
| 459 | goto out; | 459 | uprobe_mmap(tmp); | 
| 460 | } | 460 | } | 
| 461 | /* a new mm has just been created */ | 461 | /* a new mm has just been created */ | 
| 462 | arch_dup_mmap(oldmm, mm); | 462 | arch_dup_mmap(oldmm, mm); | 
| diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index e16af197a2bc..0c1485e42be6 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -115,6 +115,7 @@ static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts) | |||
| 115 | { | 115 | { | 
| 116 | tk->xtime_sec += ts->tv_sec; | 116 | tk->xtime_sec += ts->tv_sec; | 
| 117 | tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift; | 117 | tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift; | 
| 118 | tk_normalize_xtime(tk); | ||
| 118 | } | 119 | } | 
| 119 | 120 | ||
| 120 | static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | 121 | static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | 
| @@ -276,7 +277,7 @@ static void timekeeping_forward_now(struct timekeeper *tk) | |||
| 276 | tk->xtime_nsec += cycle_delta * tk->mult; | 277 | tk->xtime_nsec += cycle_delta * tk->mult; | 
| 277 | 278 | ||
| 278 | /* If arch requires, add in gettimeoffset() */ | 279 | /* If arch requires, add in gettimeoffset() */ | 
| 279 | tk->xtime_nsec += arch_gettimeoffset() << tk->shift; | 280 | tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; | 
| 280 | 281 | ||
| 281 | tk_normalize_xtime(tk); | 282 | tk_normalize_xtime(tk); | 
| 282 | 283 | ||
| @@ -427,7 +428,7 @@ int do_settimeofday(const struct timespec *tv) | |||
| 427 | struct timespec ts_delta, xt; | 428 | struct timespec ts_delta, xt; | 
| 428 | unsigned long flags; | 429 | unsigned long flags; | 
| 429 | 430 | ||
| 430 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 431 | if (!timespec_valid(tv)) | 
| 431 | return -EINVAL; | 432 | return -EINVAL; | 
| 432 | 433 | ||
| 433 | write_seqlock_irqsave(&tk->lock, flags); | 434 | write_seqlock_irqsave(&tk->lock, flags); | 
| @@ -463,6 +464,8 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
| 463 | { | 464 | { | 
| 464 | struct timekeeper *tk = &timekeeper; | 465 | struct timekeeper *tk = &timekeeper; | 
| 465 | unsigned long flags; | 466 | unsigned long flags; | 
| 467 | struct timespec tmp; | ||
| 468 | int ret = 0; | ||
| 466 | 469 | ||
| 467 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) | 470 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) | 
| 468 | return -EINVAL; | 471 | return -EINVAL; | 
| @@ -471,10 +474,17 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
| 471 | 474 | ||
| 472 | timekeeping_forward_now(tk); | 475 | timekeeping_forward_now(tk); | 
| 473 | 476 | ||
| 477 | /* Make sure the proposed value is valid */ | ||
| 478 | tmp = timespec_add(tk_xtime(tk), *ts); | ||
| 479 | if (!timespec_valid(&tmp)) { | ||
| 480 | ret = -EINVAL; | ||
| 481 | goto error; | ||
| 482 | } | ||
| 474 | 483 | ||
| 475 | tk_xtime_add(tk, ts); | 484 | tk_xtime_add(tk, ts); | 
| 476 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); | 485 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); | 
| 477 | 486 | ||
| 487 | error: /* even if we error out, we forwarded the time, so call update */ | ||
| 478 | timekeeping_update(tk, true); | 488 | timekeeping_update(tk, true); | 
| 479 | 489 | ||
| 480 | write_sequnlock_irqrestore(&tk->lock, flags); | 490 | write_sequnlock_irqrestore(&tk->lock, flags); | 
| @@ -482,7 +492,7 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
| 482 | /* signal hrtimers about time change */ | 492 | /* signal hrtimers about time change */ | 
| 483 | clock_was_set(); | 493 | clock_was_set(); | 
| 484 | 494 | ||
| 485 | return 0; | 495 | return ret; | 
| 486 | } | 496 | } | 
| 487 | EXPORT_SYMBOL(timekeeping_inject_offset); | 497 | EXPORT_SYMBOL(timekeeping_inject_offset); | 
| 488 | 498 | ||
| @@ -649,7 +659,20 @@ void __init timekeeping_init(void) | |||
| 649 | struct timespec now, boot, tmp; | 659 | struct timespec now, boot, tmp; | 
| 650 | 660 | ||
| 651 | read_persistent_clock(&now); | 661 | read_persistent_clock(&now); | 
| 662 | if (!timespec_valid(&now)) { | ||
| 663 | pr_warn("WARNING: Persistent clock returned invalid value!\n" | ||
| 664 | " Check your CMOS/BIOS settings.\n"); | ||
| 665 | now.tv_sec = 0; | ||
| 666 | now.tv_nsec = 0; | ||
| 667 | } | ||
| 668 | |||
| 652 | read_boot_clock(&boot); | 669 | read_boot_clock(&boot); | 
| 670 | if (!timespec_valid(&boot)) { | ||
| 671 | pr_warn("WARNING: Boot clock returned invalid value!\n" | ||
| 672 | " Check your CMOS/BIOS settings.\n"); | ||
| 673 | boot.tv_sec = 0; | ||
| 674 | boot.tv_nsec = 0; | ||
| 675 | } | ||
| 653 | 676 | ||
| 654 | seqlock_init(&tk->lock); | 677 | seqlock_init(&tk->lock); | 
| 655 | 678 | ||
| @@ -1129,6 +1152,10 @@ static void update_wall_time(void) | |||
| 1129 | offset = (clock->read(clock) - clock->cycle_last) & clock->mask; | 1152 | offset = (clock->read(clock) - clock->cycle_last) & clock->mask; | 
| 1130 | #endif | 1153 | #endif | 
| 1131 | 1154 | ||
| 1155 | /* Check if there's really nothing to do */ | ||
| 1156 | if (offset < tk->cycle_interval) | ||
| 1157 | goto out; | ||
| 1158 | |||
| 1132 | /* | 1159 | /* | 
| 1133 | * With NO_HZ we may have to accumulate many cycle_intervals | 1160 | * With NO_HZ we may have to accumulate many cycle_intervals | 
| 1134 | * (think "ticks") worth of time at once. To do this efficiently, | 1161 | * (think "ticks") worth of time at once. To do this efficiently, | 
| @@ -1161,9 +1188,9 @@ static void update_wall_time(void) | |||
| 1161 | * the vsyscall implementations are converted to use xtime_nsec | 1188 | * the vsyscall implementations are converted to use xtime_nsec | 
| 1162 | * (shifted nanoseconds), this can be killed. | 1189 | * (shifted nanoseconds), this can be killed. | 
| 1163 | */ | 1190 | */ | 
| 1164 | remainder = tk->xtime_nsec & ((1 << tk->shift) - 1); | 1191 | remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1); | 
| 1165 | tk->xtime_nsec -= remainder; | 1192 | tk->xtime_nsec -= remainder; | 
| 1166 | tk->xtime_nsec += 1 << tk->shift; | 1193 | tk->xtime_nsec += 1ULL << tk->shift; | 
| 1167 | tk->ntp_error += remainder << tk->ntp_error_shift; | 1194 | tk->ntp_error += remainder << tk->ntp_error_shift; | 
| 1168 | 1195 | ||
| 1169 | /* | 1196 | /* | 
| diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 60e4d7875672..6b245f64c8dd 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
| @@ -506,6 +506,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) | |||
| 506 | int size; | 506 | int size; | 
| 507 | 507 | ||
| 508 | syscall_nr = syscall_get_nr(current, regs); | 508 | syscall_nr = syscall_get_nr(current, regs); | 
| 509 | if (syscall_nr < 0) | ||
| 510 | return; | ||
| 509 | if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) | 511 | if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) | 
| 510 | return; | 512 | return; | 
| 511 | 513 | ||
| @@ -580,6 +582,8 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) | |||
| 580 | int size; | 582 | int size; | 
| 581 | 583 | ||
| 582 | syscall_nr = syscall_get_nr(current, regs); | 584 | syscall_nr = syscall_get_nr(current, regs); | 
| 585 | if (syscall_nr < 0) | ||
| 586 | return; | ||
| 583 | if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) | 587 | if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) | 
| 584 | return; | 588 | return; | 
| 585 | 589 | ||
