Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 168944 Details for
Bug 242254
mail-filter/libspf2 <1.2.8 DNS response buffer overflow (CVE-2008-2469)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
50_dns_resolv_bufoverflow.dpatch
50_dns_resolv_bufoverflow.dpatch (text/plain), 8.98 KB, created by
Robert Buchholz (RETIRED)
on 2008-10-18 15:39:50 UTC
(
hide
)
Description:
50_dns_resolv_bufoverflow.dpatch
Filename:
MIME Type:
Creator:
Robert Buchholz (RETIRED)
Created:
2008-10-18 15:39:50 UTC
Size:
8.98 KB
patch
obsolete
>#! /bin/sh /usr/share/dpatch/dpatch-run >## 50_permanent_include_errors.dpatch by Shevek <shevek@anarres.org>, edited by Magnus Holmgren >## >## DP: Fix CVE-2008-2469 - buffer overflows handling DNS responses. > >@DPATCH@ > >--- libspf2/src/libspf2/spf_dns_resolv.c.orig 2008-09-20 19:36:57.000000000 +0200 >+++ libspf2/src/libspf2/spf_dns_resolv.c 2008-09-20 19:39:08.000000000 +0200 >@@ -110,7 +110,8 @@ > int nrec; > int cnt; > >- u_char response[2048]; >+ u_char *responsebuf; >+ size_t responselen; > > int dns_len; > >@@ -127,11 +128,13 @@ > char name_buf[ NS_MAXDNAME ]; > int prio; > >- int rdlen; >- const u_char *rdata, *rdata_end; >+ size_t rdlen; >+ const u_char *rdata; > >+#if HAVE_DECL_RES_NINIT > void *res_spec; > struct __res_state *res_state; >+#endif > > SPF_ASSERT_NOTNULL(spf_dns_server); > >@@ -140,10 +143,12 @@ > SPF_ASSERT_NOTNULL(spfhook); > #endif > >+#if HAVE_DECL_RES_NINIT > res_spec = pthread_getspecific(res_state_key); > if (res_spec == NULL) { > res_state = (struct __res_state *) > malloc(sizeof(struct __res_state)); >+ memset(res_state, 0, sizeof(struct __res_state)); > if (res_ninit(res_state) != 0) { > SPF_error("Failed to call res_ninit()"); > } >@@ -152,20 +157,45 @@ > else { > res_state = (struct __res_state *)res_spec; > } >+#endif >+ >+ responselen = 2048; >+ responsebuf = (u_char *)malloc(responselen); >+ memset(responsebuf, 0, responselen); >+ >+ /* >+ * Retry the lookup until our response buffer is big enough. >+ * >+ * This loop repeats until either we fail a lookup or we succeed. >+ * The size of the response buffer is monotonic increasing, so eventually we >+ * must either succeed, or we try to malloc more RAM than we can. >+ * >+ * The Linux man pages do not describe res_nquery adequately. Solaris says: >+ * >+ * The res_nquery() and res_query() routines return a length that may be bigger >+ * than anslen. In that case, retry the query with a larger buf. The answer to the >+ * second query may be larger still], so it is recommended that you supply a buf >+ * larger than the answer returned by the previous query. answer must be large >+ * enough to receive a maximum UDP response from the server or parts of the answer >+ * will be silently discarded. The default maximum UDP response size is 512 bytes. >+ */ >+ for (;;) { > > /* > * try resolving the name > */ > #if HAVE_DECL_RES_NINIT > dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, >- response, sizeof(response)); >+ responsebuf, responselen); > #else > dns_len = res_query(domain, ns_c_in, rr_type, >- response, sizeof(response)); >+ responsebuf, responselen); > #endif > > if ( dns_len < 0 ) { >+ /* We failed to perform a lookup. */ > /* This block returns unconditionally. */ >+ free(responsebuf); > if ( spf_dns_server->debug ) > SPF_debugf( "query failed: err = %d %s (%d): %s", > dns_len, hstrerror( SPF_h_errno ), SPF_h_errno, >@@ -178,6 +208,25 @@ > return SPF_dns_rr_new_init(spf_dns_server, > domain, rr_type, 0, SPF_h_errno); > } >+ else if (dns_len > responselen) { >+ /* We managed a lookup but our buffer was too small. */ >+ responselen = dns_len + (dns_len >> 1); >+#if 0 >+ /* Sanity-trap - we should never hit this. */ >+ if (responselen > 1048576) { /* One megabyte. */ >+ free(responsebuf); >+ return SPF_dns_rr_new_init(spf_dns_server, >+ domain, rr_type, 0, SPF_h_errno); >+ } >+#endif >+ responsebuf = realloc(responsebuf, responselen); >+ } >+ else { >+ /* We managed a lookup, and our buffer was large enough. */ >+ responselen = dns_len; >+ break; >+ } >+ } > > /* > * initialize stuff >@@ -185,12 +234,13 @@ > spfrr = SPF_dns_rr_new_init(spf_dns_server, > domain, rr_type, 0, NETDB_SUCCESS); > >- err = ns_initparse( response, dns_len, &ns_handle ); >+ err = ns_initparse(responsebuf, responselen, &ns_handle); > > if ( err < 0 ) { /* 0 or -1 */ > if ( spf_dns_server->debug ) > SPF_debugf( "ns_initparse failed: err = %d %s (%d)", > err, strerror( errno ), errno ); >+ free(responsebuf); > return spfrr; > } > >@@ -226,6 +276,7 @@ > if ( spf_dns_server->debug > 1 ) > SPF_debugf( "ns_parserr failed: err = %d %s (%d)", > err, strerror( errno ), errno ); >+ free(responsebuf); > return spfrr; > } > >@@ -257,8 +308,8 @@ > break; > > case ns_t_ns: >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress( responsebuf, >+ responsebuf + responselen, > rdata, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -271,8 +322,8 @@ > break; > > case ns_t_cname: >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress( responsebuf, >+ responsebuf + responselen, > rdata, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -286,8 +337,8 @@ > > case ns_t_mx: > prio = ns_get16( rdata ); >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress( responsebuf, >+ responsebuf + sizeof( responselen ), > rdata + NS_INT16SZ, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -300,14 +351,13 @@ > break; > > case ns_t_txt: >- rdata_end = rdata + rdlen; > SPF_debugf( "TXT: (%d) \"%.*s\"", > rdlen, rdlen-1, rdata+1 ); > break; > > case ns_t_ptr: >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress( responsebuf, >+ responsebuf + responselen, > rdata, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -341,18 +391,21 @@ > { > case ns_t_a: > if ( SPF_dns_rr_buf_realloc( spfrr, cnt, >- sizeof( spfrr->rr[cnt]->a ) ) != SPF_E_SUCCESS ) >+ sizeof(spfrr->rr[cnt]->a)) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >- memmove( &spfrr->rr[cnt]->a, rdata, sizeof( spfrr->rr[cnt]->a ) ); >+ } >+ memcpy(&spfrr->rr[cnt]->a, rdata, sizeof(spfrr->rr[cnt]->a)); > cnt++; > break; > > case ns_t_aaaa: > if ( SPF_dns_rr_buf_realloc( spfrr, cnt, >- sizeof( spfrr->rr[cnt]->aaaa ) ) != SPF_E_SUCCESS ) >+ sizeof(spfrr->rr[cnt]->aaaa)) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >- memmove( &spfrr->rr[cnt]->aaaa, rdata, sizeof( spfrr->rr[cnt]->aaaa ) ); >- >+ } >+ memcpy(&spfrr->rr[cnt]->aaaa, rdata, sizeof(spfrr->rr[cnt]->aaaa)); > cnt++; > break; > >@@ -364,8 +417,8 @@ > break; > > case ns_t_mx: >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress(responsebuf, >+ responsebuf + responselen, > rdata + NS_INT16SZ, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -373,12 +426,15 @@ > if ( spf_dns_server->debug > 1 ) > SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", > err, strerror( errno ), errno ); >+ free(responsebuf); > return spfrr; > } > > if ( SPF_dns_rr_buf_realloc( spfrr, cnt, >- strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) >+ strlen(name_buf) + 1 ) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >+ } > strcpy( spfrr->rr[cnt]->mx, name_buf ); > > cnt++; >@@ -390,8 +446,12 @@ > u_char *src, *dst; > size_t len; > >- if ( SPF_dns_rr_buf_realloc( spfrr, cnt, rdlen ) != SPF_E_SUCCESS ) >+ /* Just rdlen is enough because there is at least one >+ * length byte. */ >+ if (SPF_dns_rr_buf_realloc(spfrr, cnt, rdlen) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >+ } > > dst = (u_char *)(spfrr->rr[cnt]->txt); > len = 0; >@@ -400,15 +460,22 @@ > { > len = *src; > src++; >+ rdlen--; >+ >+ /* Avoid buffer overrun if len is junk. */ >+ if (len > rdlen) >+ len = rdlen; > memcpy( dst, src, len ); > dst += len; > src += len; >- rdlen -= len + 1; >+ rdlen -= len; > } > *dst = '\0'; > } else { >- if ( SPF_dns_rr_buf_realloc( spfrr, cnt, 1 ) != SPF_E_SUCCESS ) >+ if (SPF_dns_rr_buf_realloc(spfrr, cnt, 1) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >+ } > spfrr->rr[cnt]->txt[0] = '\0'; > } > >@@ -416,8 +483,8 @@ > break; > > case ns_t_ptr: >- err = ns_name_uncompress( response, >- response + sizeof( response ), >+ err = ns_name_uncompress(responsebuf, >+ responsebuf + responselen, > rdata, > name_buf, sizeof( name_buf ) ); > if ( err < 0 ) /* 0 or -1 */ >@@ -425,12 +492,15 @@ > if ( spf_dns_server->debug > 1 ) > SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", > err, strerror( errno ), errno ); >+ free(responsebuf); > return spfrr; > } > > if ( SPF_dns_rr_buf_realloc( spfrr, cnt, >- strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) >+ strlen(name_buf) + 1) != SPF_E_SUCCESS) { >+ free(responsebuf); > return spfrr; >+ } > strcpy( spfrr->rr[cnt]->ptr, name_buf ); > > cnt++; >@@ -447,6 +517,7 @@ > if ( spfrr->num_rr == 0 ) > spfrr->herrno = NO_DATA; > >+ free(responsebuf); > return spfrr; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 242254
: 168944