nss_dns: Skip over non-PTR records in the netent code [BZ #19868]

Message ID 56F58B81.3010306@redhat.com
State Committed
Headers

Commit Message

Florian Weimer March 25, 2016, 7:03 p.m. UTC
  The DNS packet parser was broken and got de-synchronized by CNAME or
RRSIG records.  CNAME records are the larger problem because they come
before the PTR records we are interested in.

Curiously, this meant that the RDATA length check was not actually
missing (it was implied by the loop condition).

Florian
  

Comments

Florian Weimer April 27, 2016, 3:18 p.m. UTC | #1
On 03/25/2016 08:03 PM, Florian Weimer wrote:
> 2016-03-25  Florian Weimer<fweimer@redhat.com>
>
> 	[BZ #19868]
> 	* resolv/nss_dns/dns-network.c (getanswer_r): Skip over non-PTR
> 	records.

I have pushed this.

Thanks,
Florian
  

Patch

2016-03-25  Florian Weimer  <fweimer@redhat.com>

	[BZ #19868]
	* resolv/nss_dns/dns-network.c (getanswer_r): Skip over non-PTR
	records.

diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 2eb2f67..8d6ee0d 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -348,10 +348,23 @@  getanswer_r (const querybuf *answer, int anslen, struct netent *result,
       if (n < 0 || res_dnok (bp) == 0)
 	break;
       cp += n;
+
+      if (end_of_message - cp < 10)
+	{
+	  __set_h_errno (NO_RECOVERY);
+	  return NSS_STATUS_UNAVAIL;
+	}
+
       GETSHORT (type, cp);
       GETSHORT (class, cp);
       cp += INT32SZ;		/* TTL */
-      GETSHORT (n, cp);
+      uint16_t rdatalen;
+      GETSHORT (rdatalen, cp);
+      if (end_of_message - cp < rdatalen)
+	{
+	  __set_h_errno (NO_RECOVERY);
+	  return NSS_STATUS_UNAVAIL;
+	}
 
       if (class == C_IN && type == T_PTR)
 	{
@@ -373,7 +386,7 @@  getanswer_r (const querybuf *answer, int anslen, struct netent *result,
 	      cp += n;
 	      return NSS_STATUS_UNAVAIL;
 	    }
-	  cp += n;
+	  cp += rdatalen;
          if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
            {
              *alias_pointer++ = bp;
@@ -384,6 +397,9 @@  getanswer_r (const querybuf *answer, int anslen, struct netent *result,
              ++have_answer;
            }
 	}
+      else
+	/* Skip over unknown record data.  */
+	cp += rdatalen;
     }
 
   if (have_answer)