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
|
static void
|
||||||
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
|
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);
|
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
|
/* This involves both setting the absolute frequency with the
|
||||||
system-specific driver, as well as calling all notify handlers */
|
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_ReadRawTime(&raw);
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&cooked, offset))
|
||||||
|
return;
|
||||||
|
|
||||||
(*drv_accrue_offset)(offset, corr_rate);
|
(*drv_accrue_offset)(offset, corr_rate);
|
||||||
|
|
||||||
/* Dispatch to all handlers */
|
/* Dispatch to all handlers */
|
||||||
|
@ -498,7 +514,7 @@ LCL_AccumulateOffset(double offset, double corr_rate)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
int
|
||||||
LCL_ApplyStepOffset(double offset)
|
LCL_ApplyStepOffset(double offset)
|
||||||
{
|
{
|
||||||
struct timeval raw, cooked;
|
struct timeval raw, cooked;
|
||||||
|
@ -509,6 +525,9 @@ LCL_ApplyStepOffset(double offset)
|
||||||
LCL_ReadRawTime(&raw);
|
LCL_ReadRawTime(&raw);
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&raw, offset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
(*drv_apply_step_offset)(offset);
|
(*drv_apply_step_offset)(offset);
|
||||||
|
|
||||||
/* Reset smoothing on all clock steps */
|
/* Reset smoothing on all clock steps */
|
||||||
|
@ -516,6 +535,8 @@ LCL_ApplyStepOffset(double offset)
|
||||||
|
|
||||||
/* Dispatch to all handlers */
|
/* Dispatch to all handlers */
|
||||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep);
|
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 */
|
to the change we are about to make */
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&cooked, doffset))
|
||||||
|
return;
|
||||||
|
|
||||||
old_freq_ppm = current_freq_ppm;
|
old_freq_ppm = current_freq_ppm;
|
||||||
|
|
||||||
/* Work out new absolute frequency. Note that absolute frequencies
|
/* Work out new absolute frequency. Note that absolute frequencies
|
||||||
|
@ -629,9 +653,13 @@ LCL_MakeStep(void)
|
||||||
LCL_ReadRawTime(&raw);
|
LCL_ReadRawTime(&raw);
|
||||||
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&raw, -correction))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Cancel remaining slew and make the step */
|
/* Cancel remaining slew and make the step */
|
||||||
LCL_AccumulateOffset(correction, 0.0);
|
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);
|
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
|
the system clock is fast on true time, i.e. it needs to be stepped
|
||||||
backwards. (Same convention as for AccumulateOffset routine). */
|
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
|
/* Routine to invoke notify handlers on an unexpected time jump
|
||||||
in system clock */
|
in system clock */
|
||||||
|
|
|
@ -1051,7 +1051,7 @@ REF_SetReference(int stratum,
|
||||||
maybe_log_offset(our_offset, raw_now.tv_sec);
|
maybe_log_offset(our_offset, raw_now.tv_sec);
|
||||||
|
|
||||||
if (step_offset != 0.0) {
|
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);
|
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);
|
LCL_ReadCookedTime(&now, NULL);
|
||||||
|
|
||||||
if (now.tv_sec < buf.st_mtime) {
|
if (now.tv_sec < buf.st_mtime) {
|
||||||
LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
|
if (LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime))
|
||||||
LOG(LOGS_INFO, LOGF_Rtc,
|
LOG(LOGS_INFO, LOGF_Rtc, "System clock set from driftfile %s",
|
||||||
"System clock set from driftfile %s", drift_file);
|
drift_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1043,9 +1043,9 @@ RTC_Linux_TimePreInit(void)
|
||||||
|
|
||||||
/* Set system time only if the step is larger than 1 second */
|
/* Set system time only if the step is larger than 1 second */
|
||||||
if (fabs(sys_offset) >= 1.0) {
|
if (fabs(sys_offset) >= 1.0) {
|
||||||
|
if (LCL_ApplyStepOffset(sys_offset))
|
||||||
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
|
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
|
||||||
accumulated_error);
|
accumulated_error);
|
||||||
LCL_ApplyStepOffset(sys_offset);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
|
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
|
void
|
||||||
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
|
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);
|
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_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
|
||||||
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue