Date: Wed, 15 Apr 2020 07:03:00 +0800
Subject: [PATCH] Use-of-uninitialized-value in receive function

---
 ntpd/ntp_proto.c | 43 ++++++++++++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c
index eb66351..baffe1b 100644
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -640,31 +640,20 @@ receive(
 	 */
 	/*
 	 * Bogus port check is before anything, since it probably
-	 * reveals a clogging attack.
+	 * reveals a clogging attack. Likewise the mimimum packet size
+	 * of 2 bytes (for mode 6/7) must be checked first.
 	 */
 	sys_received++;
-	if (0 == SRCPORT(&rbufp->recv_srcadr)) {
+	if (0 == SRCPORT(&rbufp->recv_srcadr) || rbufp->recv_length < 2) {
 		sys_badlength++;
-		return;				/* bogus port */
+		return;				/* bogus port / length */
 	}
 	restrictions(&rbufp->recv_srcadr, &r4a);
 	restrict_mask = r4a.rflags;
 
 	pkt = &rbufp->recv_pkt;
 	hisversion = PKT_VERSION(pkt->li_vn_mode);
-	hisleap = PKT_LEAP(pkt->li_vn_mode);
 	hismode = (int)PKT_MODE(pkt->li_vn_mode);
-	hisstratum = PKT_TO_STRATUM(pkt->stratum);
-	DPRINTF(1, ("receive: at %ld %s<-%s ippeerlimit %d mode %d iflags %s restrict %s org %#010x.%08x xmt %#010x.%08x\n",
-		    current_time, stoa(&rbufp->dstadr->sin),
-		    stoa(&rbufp->recv_srcadr), r4a.ippeerlimit, hismode,
-		    build_iflags(rbufp->dstadr->flags),
-		    build_rflags(restrict_mask),
-		    ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
-		    ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
-
-	/* See basic mode and broadcast checks, below */
-	INSIST(0 != hisstratum);
 
 	if (restrict_mask & RES_IGNORE) {
 		DPRINTF(2, ("receive: drop: RES_IGNORE\n"));
@@ -696,6 +685,30 @@ receive(
 		return;				/* no time serve */
 	}
 
+
+	/* If we arrive here, we should have a standard NTP packet. We
+	 * check that the minimum size is available and fetch some more
+	 * items from the packet once we can be sure they are indeed
+	 * there.
+	 */
+	if (rbufp->recv_length < LEN_PKT_NOMAC) {
+		sys_badlength++;
+		return;				/* bogus length */
+	}
+
+	hisleap = PKT_LEAP(pkt->li_vn_mode);
+	hisstratum = PKT_TO_STRATUM(pkt->stratum);
+	INSIST(0 != hisstratum); /* paranoia check PKT_TO_STRATUM result */
+
+	DPRINTF(1, ("receive: at %ld %s<-%s ippeerlimit %d mode %d iflags %s "
+		    "restrict %s org %#010x.%08x xmt %#010x.%08x\n",
+		    current_time, stoa(&rbufp->dstadr->sin),
+		    stoa(&rbufp->recv_srcadr), r4a.ippeerlimit, hismode,
+		    build_iflags(rbufp->dstadr->flags),
+		    build_rflags(restrict_mask),
+		    ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
+		    ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
+
 	/*
 	 * This is for testing. If restricted drop ten percent of
 	 * surviving packets.
-- 
2.23.0

