]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2948] Potential Infinite Loop in ntpq and ntpdc
authorJuergen Perlinger <perlinger@ntp.org>
Sat, 17 Oct 2015 19:15:39 +0000 (21:15 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Sat, 17 Oct 2015 19:15:39 +0000 (21:15 +0200)
bk: 56229e5bz1aus9e4pFM3A8U7NNpttQ

ChangeLog
ntpdc/ntpdc.c
ntpq/ntpq.c

index b022ef6f6a86c267d69a5ae3c8fa64474ef83859..55d152ef42a9ce55d9a7b43aa68cab408b9456e7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,6 @@
 ---
+* [Bug 2948] Potential Infinite Loop in ntpq ( and ntpdc) perlinger@ntp.org
+---
 (4.2.8p4-RC1) 2015/10/06 Released by Harlan Stenn <stenn@ntp.org>
 
 * [Bug 2332] (reopened) Exercise thread cancellation once before dropping
index ab177885b9a562c4c165bc5dd136fdc216441ef0..797eacda42e26f6c9a0a80468535ca4f74a3472b 100644 (file)
@@ -604,6 +604,10 @@ getresponse(
        fd_set fds;
        ssize_t n;
        int pad;
+       /* absolute timeout checks. Not 'time_t' by intention! */
+       uint32_t tobase;        /* base value for timeout */
+       uint32_t tospan;        /* timeout span (max delay) */
+       uint32_t todiff;        /* current delay */
 
        /*
         * This is pretty tricky.  We may get between 1 and many packets
@@ -620,12 +624,14 @@ getresponse(
        lastseq = 999;  /* too big to be a sequence number */
        ZERO(haveseq);
        FD_ZERO(&fds);
+       tobase = (uint32_t)time(NULL);
 
     again:
        if (firstpkt)
                tvo = tvout;
        else
                tvo = tvsout;
+       tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
        
        FD_SET(sockfd, &fds);
        n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo);
@@ -634,6 +640,17 @@ getresponse(
                warning("select fails");
                return -1;
        }
+       
+       /*
+        * Check if this is already too late. Trash the data and fake a
+        * timeout if this is so.
+        */
+       todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
+       if ((n > 0) && (todiff > tospan)) {
+               n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
+               n = 0; /* faked timeout return from 'select()'*/
+       }
+       
        if (n == 0) {
                /*
                 * Timed out.  Return what we have
@@ -778,8 +795,10 @@ getresponse(
        }
 
        /*
-        * So far, so good.  Copy this data into the output array.
+        * So far, so good.  Copy this data into the output array. Bump
+        * the timeout base, in case we expect more data.
         */
+       tobase = (uint32_t)time(NULL);
        if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
                int offset = datap - pktdata;
                growpktdata();
index 17fe2ea45d5b756b48e85e4833211cf7158af6dd..6fa6a5c0af5be99092523e7b3f0b556515a0a1fa 100644 (file)
@@ -841,6 +841,10 @@ getresponse(
        fd_set fds;
        int n;
        int errcode;
+       /* absolute timeout checks. Not 'time_t' by intention! */
+       uint32_t tobase;        /* base value for timeout */
+       uint32_t tospan;        /* timeout span (max delay) */
+       uint32_t todiff;        /* current delay */
 
        /*
         * This is pretty tricky.  We may get between 1 and MAXFRAG packets
@@ -857,6 +861,8 @@ getresponse(
        numfrags = 0;
        seenlastfrag = 0;
 
+       tobase = (uint32_t)time(NULL);
+       
        FD_ZERO(&fds);
 
        /*
@@ -869,6 +875,7 @@ getresponse(
                        tvo = tvout;
                else
                        tvo = tvsout;
+               tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
 
                FD_SET(sockfd, &fds);
                n = select(sockfd + 1, &fds, NULL, NULL, &tvo);
@@ -877,6 +884,17 @@ getresponse(
                        warning("select fails");
                        return -1;
                }
+
+               /*
+                * Check if this is already too late. Trash the data and
+                * fake a timeout if this is so.
+                */
+               todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
+               if ((n > 0) && (todiff > tospan)) {
+                       n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
+                       n = 0; /* faked timeout return from 'select()'*/
+               }
+               
                if (n == 0) {
                        /*
                         * Timed out.  Return what we have
@@ -1139,10 +1157,12 @@ getresponse(
                }
 
                /*
-                * Copy the data into the data buffer.
+                * Copy the data into the data buffer, and bump the
+                * timout base in case we need more.
                 */
                memcpy((char *)pktdata + offset, &rpkt.u, count);
-
+               tobase = (uint32_t)time(NULL);
+               
                /*
                 * If we've seen the last fragment, look for holes in the sequence.
                 * If there aren't any, we're done.