RosaLinux Bugzilla – Attachment 5971 Details for
Bug 13848
[CVE 21] glibc 2.33 CVEs found
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
CVE-2023-4527
CVE-2023-4527.patch (text/plain), 38.08 KB, created by
Aleksandr Proklov
on 2023-10-27 06:29:08 MSK
(
hide
)
Description:
CVE-2023-4527
Filename:
MIME Type:
Creator:
Aleksandr Proklov
Created:
2023-10-27 06:29:08 MSK
Size:
38.08 KB
patch
obsolete
># from https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=f282cdbe7f436c75864e5640a4;hp=62a321b12d0e397af88fa422db65079332f971dc ># https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bd77dd7e73e3530203be1c52c8a29d08270cb25d;hp=c8fa383f4cec9cf1c0cc8ec97903c09af10286f4 > >diff -ruN a/resolv/Makefile b/resolv/Makefile >--- a/resolv/Makefile 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/Makefile 2023-10-27 11:06:33.257096668 +0900 >@@ -28,7 +28,7 @@ > sys/bitypes.h > > routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ >- res_hconf res_libc res-state res_randomid res-close \ >+ res_hconf res_libc res-noaaaa res-state res_randomid res-close \ > resolv_context resolv_conf > > tests = tst-aton tst-leaks tst-inet_ntop >@@ -56,6 +56,8 @@ > tst-resolv-binary \ > tst-resolv-edns \ > tst-resolv-network \ >+ tst-resolv-noaaaa \ >+ tst-resolv-noaaaa-vc \ > tst-resolv-nondecimal \ > tst-resolv-res_init-multi \ > tst-resolv-search \ >@@ -190,6 +192,8 @@ > $(shared-thread-library) > $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ > $(shared-thread-library) >+$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) >+$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library) > $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) > $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) > $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) >diff -ruN a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c >--- a/resolv/nss_dns/dns-host.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/nss_dns/dns-host.c 2023-10-27 11:09:59.348051859 +0900 >@@ -127,6 +127,14 @@ > int *errnop, int *h_errnop, > int32_t *ttlp); > >+static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1, >+ int anslen1, >+ const char *qname, >+ struct gaih_addrtuple **pat, >+ char *buffer, size_t buflen, >+ int *errnop, int *h_errnop, >+ int32_t *ttlp); >+ > static enum nss_status gethostbyname3_context (struct resolv_context *ctx, > const char *name, int af, > struct hostent *result, >@@ -253,7 +261,7 @@ > if (af == AF_INET6 && res_use_inet6 ()) > n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf, > host_buffer.buf != orig_host_buffer >- ? MAXPACKET : 1024, &host_buffer.ptr, >+ ? MAXPACKET : 1024, &alt_dns_packet_buffer, > NULL, NULL, NULL, NULL); > > if (n < 0) >@@ -371,17 +379,30 @@ > int ans2p_malloced = 0; > > int olderr = errno; >- int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, >+ int n; >+ >+ 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); >- if (n >= 0) >- { >- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, >- resplen2, name, pat, buffer, buflen, >- errnop, herrnop, ttlp); >+ if (n >= 0) >+ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, >+ resplen2, name, pat, buffer, buflen, >+ errnop, herrnop, ttlp); > } > else > { >+ n = __res_context_search (ctx, name, C_IN, T_A, >+ host_buffer.buf->buf, 2048, NULL, >+ NULL, NULL, NULL, NULL); >+ if (n >= 0) >+ status = gaih_getanswer_noaaaa (host_buffer.buf, n, >+ name, pat, buffer, buflen, >+ errnop, herrnop, ttlp); >+ } >+ if (n < 0) >+ { > switch (errno) > { > case ESRCH: >@@ -1396,3 +1417,21 @@ > > return status; > } >+ >+/* 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, >+ 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); >+ return status; >+} >diff -ruN a/resolv/res_debug.c b/resolv/res_debug.c >--- a/resolv/res_debug.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/res_debug.c 2023-10-27 11:13:27.250116768 +0900 >@@ -613,6 +613,7 @@ > case RES_NOTLDQUERY: return "no-tld-query"; > case RES_NORELOAD: return "no-reload"; > case RES_TRUSTAD: return "trust-ad"; >+ case RES_NOAAAA: return "no-aaaa"; > /* XXX nonreentrant */ > default: sprintf(nbuf, "?0x%lx?", (u_long)option); > return (nbuf); >diff -ruN a/resolv/res_init.c b/resolv/res_init.c >--- a/resolv/res_init.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/res_init.c 2023-10-27 11:13:55.591362390 +0900 >@@ -695,6 +695,7 @@ > { STRnLEN ("no-reload"), 0, RES_NORELOAD }, > { STRnLEN ("use-vc"), 0, RES_USEVC }, > { STRnLEN ("trust-ad"), 0, RES_TRUSTAD }, >+ { STRnLEN ("no-aaaa"), 0, RES_NOAAAA }, > }; > #define noptions (sizeof (options) / sizeof (options[0])) > for (int i = 0; i < noptions; ++i) >diff -ruN a/resolv/res-noaaaa.c b/resolv/res-noaaaa.c >--- a/resolv/res-noaaaa.c 1970-01-01 09:00:00.000000000 +0900 >+++ b/resolv/res-noaaaa.c 2023-10-27 11:12:03.348440000 +0900 >@@ -0,0 +1,143 @@ >+/* Implement suppression of AAAA queries. >+ Copyright (C) 2022 Free Software Foundation, Inc. >+ This file is part of the GNU C Library. >+ >+ The GNU C Library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Lesser General Public >+ License as published by the Free Software Foundation; either >+ version 2.1 of the License, or (at your option) any later version. >+ >+ The GNU C Library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Lesser General Public License for more details. >+ >+ You should have received a copy of the GNU Lesser General Public >+ License along with the GNU C Library; if not, see >+ <https://www.gnu.org/licenses/>. */ >+ >+#include <resolv.h> >+#include <string.h> >+#include <resolv-internal.h> >+#include <resolv_context.h> >+#include <arpa/nameser.h> >+ >+/* Returns true if the question type at P matches EXPECTED, and the >+ class is IN. */ >+static bool >+qtype_matches (const unsigned char *p, int expected) >+{ >+ /* This assumes that T_A/C_IN constants are less than 256, which >+ they are. */ >+ return p[0] == 0 && p[1] == expected && p[2] == 0 && p[3] == C_IN; >+} >+ >+/* Handle RES_NOAAAA translation of AAAA queries. To produce a Name >+ Error (NXDOMAIN) repsonse for domain names that do not exist, it is >+ still necessary to send a query. Using question type A is a >+ conservative choice. In the returned answer, it is necessary to >+ switch back the question type to AAAA. */ >+bool >+__res_handle_no_aaaa (struct resolv_context *ctx, >+ const unsigned char *buf, int buflen, >+ unsigned char *ans, int anssiz, int *result) >+{ >+ /* AAAA mode is not active, or the query looks invalid (will not be >+ able to be parsed). */ >+ if ((ctx->resp->options & RES_NOAAAA) == 0 >+ || buflen <= sizeof (HEADER)) >+ return false; >+ >+ /* The replacement A query is produced here. */ >+ struct >+ { >+ HEADER header; >+ unsigned char question[NS_MAXCDNAME + 4]; >+ } replacement; >+ memcpy (&replacement.header, buf, sizeof (replacement.header)); >+ >+ if (replacement.header.qr >+ || replacement.header.opcode != 0 >+ || replacement.header.rcode != 0 >+ || ntohs (replacement.header.qdcount) != 1 >+ || ntohs (replacement.header.ancount) != 0 >+ || ntohs (replacement.header.nscount) != 0) >+ /* Not a well-formed question. Let the core resolver code produce >+ the proper error. */ >+ return false; >+ >+ /* Disable EDNS0. */ >+ replacement.header.arcount = htons (0); >+ >+ /* Extract the QNAME. */ >+ int ret = __ns_name_unpack (buf, buf + buflen, buf + sizeof (HEADER), >+ replacement.question, NS_MAXCDNAME); >+ if (ret < 0) >+ /* Format error. */ >+ return false; >+ >+ /* Compute the end of the question name. */ >+ const unsigned char *after_question = buf + sizeof (HEADER) + ret; >+ >+ /* Check that we are dealing with an AAAA query. */ >+ if (buf + buflen - after_question < 4 >+ || !qtype_matches (after_question, T_AAAA)) >+ return false; >+ >+ /* Find the place to store the type/class data in the replacement >+ query. */ >+ after_question = replacement.question; >+ /* This cannot fail because __ns_name_unpack above produced a valid >+ domain name. */ >+ (void) __ns_name_skip (&after_question, &replacement.question[NS_MAXCDNAME]); >+ unsigned char *start_of_query = (unsigned char *) &replacement; >+ const unsigned char *end_of_query = after_question + 4; >+ >+ /* Produce an A/IN query. */ >+ { >+ unsigned char *p = (unsigned char *) after_question; >+ p[0] = 0; >+ p[1] = T_A; >+ p[2] = 0; >+ p[3] = C_IN; >+ } >+ >+ /* Clear the output buffer, to avoid reading undefined data when >+ rewriting the result from A to AAAA. */ >+ memset (ans, 0, anssiz); >+ >+ /* Always perform the message translation, independent of the error >+ code. */ >+ ret = __res_context_send (ctx, >+ start_of_query, end_of_query - start_of_query, >+ NULL, 0, ans, anssiz, >+ NULL, NULL, NULL, NULL, NULL); >+ >+ /* Patch in the AAAA question type if there is room and the A query >+ type was received. */ >+ after_question = ans + sizeof (HEADER); >+ if (__ns_name_skip (&after_question, ans + anssiz) == 0 >+ && ans + anssiz - after_question >= 4 >+ && qtype_matches (after_question, T_A)) >+ { >+ ((unsigned char *) after_question)[1] = T_AAAA; >+ >+ /* Create an aligned copy of the header. Hide all data except >+ the question from the response. Put back the header. There is >+ no need to change the response code. The zero answer count turns >+ a positive response with data into a no-data response. */ >+ memcpy (&replacement.header, ans, sizeof (replacement.header)); >+ replacement.header.ancount = htons (0); >+ replacement.header.nscount = htons (0); >+ replacement.header.arcount = htons (0); >+ memcpy (ans, &replacement.header, sizeof (replacement.header)); >+ >+ /* Truncate the reply. */ >+ if (ret <= 0) >+ *result = ret; >+ else >+ *result = after_question - ans + 4; >+ } >+ >+ return true; >+} >diff -ruN a/resolv/resolv.h b/resolv/resolv.h >--- a/resolv/resolv.h 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/resolv.h 2023-10-27 11:16:45.449827810 +0900 >@@ -132,6 +132,7 @@ > as a TLD. */ > #define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */ > #define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */ >+#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */ > > #define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) > >diff -ruN a/resolv/resolv-internal.h b/resolv/resolv-internal.h >--- a/resolv/resolv-internal.h 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/resolv-internal.h 2023-10-27 11:16:17.148583947 +0900 >@@ -76,6 +76,14 @@ > int, unsigned char **, unsigned char **, > int *, int *, int *) attribute_hidden; > >+/* Return true if the query has been handled in RES_NOAAAA mode. For >+ that, RES_NOAAAA must be active, and the question type must be AAAA. >+ The caller is expected to return *RESULT as the return value. */ >+bool __res_handle_no_aaaa (struct resolv_context *ctx, >+ const unsigned char *buf, int buflen, >+ unsigned char *ans, int anssiz, int *result) >+ attribute_hidden; >+ > /* Internal function similar to res_hostalias. */ > const char *__res_context_hostalias (struct resolv_context *, > const char *, char *, size_t); >diff -ruN a/resolv/res_query.c b/resolv/res_query.c >--- a/resolv/res_query.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/res_query.c 2023-10-27 11:14:34.531073822 +0900 >@@ -204,10 +204,26 @@ > free (buf); > return (n); > } >- assert (answerp == NULL || (void *) *answerp == (void *) answer); >- n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer, >- anslen, answerp, answerp2, nanswerp2, resplen2, >- answerp2_malloced); >+ >+ /* Suppress AAAA lookups if required. __res_handle_no_aaaa >+ checks RES_NOAAAA first, so avoids parsing the >+ just-generated query packet in most cases. nss_dns avoids >+ using T_QUERY_A_AND_AAAA in RES_NOAAAA mode, so there is no >+ need to handle it here. */ >+ if (type == T_AAAA && __res_handle_no_aaaa (ctx, query1, nquery1, >+ answer, anslen, &n)) >+ /* There must be no second query for AAAA queries. The code >+ below is still needed to translate NODATA responses. */ >+ assert (query2 == NULL); >+ else >+ { >+ assert (answerp == NULL || (void *) *answerp == (void *) answer); >+ n = __res_context_send (ctx, query1, nquery1, query2, nquery2, >+ answer, anslen, >+ answerp, answerp2, nanswerp2, resplen2, >+ answerp2_malloced); >+ } >+ > if (use_malloc) > free (buf); > if (n < 0) { >diff -ruN a/resolv/res_send.c b/resolv/res_send.c >--- a/resolv/res_send.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/res_send.c 2023-10-27 11:15:23.625231551 +0900 >@@ -585,8 +585,13 @@ > RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); > return -1; > } >- int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, >- NULL, NULL, NULL, NULL, NULL); >+ >+ int result; >+ if (__res_handle_no_aaaa (ctx, buf, buflen, ans, anssiz, &result)) >+ return result; >+ >+ result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, >+ NULL, NULL, NULL, NULL, NULL); > __resolv_context_put (ctx); > return result; > } >diff -ruN a/resolv/tst-resolv-noaaaa.c b/resolv/tst-resolv-noaaaa.c >--- a/resolv/tst-resolv-noaaaa.c 1970-01-01 09:00:00.000000000 +0900 >+++ b/resolv/tst-resolv-noaaaa.c 2023-10-27 11:18:52.618416975 +0900 >@@ -0,0 +1,533 @@ >+/* Test the RES_NOAAAA resolver option. >+ Copyright (C) 2022 Free Software Foundation, Inc. >+ This file is part of the GNU C Library. >+ >+ The GNU C Library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Lesser General Public >+ License as published by the Free Software Foundation; either >+ version 2.1 of the License, or (at your option) any later version. >+ >+ The GNU C Library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Lesser General Public License for more details. >+ >+ You should have received a copy of the GNU Lesser General Public >+ License along with the GNU C Library; if not, see >+ <https://www.gnu.org/licenses/>. */ >+ >+#include <errno.h> >+#include <netdb.h> >+#include <resolv.h> >+#include <stdlib.h> >+#include <support/check.h> >+#include <support/check_nss.h> >+#include <support/resolv_test.h> >+#include <support/support.h> >+ >+/* Used to keep track of the number of queries. */ >+static volatile unsigned int queries; >+ >+static void >+response (const struct resolv_response_context *ctx, >+ struct resolv_response_builder *b, >+ const char *qname, uint16_t qclass, uint16_t qtype) >+{ >+ /* Each test should only send one query. */ >+ ++queries; >+ TEST_COMPARE (queries, 1); >+ >+ /* AAAA queries are supposed to be disabled. */ >+ TEST_VERIFY (qtype != T_AAAA); >+ TEST_COMPARE (qclass, C_IN); >+ >+ /* The only other query type besides A is PTR. */ >+ if (qtype != T_A) >+ TEST_COMPARE (qtype, T_PTR); >+ >+ int an, ns, ar; >+ char *tail; >+ if (sscanf (qname, "an%d.ns%d.ar%d.%ms", &an, &ns, &ar, &tail) != 4) >+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname); >+ TEST_COMPARE_STRING (tail, "example"); >+ free (tail); >+ >+ if (an < 0 || ns < 0 || ar < 0) >+ { >+ struct resolv_response_flags flags = { .rcode = NXDOMAIN, }; >+ resolv_response_init (b, flags); >+ resolv_response_add_question (b, qname, qclass, qtype); >+ return; >+ } >+ >+ struct resolv_response_flags flags = {}; >+ resolv_response_init (b, flags); >+ resolv_response_add_question (b, qname, qclass, qtype); >+ >+ resolv_response_section (b, ns_s_an); >+ for (int i = 0; i < an; ++i) >+ { >+ resolv_response_open_record (b, qname, qclass, qtype, 60); >+ switch (qtype) >+ { >+ case T_A: >+ char ipv4[4] = {192, 0, 2, i + 1}; >+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); >+ break; >+ >+ case T_PTR: >+ char *name = xasprintf ("ptr-%d", i); >+ resolv_response_add_name (b, name); >+ free (name); >+ break; >+ } >+ resolv_response_close_record (b); >+ } >+ >+ resolv_response_section (b, ns_s_ns); >+ for (int i = 0; i < ns; ++i) >+ { >+ resolv_response_open_record (b, qname, qclass, T_NS, 60); >+ char *name = xasprintf ("ns%d.example.net", i); >+ resolv_response_add_name (b, name); >+ free (name); >+ resolv_response_close_record (b); >+ } >+ >+ resolv_response_section (b, ns_s_ar); >+ int addr = 1; >+ for (int i = 0; i < ns; ++i) >+ { >+ char *name = xasprintf ("ns%d.example.net", i); >+ for (int j = 0; j < ar; ++j) >+ { >+ resolv_response_open_record (b, name, qclass, T_A, 60); >+ char ipv4[4] = {192, 0, 2, addr}; >+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); >+ resolv_response_close_record (b); >+ >+ resolv_response_open_record (b, name, qclass, T_AAAA, 60); >+ char ipv6[16] >+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr}; >+ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); >+ resolv_response_close_record (b); >+ >+ ++addr; >+ } >+ free (name); >+ } >+} >+ >+/* Number of modes. Lowest bit encodes *n* function vs implicit _res >+ argument. The mode numbers themselves are arbitrary. */ >+enum { mode_count = 8 }; >+ >+/* res_send-like modes do not perform error translation. */ >+enum { first_send_mode = 6 }; >+ >+static int >+libresolv_query (unsigned int mode, const char *qname, uint16_t qtype, >+ unsigned char *buf, size_t buflen) >+{ >+ int saved_errno = errno; >+ >+ TEST_VERIFY_EXIT (mode < mode_count); >+ >+ switch (mode) >+ { >+ case 0: >+ return res_query (qname, C_IN, qtype, buf, buflen); >+ case 1: >+ return res_nquery (&_res, qname, C_IN, qtype, buf, buflen); >+ case 2: >+ return res_search (qname, C_IN, qtype, buf, buflen); >+ case 3: >+ return res_nsearch (&_res, qname, C_IN, qtype, buf, buflen); >+ case 4: >+ return res_querydomain (qname, "", C_IN, qtype, buf, buflen); >+ case 5: >+ return res_nquerydomain (&_res, qname, "", C_IN, qtype, buf, buflen); >+ case 6: >+ { >+ unsigned char querybuf[512]; >+ int ret = res_mkquery (QUERY, qname, C_IN, qtype, >+ NULL, 0, NULL, querybuf, sizeof (querybuf)); >+ TEST_VERIFY_EXIT (ret > 0); >+ errno = saved_errno; >+ return res_send (querybuf, ret, buf, buflen); >+ } >+ case 7: >+ { >+ unsigned char querybuf[512]; >+ int ret = res_nmkquery (&_res, QUERY, qname, C_IN, qtype, >+ NULL, 0, NULL, querybuf, sizeof (querybuf)); >+ TEST_VERIFY_EXIT (ret > 0); >+ errno = saved_errno; >+ return res_nsend (&_res, querybuf, ret, buf, buflen); >+ } >+ } >+ __builtin_unreachable (); >+} >+ >+static int >+do_test (void) >+{ >+ struct resolv_test *obj = resolv_test_start >+ ((struct resolv_redirect_config) >+ { >+ .response_callback = response >+ }); >+ >+ _res.options |= RES_NOAAAA; >+ >+ check_hostent ("an1.ns2.ar1.example", >+ gethostbyname ("an1.ns2.ar1.example"), >+ "name: an1.ns2.ar1.example\n" >+ "address: 192.0.2.1\n"); >+ queries = 0; >+ check_hostent ("an0.ns2.ar1.example", >+ gethostbyname ("an0.ns2.ar1.example"), >+ "error: NO_ADDRESS\n"); >+ queries = 0; >+ check_hostent ("an-1.ns2.ar1.example", >+ gethostbyname ("an-1.ns2.ar1.example"), >+ "error: HOST_NOT_FOUND\n"); >+ queries = 0; >+ >+ check_hostent ("an1.ns2.ar1.example AF_INET", >+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET), >+ "name: an1.ns2.ar1.example\n" >+ "address: 192.0.2.1\n"); >+ queries = 0; >+ check_hostent ("an0.ns2.ar1.example AF_INET", >+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET), >+ "error: NO_ADDRESS\n"); >+ queries = 0; >+ check_hostent ("an-1.ns2.ar1.example AF_INET", >+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET), >+ "error: HOST_NOT_FOUND\n"); >+ queries = 0; >+ >+ check_hostent ("an1.ns2.ar1.example AF_INET6", >+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET6), >+ "error: NO_ADDRESS\n"); >+ queries = 0; >+ check_hostent ("an0.ns2.ar1.example AF_INET6", >+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET6), >+ "error: NO_ADDRESS\n"); >+ queries = 0; >+ check_hostent ("an-1.ns2.ar1.example AF_INET6", >+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET6), >+ "error: HOST_NOT_FOUND\n"); >+ queries = 0; >+ >+ /* Multiple addresses. */ >+ check_hostent ("an2.ns0.ar0.example", >+ gethostbyname ("an2.ns0.ar0.example"), >+ "name: an2.ns0.ar0.example\n" >+ "address: 192.0.2.1\n" >+ "address: 192.0.2.2\n"); >+ queries = 0; >+ check_hostent ("an2.ns0.ar0.example AF_INET6", >+ gethostbyname2 ("an2.ns0.ar0.example", AF_INET6), >+ "error: NO_ADDRESS\n"); >+ queries = 0; >+ >+ /* getaddrinfo checks with one address. */ >+ struct addrinfo *ai; >+ int ret; >+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai, ret, >+ "address: STREAM/TCP 192.0.2.1 80\n"); >+ freeaddrinfo (ai); >+ queries = 0; >+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET6, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai, ret, >+ "error: No address associated with hostname\n"); >+ queries = 0; >+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_UNSPEC, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC)", ai, ret, >+ "address: STREAM/TCP 192.0.2.1 80\n"); >+ freeaddrinfo (ai); >+ queries = 0; >+ >+ /* getaddrinfo checks with three addresses. */ >+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai, ret, >+ "address: STREAM/TCP 192.0.2.1 80\n" >+ "address: STREAM/TCP 192.0.2.2 80\n" >+ "address: STREAM/TCP 192.0.2.3 80\n"); >+ freeaddrinfo (ai); >+ queries = 0; >+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET6, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai, ret, >+ "error: No address associated with hostname\n"); >+ queries = 0; >+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_UNSPEC, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC)", ai, ret, >+ "address: STREAM/TCP 192.0.2.1 80\n" >+ "address: STREAM/TCP 192.0.2.2 80\n" >+ "address: STREAM/TCP 192.0.2.3 80\n"); >+ freeaddrinfo (ai); >+ queries = 0; >+ >+ /* getaddrinfo checks with no address. */ >+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai, ret, >+ "error: No address associated with hostname\n"); >+ queries = 0; >+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET6, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai, ret, >+ "error: No address associated with hostname\n"); >+ queries = 0; >+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_UNSPEC, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, >+ "error: No address associated with hostname\n"); >+ queries = 0; >+ >+ /* getaddrinfo checks with NXDOMAIN. */ >+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai, ret, >+ "error: Name or service not known\n"); >+ queries = 0; >+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_INET6, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai, ret, >+ "error: Name or service not known\n"); >+ queries = 0; >+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_UNSPEC, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, >+ "error: Name or service not known\n"); >+ queries = 0; >+ >+ for (unsigned int mode = 0; mode < mode_count; ++mode) >+ { >+ unsigned char *buf; >+ int ret; >+ >+ /* Response for A. */ >+ buf = malloc (512); >+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_A, buf, 512); >+ TEST_VERIFY_EXIT (ret > 0); >+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, >+ "name: an1.ns2.ar1.example\n" >+ "address: 192.0.2.1\n"); >+ free (buf); >+ queries = 0; >+ >+ /* NODATA response for A. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_A, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, NO_ADDRESS); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); >+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, >+ "name: an0.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* NXDOMAIN response for A. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_A, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); >+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, >+ "name: an-1.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* Response for PTR. */ >+ buf = malloc (512); >+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_PTR, buf, 512); >+ TEST_VERIFY_EXIT (ret > 0); >+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, >+ "name: an1.ns2.ar1.example\n" >+ "data: an1.ns2.ar1.example PTR ptr-0\n"); >+ free (buf); >+ queries = 0; >+ >+ /* NODATA response for PTR. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_PTR, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, NO_ADDRESS); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); >+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, >+ "name: an0.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* NXDOMAIN response for PTR. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_PTR, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); >+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, >+ "name: an-1.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* NODATA response for AAAA. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_AAAA, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, NO_ADDRESS); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); >+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, >+ "name: an1.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* NODATA response for AAAA (original is already NODATA). */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_AAAA, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, NO_ADDRESS); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); >+ check_dns_packet ("an0.ns2.ar1.example A", buf, ret, >+ "name: an0.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ >+ /* NXDOMAIN response. */ >+ buf = malloc (512); >+ errno = 0; >+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_AAAA, buf, 512); >+ if (mode < first_send_mode) >+ { >+ TEST_COMPARE (ret, -1); >+ TEST_COMPARE (errno, 0); >+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); >+ } >+ else >+ { >+ TEST_VERIFY_EXIT (ret > 0); >+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); >+ check_dns_packet ("an-1.ns2.ar1.example A", buf, ret, >+ "name: an-1.ns2.ar1.example\n"); >+ } >+ free (buf); >+ queries = 0; >+ } >+ >+ resolv_test_end (obj); >+ >+ return 0; >+} >+ >+#include <support/test-driver.c> >diff -ruN a/resolv/tst-resolv-noaaaa-vc.c b/resolv/tst-resolv-noaaaa-vc.c >--- a/resolv/tst-resolv-noaaaa-vc.c 1970-01-01 09:00:00.000000000 +0900 >+++ b/resolv/tst-resolv-noaaaa-vc.c 2023-10-27 11:12:13.620886365 +0900 >@@ -0,0 +1,129 @@ >+/* Test the RES_NOAAAA resolver option with a large response. >+ Copyright (C) 2022-2023 Free Software Foundation, Inc. >+ This file is part of the GNU C Library. >+ >+ The GNU C Library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Lesser General Public >+ License as published by the Free Software Foundation; either >+ version 2.1 of the License, or (at your option) any later version. >+ >+ The GNU C Library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Lesser General Public License for more details. >+ >+ You should have received a copy of the GNU Lesser General Public >+ License along with the GNU C Library; if not, see >+ <https://www.gnu.org/licenses/>. */ >+ >+#include <errno.h> >+#include <netdb.h> >+#include <resolv.h> >+#include <stdbool.h> >+#include <stdlib.h> >+#include <support/check.h> >+#include <support/check_nss.h> >+#include <support/resolv_test.h> >+#include <support/support.h> >+#include <support/xmemstream.h> >+ >+/* Used to keep track of the number of queries. */ >+static volatile unsigned int queries; >+ >+/* If true, add a large TXT record at the start of the answer section. */ >+static volatile bool stuff_txt; >+ >+static void >+response (const struct resolv_response_context *ctx, >+ struct resolv_response_builder *b, >+ const char *qname, uint16_t qclass, uint16_t qtype) >+{ >+ /* If not using TCP, just force its use. */ >+ if (!ctx->tcp) >+ { >+ struct resolv_response_flags flags = {.tc = true}; >+ resolv_response_init (b, flags); >+ resolv_response_add_question (b, qname, qclass, qtype); >+ return; >+ } >+ >+ /* The test needs to send four queries, the first three are used to >+ grow the NSS buffer via the ERANGE handshake. */ >+ ++queries; >+ TEST_VERIFY (queries <= 4); >+ >+ /* AAAA queries are supposed to be disabled. */ >+ TEST_COMPARE (qtype, T_A); >+ TEST_COMPARE (qclass, C_IN); >+ TEST_COMPARE_STRING (qname, "example.com"); >+ >+ struct resolv_response_flags flags = {}; >+ resolv_response_init (b, flags); >+ resolv_response_add_question (b, qname, qclass, qtype); >+ >+ resolv_response_section (b, ns_s_an); >+ >+ if (stuff_txt) >+ { >+ resolv_response_open_record (b, qname, qclass, T_TXT, 60); >+ int zero = 0; >+ for (int i = 0; i <= 15000; ++i) >+ resolv_response_add_data (b, &zero, sizeof (zero)); >+ resolv_response_close_record (b); >+ } >+ >+ for (int i = 0; i < 200; ++i) >+ { >+ resolv_response_open_record (b, qname, qclass, qtype, 60); >+ char ipv4[4] = {192, 0, 2, i + 1}; >+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); >+ resolv_response_close_record (b); >+ } >+} >+ >+static int >+do_test (void) >+{ >+ struct resolv_test *obj = resolv_test_start >+ ((struct resolv_redirect_config) >+ { >+ .response_callback = response >+ }); >+ >+ _res.options |= RES_NOAAAA; >+ >+ for (int do_stuff_txt = 0; do_stuff_txt < 2; ++do_stuff_txt) >+ { >+ queries = 0; >+ stuff_txt = do_stuff_txt; >+ >+ struct addrinfo *ai = NULL; >+ int ret; >+ ret = getaddrinfo ("example.com", "80", >+ &(struct addrinfo) >+ { >+ .ai_family = AF_UNSPEC, >+ .ai_socktype = SOCK_STREAM, >+ }, &ai); >+ >+ char *expected_result; >+ { >+ struct xmemstream mem; >+ xopen_memstream (&mem); >+ for (int i = 0; i < 200; ++i) >+ fprintf (mem.out, "address: STREAM/TCP 192.0.2.%d 80\n", i + 1); >+ xfclose_memstream (&mem); >+ expected_result = mem.buffer; >+ } >+ >+ check_addrinfo ("example.com", ai, ret, expected_result); >+ >+ free (expected_result); >+ freeaddrinfo (ai); >+ } >+ >+ resolv_test_end (obj); >+ return 0; >+} >+ >+#include <support/test-driver.c> >diff -ruN a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c >--- a/resolv/tst-resolv-res_init-skeleton.c 2021-02-02 02:15:33.000000000 +0900 >+++ b/resolv/tst-resolv-res_init-skeleton.c 2023-10-27 11:19:53.153077524 +0900 >@@ -128,6 +128,7 @@ > print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query"); > print_option_flag (fp, &options, RES_NORELOAD, "no-reload"); > print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad"); >+ print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa"); > fputc ('\n', fp); > if (options != 0) > fprintf (fp, "; error: unresolved option bits: 0x%x\n", options); >@@ -719,6 +720,15 @@ > "search example.com\n" > "; search[0]: example.com\n" > "nameserver 192.0.2.1\n" >+ "; nameserver[0]: [192.0.2.1]:53\n" >+ }, >+ {.name = "no-aaaa flag", >+ .conf = "options no-aaaa\n" >+ "nameserver 192.0.2.1\n", >+ .expected = "options no-aaaa\n" >+ "search example.com\n" >+ "; search[0]: example.com\n" >+ "nameserver 192.0.2.1\n" > "; nameserver[0]: [192.0.2.1]:53\n" > }, > { NULL }
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 Raw
Actions:
View
Attachments on
bug 13848
: 5971