]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Fix crash with duplicated initstepslew address
authorvictor lum <viclum@vanu.com>
Fri, 26 Apr 2013 12:36:17 +0000 (14:36 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 26 Apr 2013 12:36:17 +0000 (14:36 +0200)
When there are duplicate ntp servers listed on the initstepslew line, 2
SourceRecords are created (sourceA and sourceB), and two timers are
created (timerA and timerB).  When ntp responses are received, only
sourceA is updated because of the way read_from_socket searches for a
matching record.  Eventually, the criteria for sourceA are met, causing
timerA to stop and n_completed_sources to increment.  timerB continues
to trigger, sending ntp poll messages to the ntp server.  Responses from
that server are assigned to sourceA, triggering the criteria for sourceA
and causing n_completed_sources to increment improperly.  Once this
happens enough times, n_complete_sources == number of servers and all
SourceRecords are deleted.  The next time timerB triggers, it attempts
to access sourceB, which was already been deleted, causing the core.

acquire.c

index 6b479f83d526223170aeb3496811da229551e075..a35a09bacb9e0b5ea6dc1c629969ca09b7b6b645 100644 (file)
--- a/acquire.c
+++ b/acquire.c
@@ -757,6 +757,7 @@ ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(
 {
 
   int i, ip4, ip6;
+  int k, duplicate_ip;
 
   saved_after_hook = after_hook;
   saved_after_hook_anything = anything;
@@ -765,18 +766,31 @@ ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(
 
   n_started_sources = 0;
   n_completed_sources = 0;
-  n_sources = n;
+  n_sources = 0;
   sources = MallocArray(SourceRecord, n);
 
   for (i = ip4 = ip6 = 0; i < n; i++) {
-    sources[i].ip_addr = ip_addrs[i];
-    sources[i].n_samples = 0;
-    sources[i].n_total_samples = 0;
-    sources[i].n_dead_probes = 0;
-    if (ip_addrs[i].family == IPADDR_INET4)
-      ip4++;
-    else if (ip_addrs[i].family == IPADDR_INET6)
-      ip6++;
+    /* check for duplicate IP addresses and ignore them */
+    duplicate_ip = 0;
+    for (k = 0; k < i; k++) {
+      duplicate_ip |= UTI_CompareIPs(&(sources[k].ip_addr),
+                                     &ip_addrs[i],
+                                     NULL) == 0;
+    }
+    if (!duplicate_ip) {
+      sources[n_sources].ip_addr = ip_addrs[i];
+      sources[n_sources].n_samples = 0;
+      sources[n_sources].n_total_samples = 0;
+      sources[n_sources].n_dead_probes = 0;
+      if (ip_addrs[i].family == IPADDR_INET4)
+        ip4++;
+      else if (ip_addrs[i].family == IPADDR_INET6)
+        ip6++;
+      n_sources++;
+    } else {
+      LOG(LOGS_WARN, LOGF_Acquire, "Ignoring duplicate source: %s",
+          UTI_IPToString(&ip_addrs[i]));
+    }
   }
 
   initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));