local: check offset sanity before accumulation
Don't accept an offset that points to time before 1970 or outside the interval to which is mapped NTP time.
This commit is contained in:
parent
183a648d01
commit
aec97397e8
8 changed files with 77 additions and 13 deletions
5
cmdmon.c
5
cmdmon.c
|
@ -1555,8 +1555,11 @@ handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||
static void
|
||||
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
LCL_MakeStep();
|
||||
if (!LCL_MakeStep()) {
|
||||
tx_message->status = htons(STT_FAILED);
|
||||
} else {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
32
local.c
32
local.c
|
@ -416,6 +416,19 @@ clamp_freq(double freq)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
check_offset(struct timeval *now, double offset)
|
||||
{
|
||||
/* Check if the time will be still sane with accumulated offset */
|
||||
if (UTI_IsTimeOffsetSane(now, -offset))
|
||||
return 1;
|
||||
|
||||
LOG(LOGS_WARN, LOGF_Local, "Adjustment of %.1f seconds is invalid", -offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* This involves both setting the absolute frequency with the
|
||||
system-specific driver, as well as calling all notify handlers */
|
||||
|
||||
|
@ -490,6 +503,9 @@ LCL_AccumulateOffset(double offset, double corr_rate)
|
|||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&cooked, offset))
|
||||
return;
|
||||
|
||||
(*drv_accrue_offset)(offset, corr_rate);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
|
@ -498,7 +514,7 @@ LCL_AccumulateOffset(double offset, double corr_rate)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
int
|
||||
LCL_ApplyStepOffset(double offset)
|
||||
{
|
||||
struct timeval raw, cooked;
|
||||
|
@ -509,6 +525,9 @@ LCL_ApplyStepOffset(double offset)
|
|||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&raw, offset))
|
||||
return 0;
|
||||
|
||||
(*drv_apply_step_offset)(offset);
|
||||
|
||||
/* Reset smoothing on all clock steps */
|
||||
|
@ -516,6 +535,8 @@ LCL_ApplyStepOffset(double offset)
|
|||
|
||||
/* Dispatch to all handlers */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -557,6 +578,9 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
|||
to the change we are about to make */
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&cooked, doffset))
|
||||
return;
|
||||
|
||||
old_freq_ppm = current_freq_ppm;
|
||||
|
||||
/* Work out new absolute frequency. Note that absolute frequencies
|
||||
|
@ -629,9 +653,13 @@ LCL_MakeStep(void)
|
|||
LCL_ReadRawTime(&raw);
|
||||
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
||||
|
||||
if (!check_offset(&raw, -correction))
|
||||
return 0;
|
||||
|
||||
/* Cancel remaining slew and make the step */
|
||||
LCL_AccumulateOffset(correction, 0.0);
|
||||
LCL_ApplyStepOffset(-correction);
|
||||
if (!LCL_ApplyStepOffset(-correction))
|
||||
return 0;
|
||||
|
||||
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.6f seconds", correction);
|
||||
|
||||
|
|
2
local.h
2
local.h
|
@ -159,7 +159,7 @@ extern void LCL_AccumulateOffset(double offset, double corr_rate);
|
|||
the system clock is fast on true time, i.e. it needs to be stepped
|
||||
backwards. (Same convention as for AccumulateOffset routine). */
|
||||
|
||||
extern void LCL_ApplyStepOffset(double offset);
|
||||
extern int LCL_ApplyStepOffset(double offset);
|
||||
|
||||
/* Routine to invoke notify handlers on an unexpected time jump
|
||||
in system clock */
|
||||
|
|
|
@ -1051,7 +1051,7 @@ REF_SetReference(int stratum,
|
|||
maybe_log_offset(our_offset, raw_now.tv_sec);
|
||||
|
||||
if (step_offset != 0.0) {
|
||||
LCL_ApplyStepOffset(step_offset);
|
||||
if (LCL_ApplyStepOffset(step_offset))
|
||||
LOG(LOGS_WARN, LOGF_Reference, "System clock was stepped by %.6f seconds", -step_offset);
|
||||
}
|
||||
|
||||
|
|
6
rtc.c
6
rtc.c
|
@ -93,9 +93,9 @@ fallback_time_init(void)
|
|||
LCL_ReadCookedTime(&now, NULL);
|
||||
|
||||
if (now.tv_sec < buf.st_mtime) {
|
||||
LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
|
||||
LOG(LOGS_INFO, LOGF_Rtc,
|
||||
"System clock set from driftfile %s", drift_file);
|
||||
if (LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime))
|
||||
LOG(LOGS_INFO, LOGF_Rtc, "System clock set from driftfile %s",
|
||||
drift_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1043,9 +1043,9 @@ RTC_Linux_TimePreInit(void)
|
|||
|
||||
/* Set system time only if the step is larger than 1 second */
|
||||
if (fabs(sys_offset) >= 1.0) {
|
||||
if (LCL_ApplyStepOffset(sys_offset))
|
||||
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
|
||||
accumulated_error);
|
||||
LCL_ApplyStepOffset(sys_offset);
|
||||
}
|
||||
} else {
|
||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
|
||||
|
|
30
util.c
30
util.c
|
@ -606,6 +606,36 @@ UTI_Int64ToTimeval(NTP_int64 *src,
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
/* Maximum offset between two sane times */
|
||||
#define MAX_OFFSET 4294967296.0
|
||||
|
||||
int
|
||||
UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
|
||||
{
|
||||
double t;
|
||||
|
||||
/* Handle nan correctly here */
|
||||
if (!(offset > -MAX_OFFSET && offset < MAX_OFFSET))
|
||||
return 0;
|
||||
|
||||
UTI_TimevalToDouble(tv, &t);
|
||||
t += offset;
|
||||
|
||||
/* Time before 1970 is not considered valid */
|
||||
if (t < 0.0)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_LONG_TIME_T
|
||||
/* Check if it's in the interval to which NTP time is mapped */
|
||||
if (t < (double)NTP_ERA_SPLIT || t > (double)(NTP_ERA_SPLIT + (1LL << 32)))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
|
||||
{
|
||||
|
|
3
util.h
3
util.h
|
@ -104,6 +104,9 @@ extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fu
|
|||
|
||||
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
|
||||
|
||||
/* Check if time + offset is sane */
|
||||
extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset);
|
||||
|
||||
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
|
||||
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
||||
|
||||
|
|
Loading…
Reference in a new issue