From: Juergen Perlinger Date: Sat, 17 Oct 2015 19:15:39 +0000 (+0200) Subject: [Bug 2948] Potential Infinite Loop in ntpq and ntpdc X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94c17aae0bfc63e09185d3e53a4ac0327a8a099c;p=thirdparty%2Fntp.git [Bug 2948] Potential Infinite Loop in ntpq and ntpdc bk: 56229e5bz1aus9e4pFM3A8U7NNpttQ --- diff --git a/ChangeLog b/ChangeLog index b022ef6f6..55d152ef4 100644 --- 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 * [Bug 2332] (reopened) Exercise thread cancellation once before dropping diff --git a/ntpdc/ntpdc.c b/ntpdc/ntpdc.c index ab177885b..797eacda4 100644 --- a/ntpdc/ntpdc.c +++ b/ntpdc/ntpdc.c @@ -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(); diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index 17fe2ea45..6fa6a5c0a 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -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.