]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
client: don't call select() with invalid timeout
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 5 Dec 2017 10:08:24 +0000 (11:08 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 5 Dec 2017 11:13:37 +0000 (12:13 +0100)
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().

client.c

index 5c3a99e02b1d3aac2bcc79b12f4b87d9028ef743..4e23158acebd3541696ebcb4167010446f138841 100644 (file)
--- 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;