commit d0b24860363a3704e28569ce9a6987717834edea Author: Miroslav Lichvar Date: Tue Dec 5 11:08:24 2017 +0100 client: don't call select() with invalid timeout If the system clock was stepped forward after chronyc sent a request and before it read the clock in order to calculate the receive timeout, select() could be called with a negative timeout, which resulted in an infinite loop waiting for select() to succeed. Fix the submit_request() function to not call select() with a negative timeout. Also, return immediately on any error of select(). diff --git a/client.c b/client.c index 5c3a99e..4e23158 100644 --- a/client.c +++ b/client.c @@ -1394,9 +1394,16 @@ submit_request(CMD_Request *request, CMD_Reply *reply) timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) - UTI_DiffTimespecsToDouble(&ts_now, &ts_start); - UTI_DoubleToTimeval(timeout, &tv); DEBUG_LOG("Timeout %f seconds", timeout); + /* Avoid calling select() with an invalid timeout */ + if (timeout <= 0.0) { + new_attempt = 1; + continue; + } + + UTI_DoubleToTimeval(timeout, &tv); + FD_ZERO(&rdfd); FD_ZERO(&wrfd); FD_ZERO(&exfd); @@ -1410,6 +1417,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply) if (select_status < 0) { DEBUG_LOG("select failed : %s", strerror(errno)); + return 0; } else if (select_status == 0) { /* Timeout must have elapsed, try a resend? */ new_attempt = 1; commit 6863e43269fe27ce2744eb643295f31c00ec176d Author: Miroslav Lichvar Date: Tue Dec 12 11:03:04 2017 +0100 client: avoid reading clock after sending request If chronyc sent a request which caused chronyd to step the clock (e.g. makestep, settime) and the second reading of the clock before calling select() to wait for a response happened after the clock was stepped, a new request could be sent immediately and chronyd would process the same command twice. If the second request failed (e.g. a settime request too close to the first request), chronyc would report an error. Change the submit_request() function to read the clock only once per select() to wait for the first response even when the clock was stepped. diff --git a/client.c b/client.c index a04dcb8..7d1e346 100644 --- a/client.c +++ b/client.c @@ -1347,15 +1347,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply) new_attempt = 1; do { + if (gettimeofday(&tv, NULL)) + return 0; + if (new_attempt) { new_attempt = 0; if (n_attempts > max_retries) return 0; - if (gettimeofday(&tv, NULL)) - return 0; - UTI_TimevalToTimespec(&tv, &ts_start); UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence)); @@ -1383,9 +1383,6 @@ submit_request(CMD_Request *request, CMD_Reply *reply) DEBUG_LOG("Sent %d bytes", command_length); } - if (gettimeofday(&tv, NULL)) - return 0; - UTI_TimevalToTimespec(&tv, &ts_now); /* Check if the clock wasn't stepped back */