summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2022-10-19 22:58:33 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2022-10-19 22:58:33 +0100
commit5dda5a0e59f7d44615ab575f549af10166299f10 (patch)
tree1e8fea1afd46b11b587e38767b576674db1a505e
parentRevert rewrite resolver (diff)
downloadpatches-5dda5a0e59f7d44615ab575f549af10166299f10.tar.bz2
patches-5dda5a0e59f7d44615ab575f549af10166299f10.tar.xz
patches-5dda5a0e59f7d44615ab575f549af10166299f10.zip
Revert "Revert rewrite resolver"
This reverts commit 8140e5ab627796383abc93292d6bd66a09c5aac8.
-rw-r--r--sys-libs/glibc/revert-rewrite-resolver.patch576
1 files changed, 0 insertions, 576 deletions
diff --git a/sys-libs/glibc/revert-rewrite-resolver.patch b/sys-libs/glibc/revert-rewrite-resolver.patch
deleted file mode 100644
index 05fcb55..0000000
--- a/sys-libs/glibc/revert-rewrite-resolver.patch
+++ /dev/null
@@ -1,576 +0,0 @@
-reverted:
---- b/resolv/nss_dns/dns-host.c
-+++ a/resolv/nss_dns/dns-host.c
-@@ -100,6 +100,13 @@
- #endif
- #define MAXHOSTNAMELEN 256
-
-+/* We need this time later. */
-+typedef union querybuf
-+{
-+ HEADER hdr;
-+ u_char buf[MAXPACKET];
-+} querybuf;
-+
- /* For historic reasons, pointers to IP addresses are char *, so use a
- single list type for addresses and host names. */
- #define DYNARRAY_STRUCT ptrlist
-@@ -118,18 +125,18 @@
- char **hnamep, int *errnop,
- int *h_errnop, int32_t *ttlp);
-
-+static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
-+ const querybuf *answer2, int anslen2,
-+ const char *qname,
--static enum nss_status gaih_getanswer (unsigned char *packet1,
-- size_t packet1len,
-- unsigned char *packet2,
-- size_t packet2len,
-- struct alloc_buffer *abuf,
- struct gaih_addrtuple **pat,
-+ char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp);
-+static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1,
-+ int anslen1,
-+ const char *qname,
--static enum nss_status gaih_getanswer_noaaaa (unsigned char *packet,
-- size_t packetlen,
-- struct alloc_buffer *abuf,
- struct gaih_addrtuple **pat,
-+ char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp);
-
-@@ -401,13 +408,17 @@
- name = cp;
- }
-
-+ union
-+ {
-+ querybuf *buf;
-+ u_char *ptr;
-+ } host_buffer;
-+ querybuf *orig_host_buffer;
-+ host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
-- unsigned char dns_packet_buffer[2048];
-- unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
- u_char *ans2p = NULL;
- int nans2p = 0;
- int resplen2 = 0;
- int ans2p_malloced = 0;
-- struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
-
-
- int olderr = errno;
-@@ -416,21 +427,22 @@
- if ((ctx->resp->options & RES_NOAAAA) == 0)
- {
- n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
-+ host_buffer.buf->buf, 2048, &host_buffer.ptr,
-+ &ans2p, &nans2p, &resplen2, &ans2p_malloced);
-- dns_packet_buffer, sizeof (dns_packet_buffer),
-- &alt_dns_packet_buffer, &ans2p, &nans2p,
-- &resplen2, &ans2p_malloced);
- if (n >= 0)
-+ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
-+ resplen2, name, pat, buffer, buflen,
-+ errnop, herrnop, ttlp);
-- status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
-- &abuf, pat, errnop, herrnop, ttlp);
- }
- else
- {
- n = __res_context_search (ctx, name, C_IN, T_A,
-+ host_buffer.buf->buf, 2048, NULL,
-+ NULL, NULL, NULL, NULL);
-- dns_packet_buffer, sizeof (dns_packet_buffer),
-- NULL, NULL, NULL, NULL, NULL);
- if (n >= 0)
-+ status = gaih_getanswer_noaaaa (host_buffer.buf, n,
-+ name, pat, buffer, buflen,
-+ errnop, herrnop, ttlp);
-- status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
-- &abuf, pat, errnop, herrnop, ttlp);
- }
- if (n < 0)
- {
-@@ -461,20 +473,12 @@
- __set_errno (olderr);
- }
-
-- /* Implement the buffer resizing protocol. */
-- if (alloc_buffer_has_failed (&abuf))
-- {
-- *errnop = ERANGE;
-- *herrnop = NETDB_INTERNAL;
-- status = NSS_STATUS_TRYAGAIN;
-- }
--
- /* Check whether ans2p was separately allocated. */
- if (ans2p_malloced)
- free (ans2p);
-
-+ if (host_buffer.buf != orig_host_buffer)
-+ free (host_buffer.buf);
-- if (alt_dns_packet_buffer != dns_packet_buffer)
-- free (alt_dns_packet_buffer);
-
- __resolv_context_put (ctx);
- return status;
-@@ -888,152 +892,259 @@
- return NSS_STATUS_TRYAGAIN;
- }
-
--/* Parses DNS data found in PACKETLEN bytes at PACKET in struct
-- gaih_addrtuple address tuples. The new address tuples are linked
-- from **TAILP, with backing store allocated from ABUF, and *TAILP is
-- updated to point where the next tuple pointer should be stored. If
-- TTLP is not null, *TTLP is updated to reflect the minimum TTL. If
-- STORE_CANON is true, the canonical name is stored as part of the
-- first address tuple being written. */
- static enum nss_status
-+gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
-+ struct gaih_addrtuple ***patp,
-+ char **bufferp, size_t *buflenp,
-+ int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
--gaih_getanswer_slice (unsigned char *packet, size_t packetlen,
-- struct alloc_buffer *abuf,
-- struct gaih_addrtuple ***tailp,
-- int *errnop, int *h_errnop, int32_t *ttlp,
-- bool store_canon)
- {
-+ char *buffer = *bufferp;
-+ size_t buflen = *buflenp;
-+
-+ struct gaih_addrtuple **pat = *patp;
-+ const HEADER *hp = &answer->hdr;
-+ int ancount = ntohs (hp->ancount);
-+ int qdcount = ntohs (hp->qdcount);
-+ const u_char *cp = answer->buf + HFIXEDSZ;
-+ const u_char *end_of_message = answer->buf + anslen;
-+ if (__glibc_unlikely (qdcount != 1))
-+ {
-+ *h_errnop = NO_RECOVERY;
-+ return NSS_STATUS_UNAVAIL;
-+ }
-+
-+ u_char packtmp[NS_MAXCDNAME];
-+ int n = __ns_name_unpack (answer->buf, end_of_message, cp,
-+ packtmp, sizeof packtmp);
-+ /* We unpack the name to check it for validity. But we do not need
-+ it later. */
-+ if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
-+ {
-+ if (__glibc_unlikely (errno == EMSGSIZE))
-+ {
-+ too_small:
-+ *errnop = ERANGE;
-+ *h_errnop = NETDB_INTERNAL;
-+ return NSS_STATUS_TRYAGAIN;
-+ }
-+
-+ n = -1;
-+ }
-+
-+ if (__glibc_unlikely (n < 0))
-+ {
-+ *errnop = errno;
-+ *h_errnop = NO_RECOVERY;
-+ return NSS_STATUS_UNAVAIL;
-+ }
-+ if (__glibc_unlikely (__libc_res_hnok (buffer) == 0))
-- struct ns_rr_cursor c;
-- if (!__ns_rr_cursor_init (&c, packet, packetlen))
- {
-+ errno = EBADMSG;
-+ *errnop = EBADMSG;
-- /* This should not happen because __res_context_query already
-- perfroms response validation. */
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
- }
-+ cp += n + QFIXEDSZ;
-- bool haveanswer = false; /* Set to true if at least one address. */
-- uint16_t qtype = ns_rr_cursor_qtype (&c);
-- int ancount = ns_rr_cursor_ancount (&c);
-- const unsigned char *expected_name = ns_rr_cursor_qname (&c);
-- /* expected_name may be updated to point into this buffer. */
-- unsigned char name_buffer[NS_MAXCDNAME];
-
-+ int haveanswer = 0;
-+ int had_error = 0;
-+ char *canon = NULL;
-+ char *h_name = NULL;
-+ int h_namelen = 0;
-- /* This is a pointer to a possibly-compressed name in the packet.
-- Eventually it is equivalent to the canonical name. If needed, it
-- is uncompressed and translated to text form when the first
-- address tuple is encountered. */
-- const unsigned char *compressed_alias_name = expected_name;
-
-+ if (ancount == 0)
-- if (ancount == 0 || !__res_binary_hnok (compressed_alias_name))
- {
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
-
-+ while (ancount-- > 0 && cp < end_of_message && had_error == 0)
-- for (; ancount > -0; --ancount)
- {
-+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
-+ packtmp, sizeof packtmp);
-+ if (n != -1 &&
-+ (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
-+ {
-+ if (__glibc_unlikely (errno == EMSGSIZE))
-+ goto too_small;
-+
-+ n = -1;
-+ }
-+ if (__glibc_unlikely (n < 0))
-+ {
-+ ++had_error;
-+ continue;
-+ }
-+ if (*firstp && canon == NULL && __libc_res_hnok (buffer))
-+ {
-+ h_name = buffer;
-+ buffer += h_namelen;
-+ buflen -= h_namelen;
-+ }
-+
-+ cp += n; /* name */
-+
-+ if (__glibc_unlikely (cp + 10 > end_of_message))
-+ {
-+ ++had_error;
-+ continue;
-+ }
-+
-+ uint16_t type;
-+ NS_GET16 (type, cp);
-+ uint16_t class;
-+ NS_GET16 (class, cp);
-+ int32_t ttl;
-+ NS_GET32 (ttl, cp);
-+ NS_GET16 (n, cp); /* RDATA length. */
-+
-+ if (end_of_message - cp < n)
-- struct ns_rr_wire rr;
-- if (!__ns_rr_cursor_next (&c, &rr))
- {
-+ /* RDATA extends beyond the end of the packet. */
-+ ++had_error;
-+ continue;
-- *h_errnop = NO_RECOVERY;
-- return NSS_STATUS_UNAVAIL;
- }
-
-+ if (class != C_IN)
-+ {
-+ cp += n;
-+ continue;
-+ }
-- /* Update TTL for known record types. */
-- if ((rr.rtype == T_CNAME || rr.rtype == qtype)
-- && ttlp != NULL && *ttlp > rr.ttl)
-- *ttlp = rr.ttl;
-
-+ if (type == T_CNAME)
-- if (rr.rtype == T_CNAME)
- {
-+ char tbuf[MAXDNAME];
-+
-+ /* A CNAME could also have a TTL entry. */
-+ if (ttlp != NULL && ttl < *ttlp)
-+ *ttlp = ttl;
-+
-+ n = __libc_dn_expand (answer->buf, end_of_message, cp,
-+ tbuf, sizeof tbuf);
-+ if (__glibc_unlikely (n < 0))
-+ {
-+ ++had_error;
-+ continue;
-+ }
-+ cp += n;
-+
-+ if (*firstp && __libc_res_hnok (tbuf))
-- /* NB: No check for owner name match, based on historic
-- precedent. Record the CNAME target as the new expected
-- name. */
-- int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
-- name_buffer, sizeof (name_buffer));
-- if (n < 0)
- {
-+ /* Reclaim buffer space. */
-+ if (h_name + h_namelen == buffer)
-+ {
-+ buffer = h_name;
-+ buflen += h_namelen;
-+ }
-+
-+ n = strlen (tbuf) + 1;
-+ if (__glibc_unlikely (n > buflen))
-+ goto too_small;
-+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
-+ {
-+ ++had_error;
-+ continue;
-+ }
-+
-+ canon = buffer;
-+ buffer = __mempcpy (buffer, tbuf, n);
-+ buflen -= n;
-+ h_namelen = 0;
-- *h_errnop = NO_RECOVERY;
-- return NSS_STATUS_UNAVAIL;
- }
-+ continue;
-- expected_name = name_buffer;
-- if (store_canon && __res_binary_hnok (name_buffer))
-- /* This name can be used as a canonical name. Do not
-- translate to text form here to conserve buffer space.
-- Point to the compressed name because name_buffer can be
-- overwritten with an unusable name later. */
-- compressed_alias_name = rr.rdata;
- }
-+
-+ /* Stop parsing if we encounter a record with incorrect RDATA
-+ length. */
-+ if (type == T_A || type == T_AAAA)
-- else if (rr.rtype == qtype
-- && __ns_samebinaryname (rr.rname, expected_name)
-- && rr.rdlength == rrtype_to_rdata_length (qtype))
- {
-+ if (n != rrtype_to_rdata_length (type))
-- struct gaih_addrtuple *ntup
-- = alloc_buffer_alloc (abuf, struct gaih_addrtuple);
-- /* Delay error reporting to the callers (they implement the
-- ERANGE buffer resizing handshake). */
-- if (ntup != NULL)
- {
-+ ++had_error;
-+ continue;
-- ntup->next = NULL;
-- if (store_canon && compressed_alias_name != NULL)
-- {
-- /* This assumes that all the CNAME records come
-- first. Use MAXHOSTNAMELEN instead of
-- NS_MAXCDNAME for additional length checking.
-- However, these checks are not expected to fail
-- because all size NS_MAXCDNAME names should into
-- the hname buffer because no escaping is
-- needed. */
-- char unsigned nbuf[NS_MAXCDNAME];
-- char hname[MAXHOSTNAMELEN + 1];
-- if (__ns_name_unpack (c.begin, c.end,
-- compressed_alias_name,
-- nbuf, sizeof (nbuf)) >= 0
-- && __ns_name_ntop (nbuf, hname, sizeof (hname)) >= 0)
-- /* Space checking is performed by the callers. */
-- ntup->name = alloc_buffer_copy_string (abuf, hname);
-- store_canon = false;
-- }
-- else
-- ntup->name = NULL;
-- if (rr.rdlength == 4)
-- ntup->family = AF_INET;
-- else
-- ntup->family = AF_INET6;
-- memcpy (ntup->addr, rr.rdata, rr.rdlength);
-- ntup->scopeid = 0;
--
-- /* Link in the new tuple, and update the tail pointer to
-- point to its next field. */
-- **tailp = ntup;
-- *tailp = &ntup->next;
--
-- haveanswer = true;
- }
- }
-+ else
-+ {
-+ /* Skip unknown records. */
-+ cp += n;
-+ continue;
-+ }
-+
-+ assert (type == T_A || type == T_AAAA);
-+ if (*pat == NULL)
-+ {
-+ uintptr_t pad = (-(uintptr_t) buffer
-+ % __alignof__ (struct gaih_addrtuple));
-+ buffer += pad;
-+ buflen = buflen > pad ? buflen - pad : 0;
-+
-+ if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
-+ goto too_small;
-+
-+ *pat = (struct gaih_addrtuple *) buffer;
-+ buffer += sizeof (struct gaih_addrtuple);
-+ buflen -= sizeof (struct gaih_addrtuple);
-+ }
-+
-+ (*pat)->name = NULL;
-+ (*pat)->next = NULL;
-+
-+ if (*firstp)
-+ {
-+ /* We compose a single hostent out of the entire chain of
-+ entries, so the TTL of the hostent is essentially the lowest
-+ TTL in the chain. */
-+ if (ttlp != NULL && ttl < *ttlp)
-+ *ttlp = ttl;
-+
-+ (*pat)->name = canon ?: h_name;
-+
-+ *firstp = 0;
-+ }
-+
-+ (*pat)->family = type == T_A ? AF_INET : AF_INET6;
-+ memcpy ((*pat)->addr, cp, n);
-+ cp += n;
-+ (*pat)->scopeid = 0;
-+
-+ pat = &((*pat)->next);
-+
-+ haveanswer = 1;
- }
-
- if (haveanswer)
- {
-+ *patp = pat;
-+ *bufferp = buffer;
-+ *buflenp = buflen;
-+
- *h_errnop = NETDB_SUCCESS;
- return NSS_STATUS_SUCCESS;
- }
-+
-+ /* Special case here: if the resolver sent a result but it only
-+ contains a CNAME while we are looking for a T_A or T_AAAA record,
-+ we fail with NOTFOUND instead of TRYAGAIN. */
-+ if (canon != NULL)
-- else
- {
-- /* Special case here: if the resolver sent a result but it only
-- contains a CNAME while we are looking for a T_A or T_AAAA
-- record, we fail with NOTFOUND. */
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
-+
-+ *h_errnop = NETDB_INTERNAL;
-+ return NSS_STATUS_TRYAGAIN;
- }
-
-
- static enum nss_status
-+gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
-+ int anslen2, const char *qname,
-+ struct gaih_addrtuple **pat, char *buffer, size_t buflen,
--gaih_getanswer (unsigned char *packet1, size_t packet1len,
-- unsigned char *packet2, size_t packet2len,
-- struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
- int *errnop, int *h_errnop, int32_t *ttlp)
- {
-+ int first = 1;
-+
- enum nss_status status = NSS_STATUS_NOTFOUND;
-
- /* Combining the NSS status of two distinct queries requires some
-@@ -1045,10 +1156,7 @@
- between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
- A recoverable TRYAGAIN is almost always due to buffer size issues
- and returns ERANGE in errno and the caller is expected to retry
-+ with a larger buffer.
-- with a larger buffer. (The caller, _nss_dns_gethostbyname4_r,
-- ignores the return status if it detects that the result buffer
-- has been exhausted and generates a TRYAGAIN failure with an
-- ERANGE code.)
-
- Lastly, you may be tempted to make significant changes to the
- conditions in this code to bring about symmetry between responses.
-@@ -1128,30 +1236,36 @@
- is a recoverable error we now return TRYAGIN even if the first
- response was SUCCESS. */
-
-+ if (anslen1 > 0)
-+ status = gaih_getanswer_slice(answer1, anslen1, qname,
-+ &pat, &buffer, &buflen,
-+ errnop, h_errnop, ttlp,
-+ &first);
-+
-+ if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
-+ || (status == NSS_STATUS_TRYAGAIN
-+ /* We want to look at the second answer in case of an
-+ NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
-+ *h_errnop is NO_RECOVERY. If not, and if the failure was due to
-+ an insufficient buffer (ERANGE), then we need to drop the results
-+ and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
-+ repeat the query with a larger buffer. */
-+ && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
-+ && answer2 != NULL && anslen2 > 0)
-- if (packet1len > 0)
- {
-+ enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
-+ &pat, &buffer, &buflen,
-+ errnop, h_errnop, ttlp,
-+ &first);
-- status = gaih_getanswer_slice (packet1, packet1len,
-- abuf, &pat, errnop, h_errnop, ttlp, true);
-- if (alloc_buffer_has_failed (abuf))
-- /* Do not try parsing the second packet if a larger result
-- buffer is needed. The caller implements the resizing
-- protocol because *abuf has been exhausted. */
-- return NSS_STATUS_TRYAGAIN; /* Ignored by the caller. */
-- }
--
-- if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
-- && packet2 != NULL && packet2len > 0)
-- {
-- enum nss_status status2
-- = gaih_getanswer_slice (packet2, packet2len,
-- abuf, &pat, errnop, h_errnop, ttlp,
-- /* Success means that data with a
-- canonical name has already been
-- stored. Do not store the name again. */
-- status != NSS_STATUS_SUCCESS);
- /* Use the second response status in some cases. */
- if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
- status = status2;
-+ /* Do not return a truncated second response (unless it was
-+ unavoidable e.g. unrecoverable TRYAGAIN). */
-+ if (status == NSS_STATUS_SUCCESS
-+ && (status2 == NSS_STATUS_TRYAGAIN
-+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
-+ status = NSS_STATUS_TRYAGAIN;
- }
-
- return status;
-@@ -1159,13 +1273,18 @@
-
- /* Variant of gaih_getanswer without a second (AAAA) response. */
- static enum nss_status
-+gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname,
-+ struct gaih_addrtuple **pat,
-+ char *buffer, size_t buflen,
--gaih_getanswer_noaaaa (unsigned char *packet, size_t packetlen,
-- struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
- int *errnop, int *h_errnop, int32_t *ttlp)
- {
-+ int first = 1;
-+
- enum nss_status status = NSS_STATUS_NOTFOUND;
-+ if (anslen1 > 0)
-+ status = gaih_getanswer_slice (answer1, anslen1, qname,
-+ &pat, &buffer, &buflen,
-+ errnop, h_errnop, ttlp,
-+ &first);
-- if (packetlen > 0)
-- status = gaih_getanswer_slice (packet, packetlen,
-- abuf, &pat, errnop, h_errnop, ttlp, true);
- return status;
- }