]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2148] ntpd 4.2.7p258 segfault with 0x0100000 bit in NMEA mode.
authorDave Hart <hart@ntp.org>
Wed, 22 Feb 2012 05:05:04 +0000 (05:05 +0000)
committerDave Hart <hart@ntp.org>
Wed, 22 Feb 2012 05:05:04 +0000 (05:05 +0000)
refclock_nmea.c merge cleanup thanks to Juergen Perlinger.
Use mutex with Lamport checks in get_systime() on Windows, which
  unlike portable ntpd uses the routine across threads.

bk: 4f447780WcagGVkhY7Nx3Nz2XtBGWg

12 files changed:
ChangeLog
include/ntp_assert.h
include/ntp_fp.h
libntp/lib_strbuf.c
libntp/systime.c
ntpd/ntp_control.c
ntpd/ntp_refclock.c
ntpd/ntpd.c
ntpd/refclock_nmea.c
ports/winnt/ntpd/ntp_iocompletionport.c
sntp/tests_main.cpp
sntp/tests_main.h

index cb078f78d80fcdce2f01144dc736336e7b72be05..7bebf88c172e79809974a94f6fc9c31ae1d8f8b6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+* [Bug 2148] ntpd 4.2.7p258 segfault with 0x0100000 bit in NMEA mode.
+* refclock_nmea.c merge cleanup thanks to Juergen Perlinger.
 (4.2.7p258) 2012/02/21 Released by Harlan Stenn <stenn@ntp.org>
 * [Bug 2140] Rework of Windows I/O completion port handling to avoid
   garbling serial input in UNIX line discipline emulation.
index ab9b41981be686c9d41ea6da8a67ad0f7760c8a2..206d50d26542a3c43c0fe3e6ac3821ee3c6f3494 100644 (file)
@@ -88,10 +88,10 @@ extern void calysto_assert(unsigned char cnd); /* check whether this holds */
 #define        DEBUG_INVARIANT(x)      INVARIANT(x)
 #define        DEBUG_ENSURE(x)         ENSURE(x)
 # else
-#define        DEBUG_REQUIRE(x)        (void)(x)
-#define        DEBUG_INSIST(x)         (void)(x)
-#define        DEBUG_INVARIANT(x)      (void)(x)
-#define        DEBUG_ENSURE(x)         (void)(x)
+#define        DEBUG_REQUIRE(x)        do {} while (FALSE)
+#define        DEBUG_INSIST(x)         do {} while (FALSE)
+#define        DEBUG_INVARIANT(x)      do {} while (FALSE)
+#define        DEBUG_ENSURE(x)         do {} while (FALSE)
 # endif
 
 #endif /* NTP_ASSERT_H */
index 1eeca3747b16e083091420f82fc43d66417083dc..bb58bf1f86bd30657c28b589c56585b5f841e3c5 100644 (file)
@@ -357,6 +357,7 @@ extern      char *  uglydate        (l_fp *);
 extern  void   mfp_mul         (int32 *, u_int32 *, int32, u_int32, int32, u_int32);
 
 extern void    set_sys_fuzz    (double);
+extern void    init_systime    (void);
 extern void    get_systime     (l_fp *);
 extern int     step_systime    (double);
 extern int     adj_systime     (double);
@@ -383,4 +384,33 @@ extern     struct tm * ntp2unix_tm (u_int32 ntp, int local);
  */
 typedef void (*time_stepped_callback)(void);
 extern time_stepped_callback   step_callback;
+
+/*
+ * Multi-thread locking for get_systime()
+ *
+ * On most systems, get_systime() is used solely by the main ntpd
+ * thread, but on Windows it's also used by the dedicated I/O thread.
+ * The [Bug 2037] changes to get_systime() have it keep state between
+ * calls to ensure time moves in only one direction, which means its
+ * use on Windows needs to be protected against simultaneous execution
+ * to avoid falsely detecting Lamport violations by ensuring only one
+ * thread at a time is in get_systime().
+ */
+#ifdef SYS_WINNT
+extern CRITICAL_SECTION get_systime_cs;
+# define INIT_GET_SYSTIME_CRITSEC()                            \
+               InitializeCriticalSection(&get_systime_cs)
+# define ENTER_GET_SYSTIME_CRITSEC()                           \
+               EnterCriticalSection(&get_systime_cs)
+# define LEAVE_GET_SYSTIME_CRITSEC()                           \
+               LeaveCriticalSection(&get_systime_cs)
+#else  /* !SYS_WINNT follows */
+# define INIT_GET_SYSTIME_CRITSEC()                    \
+               do {} while (FALSE)
+# define ENTER_GET_SYSTIME_CRITSEC()                   \
+               do {} while (FALSE)
+# define LEAVE_GET_SYSTIME_CRITSEC()                   \
+               do {} while (FALSE)
+#endif
+
 #endif /* NTP_FP_H */
index 9ddf5cf5059b83c442462cd41ed8f409d494b873..76f70163de981a50490dc404e71ab368975506c2 100644 (file)
@@ -7,9 +7,12 @@
 
 #include <isc/net.h>
 #include <isc/result.h>
+
+#include "ntp_fp.h"
 #include "ntp_stdlib.h"
 #include "lib_strbuf.h"
 
+
 /*
  * Storage declarations
  */
@@ -20,6 +23,7 @@ int           ipv4_works;
 int            ipv6_works;
 int            lib_inited;
 
+
 /*
  * initialization routine.  Might be needed if the code is ROMized.
  */
@@ -30,5 +34,6 @@ init_lib(void)
                return;
        ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
        ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
+       init_systime();
        lib_inited = TRUE;
 }
index 70a4af5fcdb2d2af19470907fe57577771d6d46e..fbe403b98105e9bc76cb5a1805828d5a4a0c993c 100644 (file)
@@ -76,7 +76,18 @@ time_stepped_callback        step_callback;
 
 #ifndef SIM
 static int lamport_violated;   /* clock was stepped back */
+#endif /* !SIM */
+
+#ifdef DEBUG
+static int systime_init_done;
+# define DONE_SYSTIME_INIT()   systime_init_done = TRUE
+#else
+# define DONE_SYSTIME_INIT()   do {} while (FALSE)
 #endif
+#ifdef SYS_WINNT
+CRITICAL_SECTION get_systime_cs;
+#endif
+
 
 void
 set_sys_fuzz(
@@ -90,6 +101,14 @@ set_sys_fuzz(
 }
 
 
+void
+init_systime(void)
+{
+       INIT_GET_SYSTIME_CRITSEC();
+       DONE_SYSTIME_INIT();
+}
+
+
 #ifndef SIM    /* ntpsim.c has get_systime() and friends for sim */
 
 static inline void
@@ -134,6 +153,7 @@ get_systime(
 {
        static struct timespec  ts_prev;        /* prior os time */
        static l_fp             lfp_prev;       /* prior result */
+       static double           dfuzz_prev;     /* prior fuzz */
        struct timespec ts;     /* seconds and nanoseconds */
        struct timespec ts_min; /* earliest permissible */
        struct timespec ts_lam; /* lamport fictional increment */
@@ -145,6 +165,8 @@ get_systime(
        l_fp    lfpdelta;
 
        get_ostime(&ts);
+       DEBUG_REQUIRE(systime_init_done);
+       ENTER_GET_SYSTIME_CRITSEC();
 
        /*
         * After default_get_precision() has set a nonzero sys_fuzz,
@@ -188,8 +210,8 @@ get_systime(
                        msyslog(LOG_ERR, "ts_min %s ts_prev %s ts %s",
                                tspectoa(ts_min), tspectoa(ts_prev_log),
                                tspectoa(ts));
-                       msyslog(LOG_ERR, "sys_fuzz %ld nsec, this fuzz %.9f",
-                               sys_fuzz_nsec, dfuzz);
+                       msyslog(LOG_ERR, "sys_fuzz %ld nsec, this fuzz %.9f, prior %.9f",
+                               sys_fuzz_nsec, dfuzz, dfuzz_prev);
                        lfpdelta = lfp_prev;
                        L_SUB(&lfpdelta, &result);
                        LFPTOD(&lfpdelta, ddelta);
@@ -200,9 +222,11 @@ get_systime(
                }
        }
        lfp_prev = result;
+       dfuzz_prev = dfuzz;
        if (lamport_violated) 
                lamport_violated = FALSE;
 
+       LEAVE_GET_SYSTIME_CRITSEC();
        *now = result;
 }
 
index 17456b1107a6a3a65e5d8f64c1b025a4108e5e20..7f6d116ab1f88434e305878a18e51d93cab0b4ad 100644 (file)
@@ -2454,7 +2454,13 @@ ctl_putpeer(
                break;
 
        case CP_TTL:
-               if (p->ttl)
+#ifdef REFCLOCK
+               if (p->flags & FLAG_REFCLOCK) {
+                       ctl_putuint(peer_var[id].text, p->ttl);
+                       break;
+               }
+#endif
+               if (p->ttl > 0 && p->ttl < COUNTOF(sys_ttl))
                        ctl_putint(peer_var[id].text,
                                   sys_ttl[p->ttl]);
                break;
index 22ca7ff043fde8857dcc5c93c95dff424b7e9fe1..65097150ad3ef5c5abe329423991418bedb9e862 100644 (file)
@@ -609,7 +609,9 @@ refclock_gtlin(
        *tsptr = rbufp->recv_time;
        DPRINTF(2, ("refclock_gtlin: fd %d time %s timecode %d %s\n",
                    rbufp->fd, ulfptoa(&rbufp->recv_time, 6), dlen,
-                   lineptr));
+                   (dlen != 0)
+                       ? lineptr
+                       : ""));
        return (dlen);
 }
 
index 6073f32df1a894f7b6e15d86f57d2ccdcf33fd56..589a0c6fcb2bfc793a390ef192cd294a712b8ac9 100644 (file)
@@ -558,6 +558,7 @@ ntpdmain(
        } while (0);                            /* 'loop' once */
 # endif        /* HAVE_WORKING_FORK */
 
+       init_lib();
 # ifdef SYS_WINNT
        /*
         * Start interpolation thread, must occur before first
@@ -763,7 +764,6 @@ ntpdmain(
        init_restrict();
        init_mon();
        init_timer();
-       init_lib();
        init_request();
        init_control();
        init_peer();
index 88875a20945d5706a02158251c3588f66af0d218..13bcca2b90d48cd4906c195a446f56cf70573266 100644 (file)
@@ -241,11 +241,6 @@ typedef struct {
                tally;
        /* per sentence checksum seen flag */
        u_char  cksum_type[NMEA_ARRAY_SIZE];
-       int     total_nmea;     /* clockstats sentence counts */
-       int     good_nmea;
-       int     bad_nmea;
-       int     filter_nmea;
-       int     pps_used;
 } nmea_unit;
 
 /*
@@ -995,14 +990,6 @@ nmea_receive(
        pp->a_lastcode[rd_lencode] = '\0';
        pp->lastrec = rd_timestamp;
 
-       if (pp->leap == LEAP_NOTINSYNC) {
-               up->bad_nmea++;
-               return;
-       }
-
-       /* Text looks OK. */
-       up->good_nmea++;
-
 #ifdef HAVE_PPSAPI
        /*
         * If we have PPS running, we try to associate the sentence
index cbec92e364d87f3c6336b472ae5f0721690efd27..9e3e541f345f966317b53672c112ad879391718d 100644 (file)
@@ -615,7 +615,7 @@ OnSerialWaitComplete(
                        lpo->DCDSTime = lpo->RecvTime;
                        lpo->flTsDCDS = 1;
                        DPRINTF(2, ("fd %d DCD PPS at %s\n", rio->fd,
-                                   lfptoa(&lpo->RecvTime, 6)));
+                                   ulfptoa(&lpo->RecvTime, 6)));
                }
        }
 
index beb51cab6b6f0b9fd836c44926d1b8452ce59adb..d9d6277b1c1b13aeda37c173c60849e20133239b 100644 (file)
@@ -3,6 +3,8 @@
 int main(int argc, char **argv) {
        ::testing::InitGoogleTest(&argc, argv);
 
+       init_lib();
+
        // Some tests makes use of extra parameters passed to the tests
        // executable. Save these params as static members of the base class.
        if (argc > 1) {
index d280da80a7a657ad7b2a2cb8893823441bb699f8..991f4b6d0da3fdde6abd47d049e9982a93122c12 100644 (file)
@@ -8,6 +8,9 @@
 
 #include <gtest/gtest.h>
 
+extern "C" {
+#include "ntp_stdlib.h"
+}
 
 class ntptest : public ::testing::Test {
 public: