|
@@ -911,6 +911,7 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|
|
struct timekeeper *tk = &tk_core.timekeeper;
|
|
|
struct timespec64 ts_delta, xt;
|
|
|
unsigned long flags;
|
|
|
+ int ret = 0;
|
|
|
|
|
|
if (!timespec64_valid_strict(ts))
|
|
|
return -EINVAL;
|
|
@@ -924,10 +925,15 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|
|
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
|
|
|
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
|
|
|
|
|
|
+ if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
|
|
|
|
|
|
tk_set_xtime(tk, ts);
|
|
|
-
|
|
|
+out:
|
|
|
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
|
|
|
|
|
|
write_seqcount_end(&tk_core.seq);
|
|
@@ -936,7 +942,7 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|
|
/* signal hrtimers about time change */
|
|
|
clock_was_set();
|
|
|
|
|
|
- return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(do_settimeofday64);
|
|
|
|
|
@@ -965,7 +971,8 @@ int timekeeping_inject_offset(struct timespec *ts)
|
|
|
|
|
|
/* Make sure the proposed value is valid */
|
|
|
tmp = timespec64_add(tk_xtime(tk), ts64);
|
|
|
- if (!timespec64_valid_strict(&tmp)) {
|
|
|
+ if (timespec64_compare(&tk->wall_to_monotonic, &ts64) > 0 ||
|
|
|
+ !timespec64_valid_strict(&tmp)) {
|
|
|
ret = -EINVAL;
|
|
|
goto error;
|
|
|
}
|