Import glibc-2.34-48.fc35 from f35
* Thu Oct 13 2022 Arjun Shankar <arjun@redhat.com> - 2.34-48 - Handle non-hostname CNAME aliases during name resolution (#2129005) - Sync with upstream branch release/2.34/master, commit e3976287b22422787f3cc6fc9adda58304b55bd9: - nscd: Drop local address tuple variable [BZ #29607] - x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations - x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation - x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations - x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations - x86-64: Require BMI2 for AVX2 strncmp implementation - x86-64: Require BMI2 for AVX2 strcmp implementation - x86-64: Require BMI2 for AVX2 str(n)casecmp implementations - x86: include BMI1 and BMI2 in x86-64-v3 level - nptl: Add backoff mechanism to spinlock loop - sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h - nptl: Effectively skip CAS in spinlock loop - Move assignment out of the CAS condition - Add LLL_MUTEX_READ_LOCK [BZ #28537] - Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537] - Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537] - resolv: Fix building tst-resolv-invalid-cname for earlier C standards - nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces - resolv: Add new tst-resolv-invalid-cname - nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154) (#2129005) - nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305) - nss_dns: Remove remnants of IPv6 address mapping - nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr - nss_dns: Split getanswer_ptr from getanswer_r - resolv: Add DNS packet parsing helpers geared towards wire format - resolv: Add internal __ns_name_length_uncompressed function - resolv: Add the __ns_samebinaryname function - resolv: Add internal __res_binary_hnok function - resolv: Add tst-resolv-aliases - resolv: Add tst-resolv-byaddr for testing reverse lookup - gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583) - elf: Fix hwcaps string size overestimation - nscd: Fix netlink cache invalidation if epoll is used [BZ #29415] - Apply asm redirections in wchar.h before first use - Apply asm redirections in stdio.h before first use [BZ #27087] - elf: Call __libc_early_init for reused namespaces (bug 29528) Resolves: #2129005 Resolves: #2116960
This commit is contained in:
parent
6b1ce0df40
commit
e43852d149
589
glibc-rh2129005.patch
Normal file
589
glibc-rh2129005.patch
Normal file
@ -0,0 +1,589 @@
|
||||
commit 1d495912a746e2a1ffb780c9a81fd234ec2464e8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces
|
||||
|
||||
Introduce struct alloc_buffer to this function, and use it and
|
||||
struct ns_rr_cursor in gaih_getanswer_slice. Adjust gaih_getanswer
|
||||
and gaih_getanswer_noaaaa accordingly.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 1cb3be71f04d98eb..36789965c06757d0 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -101,13 +101,6 @@
|
||||
#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
|
||||
@@ -126,18 +119,18 @@ static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
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);
|
||||
|
||||
@@ -409,17 +402,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
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;
|
||||
@@ -428,22 +417,21 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
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)
|
||||
{
|
||||
@@ -474,12 +462,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
__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;
|
||||
@@ -893,259 +889,152 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
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
|
||||
@@ -1157,7 +1046,10 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
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.
|
||||
@@ -1237,36 +1129,30 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
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;
|
||||
@@ -1274,18 +1160,13 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
|
||||
/* 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;
|
||||
}
|
212
glibc-upstream-2.34-309.patch
Normal file
212
glibc-upstream-2.34-309.patch
Normal file
@ -0,0 +1,212 @@
|
||||
commit 536ddc5c02f1ee82483319863a893ccb381beece
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Aug 26 21:15:43 2022 +0200
|
||||
|
||||
elf: Call __libc_early_init for reused namespaces (bug 29528)
|
||||
|
||||
libc_map is never reset to NULL, neither during dlclose nor on a
|
||||
dlopen call which reuses the namespace structure. As a result, if a
|
||||
namespace is reused, its libc is not initialized properly. The most
|
||||
visible result is a crash in the <ctype.h> functions.
|
||||
|
||||
To prevent similar bugs on namespace reuse from surfacing,
|
||||
unconditionally initialize the chosen namespace to zero using memset.
|
||||
|
||||
(cherry picked from commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe)
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 2b547d5b58f1759b..feec365e4e5fe9b3 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -399,6 +399,7 @@ tests += \
|
||||
tst-dlmopen3 \
|
||||
tst-dlmopen-dlerror \
|
||||
tst-dlmopen-gethostbyname \
|
||||
+ tst-dlmopen-twice \
|
||||
tst-dlopenfail \
|
||||
tst-dlopenfail-2 \
|
||||
tst-dlopenrpath \
|
||||
@@ -744,6 +745,8 @@ modules-names = \
|
||||
tst-dlmopen1mod \
|
||||
tst-dlmopen-dlerror-mod \
|
||||
tst-dlmopen-gethostbyname-mod \
|
||||
+ tst-dlmopen-twice-mod1 \
|
||||
+ tst-dlmopen-twice-mod2 \
|
||||
tst-dlopenfaillinkmod \
|
||||
tst-dlopenfailmod1 \
|
||||
tst-dlopenfailmod2 \
|
||||
@@ -2665,3 +2668,7 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
+
|
||||
+$(objpfx)tst-dlmopen-twice.out: \
|
||||
+ $(objpfx)tst-dlmopen-twice-mod1.so \
|
||||
+ $(objpfx)tst-dlmopen-twice-mod2.so
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index bc6872632880634e..1ab3c7b5ac2fbc45 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -839,11 +839,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
||||
_dl_signal_error (EINVAL, file, NULL, N_("\
|
||||
no more namespaces available for dlmopen()"));
|
||||
}
|
||||
- else if (nsid == GL(dl_nns))
|
||||
- {
|
||||
- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
- ++GL(dl_nns);
|
||||
- }
|
||||
+
|
||||
+ if (nsid == GL(dl_nns))
|
||||
+ ++GL(dl_nns);
|
||||
+
|
||||
+ /* Initialize the new namespace. Most members are
|
||||
+ zero-initialized, only the lock needs special treatment. */
|
||||
+ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
|
||||
+ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
|
||||
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
|
||||
}
|
||||
diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0eaf04948ce5263e
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice-mod1.c
|
||||
@@ -0,0 +1,37 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
|
||||
+ 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 <stdio.h>
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+init (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod1.so loaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+fini (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+/* Large allocation. The second module does not have this, so it
|
||||
+ should load libc at a different address. */
|
||||
+char large_allocate[16 * 1024 * 1024];
|
||||
diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..40c6c01f9625e188
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice-mod2.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
|
||||
+ 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 <ctype.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+init (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod2.so loaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+fini (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+run_check (void)
|
||||
+{
|
||||
+ puts ("info: about to call isalpha");
|
||||
+ fflush (stdout);
|
||||
+
|
||||
+ volatile char ch = 'a';
|
||||
+ if (!isalpha (ch))
|
||||
+ {
|
||||
+ puts ("error: isalpha ('a') is not true");
|
||||
+ fflush (stdout);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..449f3c8fa9f2aa01
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice.c
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
|
||||
+ 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 <support/xdlfcn.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
|
||||
+ xdlclose (handle);
|
||||
+ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
|
||||
+ int (*run_check) (void) = xdlsym (handle, "run_check");
|
||||
+ TEST_COMPARE (run_check (), 0);
|
||||
+ xdlclose (handle);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
334
glibc-upstream-2.34-310.patch
Normal file
334
glibc-upstream-2.34-310.patch
Normal file
@ -0,0 +1,334 @@
|
||||
commit 2a44960cbc78713c6a2721683a4319d50e71a01f
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Date: Thu Jul 7 18:12:58 2022 -0300
|
||||
|
||||
Apply asm redirections in stdio.h before first use [BZ #27087]
|
||||
|
||||
Compilers may not be able to apply asm redirections to functions after
|
||||
these functions are used for the first time, e.g. clang 13.
|
||||
Fix [BZ #27087] by applying all long double-related asm redirections
|
||||
before using functions in bits/stdio.h.
|
||||
However, as these asm redirections depend on the declarations provided
|
||||
by libio/bits/stdio2.h, this header was split in 2:
|
||||
|
||||
- libio/bits/stdio2-decl.h contains all function declarations;
|
||||
- libio/bits/stdio2.h remains with the remaining contents, including
|
||||
redirections.
|
||||
|
||||
This also adds the access attribute to __vsnprintf_chk that was missing.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
|
||||
(cherry picked from commit d0fa09a7701956036ff36f8ca188e9fff81553d8)
|
||||
|
||||
diff --git a/include/bits/stdio2-decl.h b/include/bits/stdio2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..bbb052f192218219
|
||||
--- /dev/null
|
||||
+++ b/include/bits/stdio2-decl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <libio/bits/stdio2-decl.h>
|
||||
diff --git a/libio/Makefile b/libio/Makefile
|
||||
index 5336b7d59584927f..981c876940f67fbf 100644
|
||||
--- a/libio/Makefile
|
||||
+++ b/libio/Makefile
|
||||
@@ -23,7 +23,7 @@ subdir := libio
|
||||
include ../Makeconfig
|
||||
|
||||
headers := stdio.h \
|
||||
- bits/stdio.h bits/stdio2.h bits/stdio-ldbl.h \
|
||||
+ bits/stdio.h bits/stdio2.h bits/stdio2-decl.h bits/stdio-ldbl.h \
|
||||
bits/types/FILE.h bits/types/__FILE.h bits/types/struct_FILE.h \
|
||||
bits/types/__fpos_t.h bits/types/__fpos64_t.h \
|
||||
bits/types/cookie_io_functions_t.h
|
||||
diff --git a/libio/bits/stdio2-decl.h b/libio/bits/stdio2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e398f7182b98e4d7
|
||||
--- /dev/null
|
||||
+++ b/libio/bits/stdio2-decl.h
|
||||
@@ -0,0 +1,111 @@
|
||||
+/* Checking macros for stdio functions. Declarations only.
|
||||
+ Copyright (C) 2004-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/>. */
|
||||
+
|
||||
+#ifndef _BITS_STDIO2_DEC_H
|
||||
+#define _BITS_STDIO2_DEC_H 1
|
||||
+
|
||||
+#ifndef _STDIO_H
|
||||
+# error "Never include <bits/stdio2-decl.h> directly; use <stdio.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
+ const char *__restrict __format, ...) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 3));
|
||||
+extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
+ const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 3));
|
||||
+
|
||||
+#if defined __USE_ISOC99 || defined __USE_UNIX98
|
||||
+
|
||||
+extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
+ size_t __slen, const char *__restrict __format,
|
||||
+ ...) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 2));
|
||||
+extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
+ size_t __slen, const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 2));
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#if __USE_FORTIFY_LEVEL > 1
|
||||
+
|
||||
+extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
+ const char *__restrict __format, ...);
|
||||
+extern int __printf_chk (int __flag, const char *__restrict __format, ...);
|
||||
+extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
+ const char *__restrict __format, __gnuc_va_list __ap);
|
||||
+extern int __vprintf_chk (int __flag, const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
|
||||
+ ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
+extern int __vdprintf_chk (int __fd, int __flag,
|
||||
+ const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
+ __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
+# endif
|
||||
+
|
||||
+# ifdef __USE_GNU
|
||||
+
|
||||
+extern int __asprintf_chk (char **__restrict __ptr, int __flag,
|
||||
+ const char *__restrict __fmt, ...)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
|
||||
+extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
|
||||
+ const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
|
||||
+extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
|
||||
+ int __flag, const char *__restrict __format,
|
||||
+ ...)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
+extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
|
||||
+ int __flag,
|
||||
+ const char *__restrict __format,
|
||||
+ __gnuc_va_list __args)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
+
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
+#if __GLIBC_USE (DEPRECATED_GETS)
|
||||
+extern char *__gets_chk (char *__str, size_t) __wur;
|
||||
+#endif
|
||||
+
|
||||
+extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
|
||||
+ FILE *__restrict __stream)
|
||||
+ __wur __attr_access ((__write_only__, 1, 3));
|
||||
+
|
||||
+extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
+ size_t __size, size_t __n,
|
||||
+ FILE *__restrict __stream) __wur;
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
|
||||
+ int __n, FILE *__restrict __stream)
|
||||
+ __wur __attr_access ((__write_only__, 1, 3));
|
||||
+#endif
|
||||
+
|
||||
+#ifdef __USE_MISC
|
||||
+# undef fread_unlocked
|
||||
+extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
+ size_t __size, size_t __n,
|
||||
+ FILE *__restrict __stream) __wur;
|
||||
+#endif
|
||||
+
|
||||
+#endif /* bits/stdio2-decl.h. */
|
||||
diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
|
||||
index 40ff16b01b4f4876..4570f86a4496c1ee 100644
|
||||
--- a/libio/bits/stdio2.h
|
||||
+++ b/libio/bits/stdio2.h
|
||||
@@ -23,14 +23,6 @@
|
||||
# error "Never include <bits/stdio2.h> directly; use <stdio.h> instead."
|
||||
#endif
|
||||
|
||||
-extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
- const char *__restrict __format, ...) __THROW
|
||||
- __attr_access ((__write_only__, 1, 3));
|
||||
-extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
- const char *__restrict __format,
|
||||
- __gnuc_va_list __ap) __THROW
|
||||
- __attr_access ((__write_only__, 1, 3));
|
||||
-
|
||||
#ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
|
||||
@@ -54,15 +46,6 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt,
|
||||
}
|
||||
|
||||
#if defined __USE_ISOC99 || defined __USE_UNIX98
|
||||
-
|
||||
-extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
- size_t __slen, const char *__restrict __format,
|
||||
- ...) __THROW
|
||||
- __attr_access ((__write_only__, 1, 2));
|
||||
-extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
- size_t __slen, const char *__restrict __format,
|
||||
- __gnuc_va_list __ap) __THROW;
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (snprintf (char *__restrict __s, size_t __n,
|
||||
@@ -89,15 +72,6 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
|
||||
#endif
|
||||
|
||||
#if __USE_FORTIFY_LEVEL > 1
|
||||
-
|
||||
-extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
- const char *__restrict __format, ...);
|
||||
-extern int __printf_chk (int __flag, const char *__restrict __format, ...);
|
||||
-extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
- const char *__restrict __format, __gnuc_va_list __ap);
|
||||
-extern int __vprintf_chk (int __flag, const char *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
|
||||
@@ -136,12 +110,6 @@ vfprintf (FILE *__restrict __stream,
|
||||
}
|
||||
|
||||
# ifdef __USE_XOPEN2K8
|
||||
-extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
|
||||
- ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
-extern int __vdprintf_chk (int __fd, int __flag,
|
||||
- const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
- __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
dprintf (int __fd, const char *__restrict __fmt, ...)
|
||||
@@ -162,23 +130,6 @@ vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __ap)
|
||||
# endif
|
||||
|
||||
# ifdef __USE_GNU
|
||||
-
|
||||
-extern int __asprintf_chk (char **__restrict __ptr, int __flag,
|
||||
- const char *__restrict __fmt, ...)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
|
||||
-extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
|
||||
- const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
|
||||
-extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
|
||||
- int __flag, const char *__restrict __format,
|
||||
- ...)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
-extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
|
||||
- int __flag,
|
||||
- const char *__restrict __format,
|
||||
- __gnuc_va_list __args)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...))
|
||||
@@ -231,7 +182,6 @@ __NTH (obstack_vprintf (struct obstack *__restrict __obstack,
|
||||
#endif
|
||||
|
||||
#if __GLIBC_USE (DEPRECATED_GETS)
|
||||
-extern char *__gets_chk (char *__str, size_t) __wur;
|
||||
extern char *__REDIRECT (__gets_warn, (char *__str), gets)
|
||||
__wur __warnattr ("please use fgets or getline instead, gets can't "
|
||||
"specify buffer size");
|
||||
@@ -245,9 +195,6 @@ gets (char *__str)
|
||||
}
|
||||
#endif
|
||||
|
||||
-extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
|
||||
- FILE *__restrict __stream)
|
||||
- __wur __attr_access ((__write_only__, 1, 3));
|
||||
extern char *__REDIRECT (__fgets_alias,
|
||||
(char *__restrict __s, int __n,
|
||||
FILE *__restrict __stream), fgets)
|
||||
@@ -269,9 +216,6 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
|
||||
return __fgets_chk (__s, sz, __n, __stream);
|
||||
}
|
||||
|
||||
-extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
- size_t __size, size_t __n,
|
||||
- FILE *__restrict __stream) __wur;
|
||||
extern size_t __REDIRECT (__fread_alias,
|
||||
(void *__restrict __ptr, size_t __size,
|
||||
size_t __n, FILE *__restrict __stream),
|
||||
@@ -297,9 +241,6 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
|
||||
}
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
|
||||
- int __n, FILE *__restrict __stream)
|
||||
- __wur __attr_access ((__write_only__, 1, 3));
|
||||
extern char *__REDIRECT (__fgets_unlocked_alias,
|
||||
(char *__restrict __s, int __n,
|
||||
FILE *__restrict __stream), fgets_unlocked)
|
||||
@@ -324,9 +265,6 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
|
||||
|
||||
#ifdef __USE_MISC
|
||||
# undef fread_unlocked
|
||||
-extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
- size_t __size, size_t __n,
|
||||
- FILE *__restrict __stream) __wur;
|
||||
extern size_t __REDIRECT (__fread_unlocked_alias,
|
||||
(void *__restrict __ptr, size_t __size,
|
||||
size_t __n, FILE *__restrict __stream),
|
||||
diff --git a/libio/stdio.h b/libio/stdio.h
|
||||
index abefe640e52d18d5..d36e61c56bbb3117 100644
|
||||
--- a/libio/stdio.h
|
||||
+++ b/libio/stdio.h
|
||||
@@ -879,20 +879,27 @@ extern void funlockfile (FILE *__stream) __THROW;
|
||||
extern int __uflow (FILE *);
|
||||
extern int __overflow (FILE *, int);
|
||||
|
||||
+#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Declare all functions from bits/stdio2-decl.h first. */
|
||||
+# include <bits/stdio2-decl.h>
|
||||
+#endif
|
||||
+
|
||||
+/* The following headers provide asm redirections. These redirections must
|
||||
+ appear before the first usage of these functions, e.g. in bits/stdio.h. */
|
||||
+#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
+# include <bits/stdio-ldbl.h>
|
||||
+#endif
|
||||
+
|
||||
/* If we are compiling with optimizing read this file. It contains
|
||||
several optimizing inline functions and macros. */
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
# include <bits/stdio.h>
|
||||
#endif
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Now include the function definitions and redirects too. */
|
||||
# include <bits/stdio2.h>
|
||||
#endif
|
||||
|
||||
-#include <bits/floatn.h>
|
||||
-#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
-# include <bits/stdio-ldbl.h>
|
||||
-#endif
|
||||
-
|
||||
__END_DECLS
|
||||
|
||||
#endif /* <stdio.h> included. */
|
414
glibc-upstream-2.34-311.patch
Normal file
414
glibc-upstream-2.34-311.patch
Normal file
@ -0,0 +1,414 @@
|
||||
commit b41c535f46e7e7bbd8ff2ac68b94c2348e2f66e4
|
||||
Author: Raphael Moreira Zinsly <rzinsly@linux.ibm.com>
|
||||
Date: Wed Aug 24 11:43:37 2022 -0300
|
||||
|
||||
Apply asm redirections in wchar.h before first use
|
||||
|
||||
Similar to d0fa09a770, but for wchar.h. Fixes [BZ #27087] by applying
|
||||
all long double related asm redirections before using functions in
|
||||
bits/wchar2.h.
|
||||
Moves the function declarations from wcsmbs/bits/wchar2.h to a new file
|
||||
wcsmbs/bits/wchar2-decl.h that will be included first in wcsmbs/wchar.h.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
(cherry picked from commit c7509d49c4e8fa494120c5ead21338559dad16f5)
|
||||
|
||||
diff --git a/include/bits/wchar2-decl.h b/include/bits/wchar2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..00b1b93342ef28ff
|
||||
--- /dev/null
|
||||
+++ b/include/bits/wchar2-decl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <wcsmbs/bits/wchar2-decl.h>
|
||||
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
|
||||
index f38eb5cfe16fd3d7..5fe755e65df6c621 100644
|
||||
--- a/wcsmbs/Makefile
|
||||
+++ b/wcsmbs/Makefile
|
||||
@@ -22,8 +22,9 @@ subdir := wcsmbs
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h \
|
||||
- bits/types/__mbstate_t.h bits/types/mbstate_t.h bits/types/wint_t.h
|
||||
+headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar2-decl.h \
|
||||
+ bits/wchar-ldbl.h uchar.h bits/types/__mbstate_t.h \
|
||||
+ bits/types/mbstate_t.h bits/types/wint_t.h
|
||||
|
||||
routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
|
||||
wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
|
||||
diff --git a/wcsmbs/bits/wchar2-decl.h b/wcsmbs/bits/wchar2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..8e1735c33b7f7e78
|
||||
--- /dev/null
|
||||
+++ b/wcsmbs/bits/wchar2-decl.h
|
||||
@@ -0,0 +1,124 @@
|
||||
+/* Checking macros for wchar functions. Declarations only.
|
||||
+ Copyright (C) 2004-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/>. */
|
||||
+
|
||||
+#ifndef _BITS_WCHAR2_DECL_H
|
||||
+#define _BITS_WCHAR2_DECL_H 1
|
||||
+
|
||||
+#ifndef _WCHAR_H
|
||||
+# error "Never include <bits/wchar2-decl.h> directly; use <wchar.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1,
|
||||
+ const wchar_t *__restrict __s2, size_t __n,
|
||||
+ size_t __ns1) __THROW;
|
||||
+extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
|
||||
+ size_t __n, size_t __ns1) __THROW;
|
||||
+
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+
|
||||
+extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1,
|
||||
+ const wchar_t *__restrict __s2, size_t __n,
|
||||
+ size_t __ns1) __THROW;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
|
||||
+ size_t __ns) __THROW;
|
||||
+extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __n) __THROW;
|
||||
+extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src, size_t __n,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src, size_t __n,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __n, size_t __destlen) __THROW;
|
||||
+extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
+ int __flag, size_t __s_len,
|
||||
+ const wchar_t *__restrict __format, ...)
|
||||
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */;
|
||||
+extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
+ int __flag, size_t __s_len,
|
||||
+ const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __arg)
|
||||
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
|
||||
+
|
||||
+#if __USE_FORTIFY_LEVEL > 1
|
||||
+
|
||||
+extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
+ const wchar_t *__restrict __format, ...);
|
||||
+extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
+ ...);
|
||||
+extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
+ const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n,
|
||||
+ __FILE *__restrict __stream) __wur;
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+
|
||||
+extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size,
|
||||
+ int __n, __FILE *__restrict __stream)
|
||||
+ __wur;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar,
|
||||
+ mbstate_t *__restrict __p,
|
||||
+ size_t __buflen) __THROW __wur;
|
||||
+extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst,
|
||||
+ const char **__restrict __src,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+extern size_t __wcsrtombs_chk (char *__restrict __dst,
|
||||
+ const wchar_t **__restrict __src,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+
|
||||
+#ifdef __USE_XOPEN2K8
|
||||
+
|
||||
+extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst,
|
||||
+ const char **__restrict __src, size_t __nmc,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+extern size_t __wcsnrtombs_chk (char *__restrict __dst,
|
||||
+ const wchar_t **__restrict __src,
|
||||
+ size_t __nwc, size_t __len,
|
||||
+ mbstate_t *__restrict __ps, size_t __dstlen)
|
||||
+ __THROW;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#endif /* bits/wchar2-decl.h. */
|
||||
diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h
|
||||
index 88c1fdfcd34292f4..50151b424d85a032 100644
|
||||
--- a/wcsmbs/bits/wchar2.h
|
||||
+++ b/wcsmbs/bits/wchar2.h
|
||||
@@ -21,9 +21,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
-extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1,
|
||||
- const wchar_t *__restrict __s2, size_t __n,
|
||||
- size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemcpy_alias,
|
||||
(wchar_t *__restrict __s1,
|
||||
const wchar_t *__restrict __s2, size_t __n),
|
||||
@@ -45,8 +42,6 @@ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
|
||||
- size_t __n, size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemmove_alias, (wchar_t *__s1,
|
||||
const wchar_t *__s2,
|
||||
size_t __n), wmemmove);
|
||||
@@ -66,9 +61,6 @@ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
|
||||
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1,
|
||||
- const wchar_t *__restrict __s2, size_t __n,
|
||||
- size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmempcpy_alias,
|
||||
(wchar_t *__restrict __s1,
|
||||
const wchar_t *__restrict __s2,
|
||||
@@ -91,8 +83,6 @@ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
|
||||
#endif
|
||||
|
||||
|
||||
-extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
|
||||
- size_t __ns) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemset_alias, (wchar_t *__s, wchar_t __c,
|
||||
size_t __n), wmemset);
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn,
|
||||
@@ -110,9 +100,6 @@ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __n) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcscpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcscpy);
|
||||
@@ -127,9 +114,6 @@ __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcpcpy);
|
||||
@@ -144,9 +128,6 @@ __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src, size_t __n,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcsncpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -168,9 +149,6 @@ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src, size_t __n,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcpncpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -192,9 +170,6 @@ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcscat_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcscat);
|
||||
@@ -209,9 +184,6 @@ __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __n, size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcsncat_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -228,10 +200,6 @@ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
- int __flag, size_t __s_len,
|
||||
- const wchar_t *__restrict __format, ...)
|
||||
- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */;
|
||||
|
||||
extern int __REDIRECT_NTH_LDBL (__swprintf_alias,
|
||||
(wchar_t *__restrict __s, size_t __n,
|
||||
@@ -258,11 +226,6 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n,
|
||||
: swprintf (s, n, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
-extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
- int __flag, size_t __s_len,
|
||||
- const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __arg)
|
||||
- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
|
||||
|
||||
extern int __REDIRECT_NTH_LDBL (__vswprintf_alias,
|
||||
(wchar_t *__restrict __s, size_t __n,
|
||||
@@ -283,16 +246,6 @@ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n,
|
||||
|
||||
#if __USE_FORTIFY_LEVEL > 1
|
||||
|
||||
-extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
- const wchar_t *__restrict __format, ...);
|
||||
-extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
- ...);
|
||||
-extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
- const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
wprintf (const wchar_t *__restrict __fmt, ...)
|
||||
@@ -328,8 +281,6 @@ vfwprintf (__FILE *__restrict __stream,
|
||||
|
||||
#endif
|
||||
|
||||
-extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n,
|
||||
- __FILE *__restrict __stream) __wur;
|
||||
extern wchar_t *__REDIRECT (__fgetws_alias,
|
||||
(wchar_t *__restrict __s, int __n,
|
||||
__FILE *__restrict __stream), fgetws) __wur;
|
||||
@@ -351,9 +302,6 @@ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
|
||||
}
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size,
|
||||
- int __n, __FILE *__restrict __stream)
|
||||
- __wur;
|
||||
extern wchar_t *__REDIRECT (__fgetws_unlocked_alias,
|
||||
(wchar_t *__restrict __s, int __n,
|
||||
__FILE *__restrict __stream), fgetws_unlocked)
|
||||
@@ -379,9 +327,6 @@ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
|
||||
#endif
|
||||
|
||||
|
||||
-extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar,
|
||||
- mbstate_t *__restrict __p,
|
||||
- size_t __buflen) __THROW __wur;
|
||||
extern size_t __REDIRECT_NTH (__wcrtomb_alias,
|
||||
(char *__restrict __s, wchar_t __wchar,
|
||||
mbstate_t *__restrict __ps), wcrtomb) __wur;
|
||||
@@ -404,10 +349,6 @@ __NTH (wcrtomb (char *__restrict __s, wchar_t __wchar,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst,
|
||||
- const char **__restrict __src,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__mbsrtowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char **__restrict __src,
|
||||
@@ -431,10 +372,6 @@ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __wcsrtombs_chk (char *__restrict __dst,
|
||||
- const wchar_t **__restrict __src,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__wcsrtombs_alias,
|
||||
(char *__restrict __dst,
|
||||
const wchar_t **__restrict __src,
|
||||
@@ -458,10 +395,6 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
|
||||
|
||||
|
||||
#ifdef __USE_XOPEN2K8
|
||||
-extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst,
|
||||
- const char **__restrict __src, size_t __nmc,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__mbsnrtowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char **__restrict __src, size_t __nmc,
|
||||
@@ -485,11 +418,6 @@ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __wcsnrtombs_chk (char *__restrict __dst,
|
||||
- const wchar_t **__restrict __src,
|
||||
- size_t __nwc, size_t __len,
|
||||
- mbstate_t *__restrict __ps, size_t __dstlen)
|
||||
- __THROW;
|
||||
extern size_t __REDIRECT_NTH (__wcsnrtombs_alias,
|
||||
(char *__restrict __dst,
|
||||
const wchar_t **__restrict __src,
|
||||
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
|
||||
index 075776890f214842..1c6d4026c46b7306 100644
|
||||
--- a/wcsmbs/wchar.h
|
||||
+++ b/wcsmbs/wchar.h
|
||||
@@ -864,14 +864,21 @@ extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize,
|
||||
|
||||
/* Define some macros helping to catch buffer overflows. */
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
-# include <bits/wchar2.h>
|
||||
+/* Declare all functions from bits/wchar2-decl.h first. */
|
||||
+# include <bits/wchar2-decl.h>
|
||||
#endif
|
||||
|
||||
-#include <bits/floatn.h>
|
||||
+/* The following headers provide asm redirections. These redirections must
|
||||
+ appear before the first usage of these functions, e.g. in bits/wchar.h. */
|
||||
#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
# include <bits/wchar-ldbl.h>
|
||||
#endif
|
||||
|
||||
+#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Now include the function definitions and redirects too. */
|
||||
+# include <bits/wchar2.h>
|
||||
+#endif
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* wchar.h */
|
40
glibc-upstream-2.34-312.patch
Normal file
40
glibc-upstream-2.34-312.patch
Normal file
@ -0,0 +1,40 @@
|
||||
commit 2b3d020055bea4fbbfc0ca2362d46038487c6dfd
|
||||
Author: Fabian Vogt <fvogt@suse.de>
|
||||
Date: Wed Jul 27 11:44:07 2022 +0200
|
||||
|
||||
nscd: Fix netlink cache invalidation if epoll is used [BZ #29415]
|
||||
|
||||
Processes cache network interface information such as whether IPv4 or IPv6
|
||||
are enabled. This is only checked again if the "netlink timestamp" provided
|
||||
by nscd changed, which is triggered by netlink socket activity.
|
||||
|
||||
However, in the epoll handler for the netlink socket, it was missed to
|
||||
assign the new timestamp to the nscd database. The handler for plain poll
|
||||
did that properly, copy that over.
|
||||
|
||||
This bug caused that e.g. processes which started before network
|
||||
configuration got unusuable addresses from getaddrinfo, like IPv6 only even
|
||||
though only IPv4 is available:
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1041
|
||||
|
||||
It's a bit hard to reproduce, so I verified this by checking the timestamp
|
||||
on calls to __check_pf manually. Without this patch it's stuck at 1, now
|
||||
it's increasing on network changes as expected.
|
||||
|
||||
Signed-off-by: Fabian Vogt <fvogt@suse.de>
|
||||
(cherry picked from commit 02ca25fef2785974011e9c5beecc99b900b69fd7)
|
||||
|
||||
diff --git a/nscd/connections.c b/nscd/connections.c
|
||||
index 3f0bda4e97edb9df..bc941715cff47c49 100644
|
||||
--- a/nscd/connections.c
|
||||
+++ b/nscd/connections.c
|
||||
@@ -2285,7 +2285,8 @@ main_loop_epoll (int efd)
|
||||
sizeof (buf))) != -1)
|
||||
;
|
||||
|
||||
- __bump_nl_timestamp ();
|
||||
+ dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
|
||||
+ = __bump_nl_timestamp ();
|
||||
}
|
||||
# endif
|
||||
else
|
55
glibc-upstream-2.34-314.patch
Normal file
55
glibc-upstream-2.34-314.patch
Normal file
@ -0,0 +1,55 @@
|
||||
commit 2ff6775ad341b10a08e3b27d6e1df1da637747c7
|
||||
Author: Javier Pello <devel@otheo.eu>
|
||||
Date: Mon Sep 5 20:09:01 2022 +0200
|
||||
|
||||
elf: Fix hwcaps string size overestimation
|
||||
|
||||
Commit dad90d528259b669342757c37dedefa8577e2636 added glibc-hwcaps
|
||||
support for LD_LIBRARY_PATH and, for this, it adjusted the total
|
||||
string size required in _dl_important_hwcaps. However, in doing so
|
||||
it inadvertently altered the calculation of the size required for
|
||||
the power set strings, as the computation of the power set string
|
||||
size depended on the first value assigned to the total variable,
|
||||
which is later shifted, resulting in overallocation of string
|
||||
space. Fix this now by using a different variable to hold the
|
||||
string size required for glibc-hwcaps.
|
||||
|
||||
Signed-off-by: Javier Pello <devel@otheo.eu>
|
||||
(cherry picked from commit a23820f6052a740246fdc7dcd9c43ce8eed0c45a)
|
||||
|
||||
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||
index e3c611e005ffbc0d..045911eb6d5d315a 100644
|
||||
--- a/elf/dl-hwcaps.c
|
||||
+++ b/elf/dl-hwcaps.c
|
||||
@@ -193,7 +193,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
/* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
|
||||
and a "/" suffix once stored in the result. */
|
||||
hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1;
|
||||
- size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
|
||||
+ size_t hwcaps_sz = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
|
||||
+ hwcaps_counts.total_length);
|
||||
|
||||
/* Count the number of bits set in the masked value. */
|
||||
@@ -229,11 +229,12 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
assert (m == cnt);
|
||||
|
||||
/* Determine the total size of all strings together. */
|
||||
+ size_t total;
|
||||
if (cnt == 1)
|
||||
- total += temp[0].len + 1;
|
||||
+ total = temp[0].len + 1;
|
||||
else
|
||||
{
|
||||
- total += temp[0].len + temp[cnt - 1].len + 2;
|
||||
+ total = temp[0].len + temp[cnt - 1].len + 2;
|
||||
if (cnt > 2)
|
||||
{
|
||||
total <<= 1;
|
||||
@@ -255,6 +256,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
/* This is the overall result, including both glibc-hwcaps
|
||||
subdirectories and the legacy hwcaps subdirectories using the
|
||||
power set construction. */
|
||||
+ total += hwcaps_sz;
|
||||
struct r_strlenpair *overall_result
|
||||
= malloc (*sz * sizeof (*result) + total);
|
||||
if (overall_result == NULL)
|
62
glibc-upstream-2.34-315.patch
Normal file
62
glibc-upstream-2.34-315.patch
Normal file
@ -0,0 +1,62 @@
|
||||
commit f50a6c843a5b5186c0aa73747de033e08ef8246d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 20 12:12:43 2022 +0200
|
||||
|
||||
gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
|
||||
|
||||
It's possible that inode numbers are outside the 32-bit range.
|
||||
The existing code only handles the in-libc case correctly, and
|
||||
still uses the legacy interfaces when building iconv.
|
||||
|
||||
Suggested-by: Helge Deller <deller@gmx.de>
|
||||
(cherry picked from commit f97905f24631097af325d6a231093071c3077a5f)
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index 79398a980cde84e3..741cf7c67e36eccd 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -29,14 +29,14 @@
|
||||
# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr)
|
||||
# define asprintf __asprintf
|
||||
# define opendir __opendir
|
||||
-# define readdir __readdir
|
||||
+# define readdir64 __readdir64
|
||||
# define closedir __closedir
|
||||
# define mempcpy __mempcpy
|
||||
-# define struct_stat struct __stat64_t64
|
||||
-# define lstat __lstat64_time64
|
||||
+# define struct_stat64 struct __stat64_t64
|
||||
+# define lstat64 __lstat64_time64
|
||||
# define feof_unlocked __feof_unlocked
|
||||
#else
|
||||
-# define struct_stat struct stat
|
||||
+# define struct_stat64 struct stat64
|
||||
#endif
|
||||
|
||||
/* Name of the file containing the module information in the directories
|
||||
@@ -148,8 +148,8 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
|
||||
DIR *confdir = opendir (buf);
|
||||
if (confdir != NULL)
|
||||
{
|
||||
- struct dirent *ent;
|
||||
- while ((ent = readdir (confdir)) != NULL)
|
||||
+ struct dirent64 *ent;
|
||||
+ while ((ent = readdir64 (confdir)) != NULL)
|
||||
{
|
||||
if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
@@ -161,12 +161,12 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
|
||||
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
{
|
||||
char *conf;
|
||||
- struct_stat st;
|
||||
+ struct_stat64 st;
|
||||
if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
continue;
|
||||
|
||||
if (ent->d_type != DT_UNKNOWN
|
||||
- || (lstat (conf, &st) != -1 && S_ISREG (st.st_mode)))
|
||||
+ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
|
||||
found |= read_conf_file (conf, dir, dir_len);
|
||||
|
||||
free (conf);
|
399
glibc-upstream-2.34-316.patch
Normal file
399
glibc-upstream-2.34-316.patch
Normal file
@ -0,0 +1,399 @@
|
||||
commit 1a3afdfe319a142228498f7a4ee82ac3917d97e8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add tst-resolv-byaddr for testing reverse lookup
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 0b99828d54e5d1fc8f5ad3edf5ba262ad2e9c5b0)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index e8269dcb5bcf216b..78165eb99e98b525 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -92,6 +92,7 @@ tests += \
|
||||
tst-res_hnok \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-binary \
|
||||
+ tst-resolv-byaddr \
|
||||
tst-resolv-edns \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
@@ -251,6 +252,7 @@ $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
|
||||
$(gen-locales) $(objpfx)tst-no-libidn2.so
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
|
||||
diff --git a/resolv/tst-resolv-byaddr.c b/resolv/tst-resolv-byaddr.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6299e89837da58c6
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-byaddr.c
|
||||
@@ -0,0 +1,326 @@
|
||||
+/* Test reverse DNS lookup.
|
||||
+ 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 <arpa/inet.h>
|
||||
+#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+#include "tst-resolv-maybe_insert_sig.h"
|
||||
+
|
||||
+/* QNAME format:
|
||||
+
|
||||
+ ADDRESSES.CNAMES...(lots of 0s)...8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
+ CNAMES|ADDRESSES.2.0.192.in-addr-arpa.
|
||||
+
|
||||
+ For the IPv4 reverse lookup, the address count is in the lower
|
||||
+ bits.
|
||||
+
|
||||
+ CNAMES is the length of the CNAME chain, ADDRESSES is the number of
|
||||
+ addresses in the response. The special value 15 means that there
|
||||
+ are no addresses, and the RCODE is NXDOMAIN. */
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int addresses, cnames, bits;
|
||||
+ char *tail;
|
||||
+ if (strstr (qname, "ip6.arpa") != NULL
|
||||
+ && sscanf (qname, "%x.%x.%ms", &addresses, &cnames, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ else if (sscanf (qname, "%u.%ms", &bits, &tail) == 2)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "2.0.192.in-addr.arpa");
|
||||
+ addresses = bits & 0x0f;
|
||||
+ cnames = bits >> 4;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ int rcode;
|
||||
+ if (addresses == 15)
|
||||
+ {
|
||||
+ /* Special case: Use no addresses with NXDOMAIN response. */
|
||||
+ rcode = ns_r_nxdomain;
|
||||
+ addresses = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ rcode = 0;
|
||||
+
|
||||
+ struct resolv_response_flags flags = { .rcode = rcode };
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ for (int unique = 0; unique < cnames; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+ char *new_name = xasprintf ("%d.alias.example", unique);
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ for (int unique = 0; unique < addresses; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_PTR, 60);
|
||||
+ char *ptr = xasprintf ("unique-%d.cnames-%u.addresses-%u.example",
|
||||
+ unique, cnames, addresses);
|
||||
+ resolv_response_add_name (b, ptr);
|
||||
+ free (ptr);
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+/* Used to check that gethostbyaddr_r does not write past the buffer
|
||||
+ end. */
|
||||
+static struct support_next_to_fault ntf;
|
||||
+
|
||||
+/* Perform a gethostbyaddr call and check the result. */
|
||||
+static void
|
||||
+check_gethostbyaddr (const char *address, const char *expected)
|
||||
+{
|
||||
+ unsigned char bytes[16];
|
||||
+ unsigned int byteslen;
|
||||
+ int family;
|
||||
+ if (strchr (address, ':') != NULL)
|
||||
+ {
|
||||
+ family = AF_INET6;
|
||||
+ byteslen = 16;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ family = AF_INET;
|
||||
+ byteslen = 4;
|
||||
+ }
|
||||
+ TEST_COMPARE (inet_pton (family, address, bytes), 1);
|
||||
+
|
||||
+ struct hostent *e = gethostbyaddr (bytes, byteslen, family);
|
||||
+ check_hostent (address, e, expected);
|
||||
+
|
||||
+ if (e == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* Try gethostbyaddr_r with increasing sizes until success. First
|
||||
+ compute a reasonable minimum buffer size, to avoid many pointless
|
||||
+ attempts. */
|
||||
+ size_t minimum_size = strlen (e->h_name);
|
||||
+ for (int i = 0; e->h_addr_list[i] != NULL; ++i)
|
||||
+ minimum_size += e->h_length + sizeof (char *);
|
||||
+ for (int i = 0; e->h_aliases[i] != NULL; ++i)
|
||||
+ minimum_size += strlen (e->h_aliases[i]) + 1 + sizeof (char *);
|
||||
+
|
||||
+ /* Gradually increase the size until success. */
|
||||
+ for (size_t size = minimum_size; size < ntf.length; ++size)
|
||||
+ {
|
||||
+ struct hostent result;
|
||||
+ int herrno;
|
||||
+ int ret = gethostbyaddr_r (bytes, byteslen, family, &result,
|
||||
+ ntf.buffer + ntf.length - size, size,
|
||||
+ &e, &herrno);
|
||||
+ if (ret == ERANGE)
|
||||
+ /* Retry with larger size. */
|
||||
+ TEST_COMPARE (herrno, NETDB_INTERNAL);
|
||||
+ else if (ret == 0)
|
||||
+ {
|
||||
+ TEST_VERIFY (size > minimum_size);
|
||||
+ check_hostent (address, e, expected);
|
||||
+ return;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("Unexpected gethostbyaddr_r failure: %d", ret);
|
||||
+ }
|
||||
+
|
||||
+ FAIL_EXIT1 ("gethostbyaddr_r always failed for: %s", address);
|
||||
+}
|
||||
+
|
||||
+/* Perform a getnameinfo call and check the result. */
|
||||
+static void
|
||||
+check_getnameinfo (const char *address, const char *expected)
|
||||
+{
|
||||
+ struct sockaddr_in sin = { };
|
||||
+ struct sockaddr_in6 sin6 = { };
|
||||
+ void *sa;
|
||||
+ socklen_t salen;
|
||||
+ if (strchr (address, ':') != NULL)
|
||||
+ {
|
||||
+ sin6.sin6_family = AF_INET6;
|
||||
+ TEST_COMPARE (inet_pton (AF_INET6, address, &sin6.sin6_addr), 1);
|
||||
+ sin6.sin6_port = htons (80);
|
||||
+ sa = &sin6;
|
||||
+ salen = sizeof (sin6);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ sin.sin_family = AF_INET;
|
||||
+ TEST_COMPARE (inet_pton (AF_INET, address, &sin.sin_addr), 1);
|
||||
+ sin.sin_port = htons (80);
|
||||
+ sa = &sin;
|
||||
+ salen = sizeof (sin);
|
||||
+ }
|
||||
+
|
||||
+ char host[64];
|
||||
+ char service[64];
|
||||
+ int ret = getnameinfo (sa, salen, host,
|
||||
+ sizeof (host), service, sizeof (service),
|
||||
+ NI_NAMEREQD | NI_NUMERICSERV);
|
||||
+ switch (ret)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ TEST_COMPARE_STRING (host, expected);
|
||||
+ TEST_COMPARE_STRING (service, "80");
|
||||
+ break;
|
||||
+ case EAI_SYSTEM:
|
||||
+ TEST_COMPARE_STRING (strerror (errno), expected);
|
||||
+ break;
|
||||
+ default:
|
||||
+ TEST_COMPARE_STRING (gai_strerror (ret), expected);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Some reasonably upper bound for the maximum response size. */
|
||||
+ ntf = support_next_to_fault_allocate (4096);
|
||||
+
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig)
|
||||
+ {
|
||||
+ insert_sig = do_insert_sig;
|
||||
+
|
||||
+ /* No PTR record, RCODE=0. */
|
||||
+ check_gethostbyaddr ("192.0.2.0", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.0", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.16", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.16", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.32", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.32", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::10", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::10", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::20", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::20", "Name or service not known");
|
||||
+
|
||||
+ /* No PTR record, NXDOMAIN. */
|
||||
+ check_gethostbyaddr ("192.0.2.15", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.15", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.31", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.31", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.47", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.47", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::f", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::1f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::1f", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::2f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::2f", "Name or service not known");
|
||||
+
|
||||
+ /* Actual response data. Only the first PTR record is returned. */
|
||||
+ check_gethostbyaddr ("192.0.2.1",
|
||||
+ "name: unique-0.cnames-0.addresses-1.example\n"
|
||||
+ "address: 192.0.2.1\n");
|
||||
+ check_getnameinfo ("192.0.2.1",
|
||||
+ "unique-0.cnames-0.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.17",
|
||||
+ "name: unique-0.cnames-1.addresses-1.example\n"
|
||||
+ "address: 192.0.2.17\n");
|
||||
+ check_getnameinfo ("192.0.2.17",
|
||||
+ "unique-0.cnames-1.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.18",
|
||||
+ "name: unique-0.cnames-1.addresses-2.example\n"
|
||||
+ "address: 192.0.2.18\n");
|
||||
+ check_getnameinfo ("192.0.2.18",
|
||||
+ "unique-0.cnames-1.addresses-2.example");
|
||||
+ check_gethostbyaddr ("192.0.2.33",
|
||||
+ "name: unique-0.cnames-2.addresses-1.example\n"
|
||||
+ "address: 192.0.2.33\n");
|
||||
+ check_getnameinfo ("192.0.2.33",
|
||||
+ "unique-0.cnames-2.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.34",
|
||||
+ "name: unique-0.cnames-2.addresses-2.example\n"
|
||||
+ "address: 192.0.2.34\n");
|
||||
+ check_getnameinfo ("192.0.2.34",
|
||||
+ "unique-0.cnames-2.addresses-2.example");
|
||||
+
|
||||
+ /* Same for IPv6 addresses. */
|
||||
+ check_gethostbyaddr ("2001:db8::1",
|
||||
+ "name: unique-0.cnames-0.addresses-1.example\n"
|
||||
+ "address: 2001:db8::1\n");
|
||||
+ check_getnameinfo ("2001:db8::1",
|
||||
+ "unique-0.cnames-0.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::11",
|
||||
+ "name: unique-0.cnames-1.addresses-1.example\n"
|
||||
+ "address: 2001:db8::11\n");
|
||||
+ check_getnameinfo ("2001:db8::11",
|
||||
+ "unique-0.cnames-1.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::12",
|
||||
+ "name: unique-0.cnames-1.addresses-2.example\n"
|
||||
+ "address: 2001:db8::12\n");
|
||||
+ check_getnameinfo ("2001:db8::12",
|
||||
+ "unique-0.cnames-1.addresses-2.example");
|
||||
+ check_gethostbyaddr ("2001:db8::21",
|
||||
+ "name: unique-0.cnames-2.addresses-1.example\n"
|
||||
+ "address: 2001:db8::21\n");
|
||||
+ check_getnameinfo ("2001:db8::21",
|
||||
+ "unique-0.cnames-2.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::22",
|
||||
+ "name: unique-0.cnames-2.addresses-2.example\n"
|
||||
+ "address: 2001:db8::22\n");
|
||||
+ check_getnameinfo ("2001:db8::22",
|
||||
+ "unique-0.cnames-2.addresses-2.example");
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-resolv-maybe_insert_sig.h b/resolv/tst-resolv-maybe_insert_sig.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..05725225af0818cb
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-maybe_insert_sig.h
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Code snippet for optionally inserting ignored SIG records in resolver tests.
|
||||
+ 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/>. */
|
||||
+
|
||||
+/* Set to true for an alternative pass that inserts (ignored) SIG
|
||||
+ records. This does not alter the response, so this property is not
|
||||
+ encoded in the QNAME. The variable needs to be volatile because
|
||||
+ leaf attributes tell GCC that the response function is not
|
||||
+ called. */
|
||||
+static volatile bool insert_sig;
|
||||
+
|
||||
+static void
|
||||
+maybe_insert_sig (struct resolv_response_builder *b, const char *owner)
|
||||
+{
|
||||
+ resolv_response_open_record (b, owner, C_IN, T_SIG, 60);
|
||||
+ resolv_response_add_data (b, "", 1);
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
289
glibc-upstream-2.34-317.patch
Normal file
289
glibc-upstream-2.34-317.patch
Normal file
@ -0,0 +1,289 @@
|
||||
commit 6a833d798e87536587cd4cc14fe8d078f80b14a0
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add tst-resolv-aliases
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 87aa98aa80627553a66bdcad2701fd6307723645)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 78165eb99e98b525..567f4c2dcf5749df 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -90,6 +90,7 @@ tests += \
|
||||
tst-ns_name_pton \
|
||||
tst-res_hconf_reorder \
|
||||
tst-res_hnok \
|
||||
+ tst-resolv-aliases \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-byaddr \
|
||||
@@ -250,6 +251,7 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
|
||||
$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
|
||||
$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
|
||||
$(gen-locales) $(objpfx)tst-no-libidn2.so
|
||||
+$(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/tst-resolv-aliases.c b/resolv/tst-resolv-aliases.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b212823aa07ceb21
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-aliases.c
|
||||
@@ -0,0 +1,254 @@
|
||||
+/* Test alias handling (mainly for gethostbyname).
|
||||
+ 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 <array_length.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <netdb.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+#include "tst-resolv-maybe_insert_sig.h"
|
||||
+
|
||||
+/* QNAME format:
|
||||
+
|
||||
+ aADDRESSES-cCNAMES.example.net
|
||||
+
|
||||
+ CNAMES is the length of the CNAME chain, ADDRESSES is the number of
|
||||
+ addresses in the response. The special value 255 means that there
|
||||
+ are no addresses, and the RCODE is NXDOMAIN. */
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+ if (qtype != T_A)
|
||||
+ TEST_COMPARE (qtype, T_AAAA);
|
||||
+
|
||||
+ unsigned int addresses, cnames;
|
||||
+ char *tail;
|
||||
+ if (sscanf (qname, "a%u-c%u%ms", &addresses, &cnames, &tail) == 3)
|
||||
+ {
|
||||
+ if (strcmp (tail, ".example.com") == 0
|
||||
+ || strcmp (tail, ".example.net.example.net") == 0
|
||||
+ || strcmp (tail, ".example.net.example.com") == 0)
|
||||
+ /* These only happen after NXDOMAIN. */
|
||||
+ TEST_VERIFY (addresses == 255);
|
||||
+ else if (strcmp (tail, ".example.net") != 0)
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||||
+ }
|
||||
+ free (tail);
|
||||
+
|
||||
+ int rcode;
|
||||
+ if (addresses == 255)
|
||||
+ {
|
||||
+ /* Special case: Use no addresses with NXDOMAIN response. */
|
||||
+ rcode = ns_r_nxdomain;
|
||||
+ addresses = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ rcode = 0;
|
||||
+
|
||||
+ struct resolv_response_flags flags = { .rcode = rcode };
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ for (int unique = 0; unique < cnames; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+ char *new_name = xasprintf ("%d.alias.example", unique);
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ for (int unique = 0; unique < addresses; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, qtype, 60);
|
||||
+
|
||||
+ if (qtype == T_A)
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 0, 2, 1 + unique};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ }
|
||||
+ else if (qtype == T_AAAA)
|
||||
+ {
|
||||
+ char ipv6[16] =
|
||||
+ {
|
||||
+ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
+ 1 + unique
|
||||
+ };
|
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+static char *
|
||||
+make_qname (bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ return xasprintf ("a%d-c%d%s",
|
||||
+ addresses, cnames, do_search ? "" : ".example.net");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check_cnames_failure (int af, bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ char *qname = make_qname (do_search, cnames, addresses);
|
||||
+
|
||||
+ struct hostent *e;
|
||||
+ if (af == AF_UNSPEC)
|
||||
+ e = gethostbyname (qname);
|
||||
+ else
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+
|
||||
+ if (addresses == 0)
|
||||
+ check_hostent (qname, e, "error: NO_RECOVERY\n");
|
||||
+ else
|
||||
+ check_hostent (qname, e, "error: HOST_NOT_FOUND\n");
|
||||
+
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check (int af, bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ char *qname = make_qname (do_search, cnames, addresses);
|
||||
+ char *fqdn = make_qname (false, cnames, addresses);
|
||||
+
|
||||
+ struct hostent *e;
|
||||
+ if (af == AF_UNSPEC)
|
||||
+ e = gethostbyname (qname);
|
||||
+ else
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+ if (e == NULL)
|
||||
+ FAIL_EXIT1 ("unexpected failure for %d, %d, %d", af, cnames, addresses);
|
||||
+
|
||||
+ if (af == AF_UNSPEC || af == AF_INET)
|
||||
+ {
|
||||
+ TEST_COMPARE (e->h_addrtype, AF_INET);
|
||||
+ TEST_COMPARE (e->h_length, 4);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_COMPARE (e->h_addrtype, AF_INET6);
|
||||
+ TEST_COMPARE (e->h_length, 16);
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < addresses; ++i)
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 0, 2, 1 + i};
|
||||
+ char ipv6[16] =
|
||||
+ { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + i };
|
||||
+ char *expected = e->h_addrtype == AF_INET ? ipv4 : ipv6;
|
||||
+ TEST_COMPARE_BLOB (e->h_addr_list[i], e->h_length,
|
||||
+ expected, e->h_length);
|
||||
+ }
|
||||
+ TEST_VERIFY (e->h_addr_list[addresses] == NULL);
|
||||
+
|
||||
+
|
||||
+ if (cnames == 0)
|
||||
+ {
|
||||
+ /* QNAME is fully qualified. */
|
||||
+ TEST_COMPARE_STRING (e->h_name, fqdn);
|
||||
+ TEST_VERIFY (e->h_aliases[0] == NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Fully-qualified QNAME is demoted to an aliases. */
|
||||
+ TEST_COMPARE_STRING (e->h_aliases[0], fqdn);
|
||||
+
|
||||
+ for (int i = 1; i <= cnames; ++i)
|
||||
+ {
|
||||
+ char *expected = xasprintf ("%d.alias.example", i - 1);
|
||||
+ if (i == cnames)
|
||||
+ TEST_COMPARE_STRING (e->h_name, expected);
|
||||
+ else
|
||||
+ TEST_COMPARE_STRING (e->h_aliases[i], expected);
|
||||
+ free (expected);
|
||||
+ }
|
||||
+ TEST_VERIFY (e->h_aliases[cnames] == NULL);
|
||||
+ }
|
||||
+
|
||||
+ free (fqdn);
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ .search = { "example.net", "example.com" },
|
||||
+ });
|
||||
+
|
||||
+ static const int families[] = { AF_UNSPEC, AF_INET, AF_INET6 };
|
||||
+
|
||||
+ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig)
|
||||
+ {
|
||||
+ insert_sig = do_insert_sig;
|
||||
+
|
||||
+ /* If do_search is true, a bare host name (for example, a1-c1)
|
||||
+ is used. This exercises search path processing and FQDN
|
||||
+ qualification. */
|
||||
+ for (int do_search = 0; do_search < 2; ++do_search)
|
||||
+ for (const int *paf = families; paf != array_end (families); ++paf)
|
||||
+ {
|
||||
+ for (int cnames = 0; cnames <= 100; ++cnames)
|
||||
+ {
|
||||
+ check_cnames_failure (*paf, do_search, cnames, 0);
|
||||
+ /* Now with NXDOMAIN responses. */
|
||||
+ check_cnames_failure (*paf, do_search, cnames, 255);
|
||||
+ }
|
||||
+
|
||||
+ for (int cnames = 0; cnames <= 10; ++cnames)
|
||||
+ for (int addresses = 1; addresses <= 10; ++addresses)
|
||||
+ check (*paf, do_search, cnames, addresses);
|
||||
+
|
||||
+ /* The current implementation is limited to 47 aliases.
|
||||
+ Addresses do not have such a limit. */
|
||||
+ check (*paf, do_search, 47, 60);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
58
glibc-upstream-2.34-318.patch
Normal file
58
glibc-upstream-2.34-318.patch
Normal file
@ -0,0 +1,58 @@
|
||||
commit 4d2e67d6e5c910114dbccd17d9b93f06552c0024
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add internal __res_binary_hnok function
|
||||
|
||||
During package parsing, only the binary representation is available,
|
||||
and it is convenient to check that directly for conformance with host
|
||||
name requirements.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit c79327bf00a4be6d60259227acc78ef80ead3622)
|
||||
|
||||
diff --git a/include/resolv.h b/include/resolv.h
|
||||
index 3590b6f496d47710..4dbbac3800b7ef30 100644
|
||||
--- a/include/resolv.h
|
||||
+++ b/include/resolv.h
|
||||
@@ -70,5 +70,8 @@ libc_hidden_proto (__libc_res_nameinquery)
|
||||
extern __typeof (__res_queriesmatch) __libc_res_queriesmatch;
|
||||
libc_hidden_proto (__libc_res_queriesmatch)
|
||||
|
||||
+/* Variant of res_hnok which operates on binary (but uncompressed) names. */
|
||||
+bool __res_binary_hnok (const unsigned char *dn) attribute_hidden;
|
||||
+
|
||||
# endif /* _RESOLV_H_ && !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/res-name-checking.c b/resolv/res-name-checking.c
|
||||
index 2c603494fa3ca992..513ddb5f6b12ccb0 100644
|
||||
--- a/resolv/res-name-checking.c
|
||||
+++ b/resolv/res-name-checking.c
|
||||
@@ -138,6 +138,12 @@ binary_leading_dash (const unsigned char *dn)
|
||||
return dn[0] > 0 && dn[1] == '-';
|
||||
}
|
||||
|
||||
+bool
|
||||
+__res_binary_hnok (const unsigned char *dn)
|
||||
+{
|
||||
+ return !binary_leading_dash (dn) && binary_hnok (dn);
|
||||
+}
|
||||
+
|
||||
/* Return 1 if res_hnok is a valid host name. Labels must only
|
||||
contain [0-9a-zA-Z_-] characters, and the name must not start with
|
||||
a '-'. The latter is to avoid confusion with program options. */
|
||||
@@ -145,11 +151,9 @@ int
|
||||
___res_hnok (const char *dn)
|
||||
{
|
||||
unsigned char buf[NS_MAXCDNAME];
|
||||
- if (!printable_string (dn)
|
||||
- || __ns_name_pton (dn, buf, sizeof (buf)) < 0
|
||||
- || binary_leading_dash (buf))
|
||||
- return 0;
|
||||
- return binary_hnok (buf);
|
||||
+ return (printable_string (dn)
|
||||
+ && __ns_name_pton (dn, buf, sizeof (buf)) >= 0
|
||||
+ && __res_binary_hnok (buf));
|
||||
}
|
||||
versioned_symbol (libc, ___res_hnok, res_hnok, GLIBC_2_34);
|
||||
versioned_symbol (libc, ___res_hnok, __libc_res_hnok, GLIBC_PRIVATE);
|
182
glibc-upstream-2.34-319.patch
Normal file
182
glibc-upstream-2.34-319.patch
Normal file
@ -0,0 +1,182 @@
|
||||
commit bb8adbba4f5d9237a144786ba8e504039beff161
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add the __ns_samebinaryname function
|
||||
|
||||
During packet parsing, only the binary name is available. If the name
|
||||
equality check is performed before conversion to text, we can sometimes
|
||||
skip the last step.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 394085a34d25a51513019a4dc411acd3527fbd33)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index 53f1dbc7c3f659e9..bb1dede187cf1500 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -55,6 +55,12 @@ int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
|
||||
int __ns_name_unpack (const unsigned char *, const unsigned char *,
|
||||
const unsigned char *, unsigned char *, size_t) __THROW;
|
||||
|
||||
+/* Like ns_samename, but for uncompressed binary names. Return true
|
||||
+ if the two arguments compare are equal as case-insensitive domain
|
||||
+ names. */
|
||||
+_Bool __ns_samebinaryname (const unsigned char *, const unsigned char *)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
#define ns_msg_getflag(handle, flag) \
|
||||
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 567f4c2dcf5749df..0b4fa30716af3b8a 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -46,6 +46,7 @@ routines := \
|
||||
ns_name_skip \
|
||||
ns_name_uncompress \
|
||||
ns_name_unpack \
|
||||
+ ns_samebinaryname \
|
||||
ns_samename \
|
||||
nsap_addr \
|
||||
nss_dns_functions \
|
||||
@@ -107,6 +108,10 @@ tests += \
|
||||
tests-internal += tst-resolv-txnid-collision
|
||||
tests-static += tst-resolv-txnid-collision
|
||||
|
||||
+# Likewise for __ns_samebinaryname.
|
||||
+tests-internal += tst-ns_samebinaryname
|
||||
+tests-static += tst-ns_samebinaryname
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_samebinaryname.c b/resolv/ns_samebinaryname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..9a47d8e97a84c759
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_samebinaryname.c
|
||||
@@ -0,0 +1,55 @@
|
||||
+/* Compare two binary domain names for quality.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
+/* Convert ASCII letters to upper case. */
|
||||
+static inline int
|
||||
+ascii_toupper (unsigned char ch)
|
||||
+{
|
||||
+ if (ch >= 'a' && ch <= 'z')
|
||||
+ return ch - 'a' + 'A';
|
||||
+ else
|
||||
+ return ch;
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+__ns_samebinaryname (const unsigned char *a, const unsigned char *b)
|
||||
+{
|
||||
+ while (*a != 0 && *b != 0)
|
||||
+ {
|
||||
+ if (*a != *b)
|
||||
+ /* Different label length. */
|
||||
+ return false;
|
||||
+ int labellen = *a;
|
||||
+ ++a;
|
||||
+ ++b;
|
||||
+ for (int i = 0; i < labellen; ++i)
|
||||
+ {
|
||||
+ if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b))
|
||||
+ /* Different character in label. */
|
||||
+ return false;
|
||||
+ ++a;
|
||||
+ ++b;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Match if both names are at the root label. */
|
||||
+ return *a == 0 && *b == 0;
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_samebinaryname.c b/resolv/tst-ns_samebinaryname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b06ac610b4cde8be
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_samebinaryname.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Test the __ns_samebinaryname function.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <array_length.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+/* First character denotes the comparison group: All names with the
|
||||
+ same first character are expected to compare equal. */
|
||||
+static const char *const cases[] =
|
||||
+ {
|
||||
+ " ",
|
||||
+ "1\001a", "1\001A",
|
||||
+ "2\002ab", "2\002aB", "2\002Ab", "2\002AB",
|
||||
+ "3\001a\002ab", "3\001A\002ab",
|
||||
+ "w\003www\007example\003com", "w\003Www\007Example\003Com",
|
||||
+ "w\003WWW\007EXAMPLE\003COM",
|
||||
+ "W\003WWW", "W\003www",
|
||||
+ };
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ for (int i = 0; i < array_length (cases); ++i)
|
||||
+ for (int j = 0; j < array_length (cases); ++j)
|
||||
+ {
|
||||
+ unsigned char *a = (unsigned char *) &cases[i][1];
|
||||
+ unsigned char *b = (unsigned char *) &cases[j][1];
|
||||
+ bool actual = __ns_samebinaryname (a, b);
|
||||
+ bool expected = cases[i][0] == cases[j][0];
|
||||
+ if (actual != expected)
|
||||
+ {
|
||||
+ char a1[NS_MAXDNAME];
|
||||
+ TEST_VERIFY (ns_name_ntop (a, a1, sizeof (a1)) > 0);
|
||||
+ char b1[NS_MAXDNAME];
|
||||
+ TEST_VERIFY (ns_name_ntop (b, b1, sizeof (b1)) > 0);
|
||||
+ printf ("error: \"%s\" \"%s\": expected %s\n",
|
||||
+ a1, b1, expected ? "equal" : "unqueal");
|
||||
+ support_record_failure ();
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
272
glibc-upstream-2.34-320.patch
Normal file
272
glibc-upstream-2.34-320.patch
Normal file
@ -0,0 +1,272 @@
|
||||
commit c288e032ae107c48679ef3c46fb84af6de0a6baf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add internal __ns_name_length_uncompressed function
|
||||
|
||||
This function is useful for checking that the question name is
|
||||
uncompressed (as it should be).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 78b1a4f0e49064e5dfb686c7cd87bd4df2640b29)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index bb1dede187cf1500..6e4808f00d60caf9 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -95,5 +95,13 @@ libc_hidden_proto (__ns_name_unpack)
|
||||
extern __typeof (ns_samename) __libc_ns_samename;
|
||||
libc_hidden_proto (__libc_ns_samename)
|
||||
|
||||
+/* Packet parser helper functions. */
|
||||
+
|
||||
+/* Verify that P points to an uncompressed domain name in wire format.
|
||||
+ On success, return the length of the encoded name, including the
|
||||
+ terminating null byte. On failure, return -1 and set errno. EOM
|
||||
+ must point one past the last byte in the packet. */
|
||||
+int __ns_name_length_uncompressed (const unsigned char *p,
|
||||
+ const unsigned char *eom) attribute_hidden;
|
||||
# endif /* !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 0b4fa30716af3b8a..308f18622a04965a 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -40,6 +40,7 @@ routines := \
|
||||
inet_pton \
|
||||
ns_makecanon \
|
||||
ns_name_compress \
|
||||
+ ns_name_length_uncompressed \
|
||||
ns_name_ntop \
|
||||
ns_name_pack \
|
||||
ns_name_pton \
|
||||
@@ -112,6 +113,10 @@ tests-static += tst-resolv-txnid-collision
|
||||
tests-internal += tst-ns_samebinaryname
|
||||
tests-static += tst-ns_samebinaryname
|
||||
|
||||
+# Likewise for __ns_name_length_uncompressed.
|
||||
+tests-internal += tst-ns_name_length_uncompressed
|
||||
+tests-static += tst-ns_name_length_uncompressed
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_name_length_uncompressed.c b/resolv/ns_name_length_uncompressed.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..51296b47efbf1849
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_name_length_uncompressed.c
|
||||
@@ -0,0 +1,72 @@
|
||||
+/* Skip over an uncompressed name in wire format.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
+int
|
||||
+__ns_name_length_uncompressed (const unsigned char *p,
|
||||
+ const unsigned char *eom)
|
||||
+{
|
||||
+ const unsigned char *start = p;
|
||||
+
|
||||
+ while (true)
|
||||
+ {
|
||||
+ if (p == eom)
|
||||
+ {
|
||||
+ /* Truncated packet: no room for label length. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ unsigned char b = *p;
|
||||
+ ++p;
|
||||
+ if (b == 0)
|
||||
+ {
|
||||
+ /* Root label. */
|
||||
+ size_t length = p - start;
|
||||
+ if (length > NS_MAXCDNAME)
|
||||
+ {
|
||||
+ /* Domain name too long. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return length;
|
||||
+ }
|
||||
+
|
||||
+ if (b <= 63)
|
||||
+ {
|
||||
+ /* Regular label. */
|
||||
+ if (b <= eom - p)
|
||||
+ p += b;
|
||||
+ else
|
||||
+ {
|
||||
+ /* Truncated packet: label incomplete. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Compression reference or corrupted label length. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_name_length_uncompressed.c b/resolv/tst-ns_name_length_uncompressed.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c4a2904db75d1221
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_name_length_uncompressed.c
|
||||
@@ -0,0 +1,135 @@
|
||||
+/* Test __ns_name_length_uncompressed.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+
|
||||
+/* Reference implementation based on other building blocks. */
|
||||
+static int
|
||||
+reference_length (const unsigned char *p, const unsigned char *eom)
|
||||
+{
|
||||
+ unsigned char buf[NS_MAXCDNAME];
|
||||
+ int n = __ns_name_unpack (p, eom, p, buf, sizeof (buf));
|
||||
+ if (n < 0)
|
||||
+ return n;
|
||||
+ const unsigned char *q = buf;
|
||||
+ if (__ns_name_skip (&q, array_end (buf)) < 0)
|
||||
+ return -1;
|
||||
+ if (q - buf != n)
|
||||
+ /* Compressed name. */
|
||||
+ return -1;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ {
|
||||
+ unsigned char buf[] = { 3, 'w', 'w', 'w', 0, 0, 0 };
|
||||
+ TEST_COMPARE (reference_length (buf, array_end (buf)), sizeof (buf) - 2);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)),
|
||||
+ sizeof (buf) - 2);
|
||||
+ TEST_COMPARE (reference_length (array_end (buf) - 1, array_end (buf)), 1);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (array_end (buf) - 1,
|
||||
+ array_end (buf)), 1);
|
||||
+ buf[4] = 0xc0; /* Forward compression reference. */
|
||||
+ buf[5] = 0x06;
|
||||
+ TEST_COMPARE (reference_length (buf, array_end (buf)), -1);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), -1);
|
||||
+ }
|
||||
+
|
||||
+ struct support_next_to_fault ntf = support_next_to_fault_allocate (300);
|
||||
+
|
||||
+ /* Buffer region with all possible bytes at start and end. */
|
||||
+ for (int length = 1; length <= 300; ++length)
|
||||
+ {
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+ memset (start, 'X', length);
|
||||
+ for (int first = 0; first <= 255; ++first)
|
||||
+ {
|
||||
+ *start = first;
|
||||
+ for (int last = 0; last <= 255; ++last)
|
||||
+ {
|
||||
+ start[length - 1] = last;
|
||||
+ TEST_COMPARE (reference_length (start, end),
|
||||
+ __ns_name_length_uncompressed (start, end));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Poor man's fuzz testing: patch two bytes. */
|
||||
+ {
|
||||
+ unsigned char ref[] =
|
||||
+ {
|
||||
+ 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'n', 'e', 't', 0, 0, 0
|
||||
+ };
|
||||
+ TEST_COMPARE (reference_length (ref, array_end (ref)), 13);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (ref, array_end (ref)), 13);
|
||||
+
|
||||
+ int good = 0;
|
||||
+ int bad = 0;
|
||||
+ for (int length = 1; length <= sizeof (ref); ++length)
|
||||
+ {
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+ memcpy (start, ref, length);
|
||||
+
|
||||
+ for (int patch1_pos = 0; patch1_pos < length; ++patch1_pos)
|
||||
+ {
|
||||
+ for (int patch1_value = 0; patch1_value <= 255; ++patch1_value)
|
||||
+ {
|
||||
+ start[patch1_pos] = patch1_value;
|
||||
+ for (int patch2_pos = 0; patch2_pos < length; ++patch2_pos)
|
||||
+ {
|
||||
+ for (int patch2_value = 0; patch2_value <= 255;
|
||||
+ ++patch2_value)
|
||||
+ {
|
||||
+ start[patch2_pos] = patch2_value;
|
||||
+ int expected = reference_length (start, end);
|
||||
+ errno = EINVAL;
|
||||
+ int actual
|
||||
+ = __ns_name_length_uncompressed (start, end);
|
||||
+ if (actual > 0)
|
||||
+ ++good;
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_COMPARE (errno, EMSGSIZE);
|
||||
+ ++bad;
|
||||
+ }
|
||||
+ TEST_COMPARE (expected, actual);
|
||||
+ }
|
||||
+ start[patch2_pos] = ref[patch2_pos];
|
||||
+ }
|
||||
+ }
|
||||
+ start[patch1_pos] = ref[patch1_pos];
|
||||
+ }
|
||||
+ }
|
||||
+ printf ("info: patched inputs with success: %d\n", good);
|
||||
+ printf ("info: patched inputs with failure: %d\n", bad);
|
||||
+ }
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
532
glibc-upstream-2.34-321.patch
Normal file
532
glibc-upstream-2.34-321.patch
Normal file
@ -0,0 +1,532 @@
|
||||
commit e7c03f47651bd451ebf2c3c65899491d0bf7167e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add DNS packet parsing helpers geared towards wire format
|
||||
|
||||
The public parser functions around the ns_rr record type produce
|
||||
textual domain names, but usually, this is not what we need while
|
||||
parsing DNS packets within glibc. This commit adds two new helper
|
||||
functions, __ns_rr_cursor_init and __ns_rr_cursor_next, for writing
|
||||
packet parsers, and struct ns_rr_cursor, struct ns_rr_wire as
|
||||
supporting types.
|
||||
|
||||
In theory, it is possible to avoid copying the owner name
|
||||
into the rname field in __ns_rr_cursor_next, but this would need
|
||||
more functions that work on compressed names.
|
||||
|
||||
Eventually, __res_context_send could be enhanced to preserve the
|
||||
result of the packet parsing that is necessary for matching the
|
||||
incoming UDP packets, so that this works does not have to be done
|
||||
twice.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 857c890d9b42c50c8a94b76d47d4a61ab6d2f49c)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index 6e4808f00d60caf9..c27e7886b7891997 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -103,5 +103,97 @@ libc_hidden_proto (__libc_ns_samename)
|
||||
must point one past the last byte in the packet. */
|
||||
int __ns_name_length_uncompressed (const unsigned char *p,
|
||||
const unsigned char *eom) attribute_hidden;
|
||||
+
|
||||
+/* Iterator over the resource records in a DNS packet. */
|
||||
+struct ns_rr_cursor
|
||||
+{
|
||||
+ /* These members are not changed after initialization. */
|
||||
+ const unsigned char *begin; /* First byte of packet. */
|
||||
+ const unsigned char *end; /* One past the last byte of the packet. */
|
||||
+ const unsigned char *first_rr; /* First resource record (or packet end). */
|
||||
+
|
||||
+ /* Advanced towards the end while reading the packet. */
|
||||
+ const unsigned char *current;
|
||||
+};
|
||||
+
|
||||
+/* Returns the RCODE field from the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_rcode (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[3] & 0x0f; /* Lower 4 bits at offset 3. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the answer section according to the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_ancount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[6] * 256 + c->begin[7]; /* 16 bits at offset 6. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the authority (name server) section according
|
||||
+ to the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_nscount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[8] * 256 + c->begin[9]; /* 16 bits at offset 8. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the additional data section according to the
|
||||
+ DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_adcount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[10] * 256 + c->begin[11]; /* 16 bits at offset 10. */
|
||||
+}
|
||||
+
|
||||
+/* Returns a pointer to the uncompressed question name in wire
|
||||
+ format. */
|
||||
+static inline const unsigned char *
|
||||
+ns_rr_cursor_qname (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin + 12; /* QNAME starts right after the header. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the question type of the first and only question. */
|
||||
+static inline const int
|
||||
+ns_rr_cursor_qtype (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ /* 16 bits 4 bytes back from the first RR header start. */
|
||||
+ return c->first_rr[-4] * 256 + c->first_rr[-3];
|
||||
+}
|
||||
+
|
||||
+/* Returns the clss of the first and only question (usally C_IN). */
|
||||
+static inline const int
|
||||
+ns_rr_cursor_qclass (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ /* 16 bits 2 bytes back from the first RR header start. */
|
||||
+ return c->first_rr[-2] * 256 + c->first_rr[-1];
|
||||
+}
|
||||
+
|
||||
+/* Initializes *C to cover the packet [BUF, BUF+LEN). Returns false
|
||||
+ if LEN is less than sizeof (*HD), if the packet does not contain a
|
||||
+ full (uncompressed) question, or if the question count is not 1. */
|
||||
+_Bool __ns_rr_cursor_init (struct ns_rr_cursor *c,
|
||||
+ const unsigned char *buf, size_t len)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+/* Like ns_rr, but the record owner name is not decoded into text format. */
|
||||
+struct ns_rr_wire
|
||||
+{
|
||||
+ unsigned char rname[NS_MAXCDNAME]; /* Owner name of the record. */
|
||||
+ uint16_t rtype; /* Resource record type (T_*). */
|
||||
+ uint16_t rclass; /* Resource record class (C_*). */
|
||||
+ uint32_t ttl; /* Time-to-live field. */
|
||||
+ const unsigned char *rdata; /* Start of resource record data. */
|
||||
+ uint16_t rdlength; /* Length of the data at rdata, in bytes. */
|
||||
+};
|
||||
+
|
||||
+/* Attempts to parse the record at C into *RR. On success, return
|
||||
+ true, and C is advanced past the record, and RR->rdata points to
|
||||
+ the record data. On failure, errno is set to EMSGSIZE, and false
|
||||
+ is returned. */
|
||||
+_Bool __ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
# endif /* !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 308f18622a04965a..fded244d61068060 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -47,6 +47,8 @@ routines := \
|
||||
ns_name_skip \
|
||||
ns_name_uncompress \
|
||||
ns_name_unpack \
|
||||
+ ns_rr_cursor_init \
|
||||
+ ns_rr_cursor_next \
|
||||
ns_samebinaryname \
|
||||
ns_samename \
|
||||
nsap_addr \
|
||||
@@ -117,6 +119,10 @@ tests-static += tst-ns_samebinaryname
|
||||
tests-internal += tst-ns_name_length_uncompressed
|
||||
tests-static += tst-ns_name_length_uncompressed
|
||||
|
||||
+# Likewise for struct ns_rr_cursor and its functions.
|
||||
+tests-internal += tst-ns_rr_cursor
|
||||
+tests-static += tst-ns_rr_cursor
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_rr_cursor_init.c b/resolv/ns_rr_cursor_init.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6ee80b30e927ecb7
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_rr_cursor_init.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Initialize a simple DNS packet parser.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+bool
|
||||
+__ns_rr_cursor_init (struct ns_rr_cursor *c,
|
||||
+ const unsigned char *buf, size_t len)
|
||||
+{
|
||||
+ c->begin = buf;
|
||||
+ c->end = buf + len;
|
||||
+
|
||||
+ /* Check for header size and 16-bit question count value (it must be 1). */
|
||||
+ if (len < 12 || buf[4] != 0 || buf[5] != 1)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current = buf + 12;
|
||||
+
|
||||
+ int consumed = __ns_name_length_uncompressed (c->current, c->end);
|
||||
+ if (consumed < 0)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ c->first_rr = NULL;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += consumed;
|
||||
+
|
||||
+ /* Ensure there is room for question type and class. */
|
||||
+ if (c->end - c->current < 4)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ c->first_rr = NULL;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += 4;
|
||||
+ c->first_rr = c->current;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
diff --git a/resolv/ns_rr_cursor_next.c b/resolv/ns_rr_cursor_next.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..33652fc5da322d69
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_rr_cursor_next.c
|
||||
@@ -0,0 +1,74 @@
|
||||
+/* Simple DNS record parser without textual name decoding.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+bool
|
||||
+__ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
|
||||
+{
|
||||
+ rr->rdata = NULL;
|
||||
+
|
||||
+ /* Extract the record owner name. */
|
||||
+ int consumed = __ns_name_unpack (c->begin, c->end, c->current,
|
||||
+ rr->rname, sizeof (rr->rname));
|
||||
+ if (consumed < 0)
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += consumed;
|
||||
+
|
||||
+ /* Extract the metadata. */
|
||||
+ struct
|
||||
+ {
|
||||
+ uint16_t rtype;
|
||||
+ uint16_t rclass;
|
||||
+ uint32_t ttl;
|
||||
+ uint16_t rdlength;
|
||||
+ } __attribute__ ((packed)) metadata;
|
||||
+ _Static_assert (sizeof (metadata) == 10, "sizeof metadata");
|
||||
+ if (c->end - c->current < sizeof (metadata))
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ memcpy (&metadata, c->current, sizeof (metadata));
|
||||
+ c->current += sizeof (metadata);
|
||||
+ /* Endianess conversion. */
|
||||
+ rr->rtype = ntohs (metadata.rtype);
|
||||
+ rr->rclass = ntohs (metadata.rclass);
|
||||
+ rr->ttl = ntohl (metadata.ttl);
|
||||
+ rr->rdlength = ntohs (metadata.rdlength);
|
||||
+
|
||||
+ /* Extract record data. */
|
||||
+ if (c->end - c->current < rr->rdlength)
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ rr->rdata = c->current;
|
||||
+ c->current += rr->rdlength;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_rr_cursor.c b/resolv/tst-ns_rr_cursor.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c3c09089053d0c40
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_rr_cursor.c
|
||||
@@ -0,0 +1,227 @@
|
||||
+/* Tests for resource record parsing.
|
||||
+ 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 <arpa/nameser.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+
|
||||
+/* Reference packet for packet parsing. */
|
||||
+static const unsigned char valid_packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x01, /* Question count. */
|
||||
+ 0x00, 0x02, /* Answer count. */
|
||||
+ 0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
|
||||
+ 0x00, 0x1c, /* Question type: AAAA. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ 0xc0, 0x0c, /* Compression reference to QNAME. */
|
||||
+ 0x00, 0x1c, /* Record type: AAAA. */
|
||||
+ 0x00, 0x01, /* Record class: IN. */
|
||||
+ 0x12, 0x34, 0x56, 0x78, /* Record TTL. */
|
||||
+ 0x00, 0x10, /* Record data length (16 bytes). */
|
||||
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */
|
||||
+ 0xc0, 0x0c, /* Compression reference to QNAME. */
|
||||
+ 0x00, 0x1c, /* Record type: AAAA. */
|
||||
+ 0x00, 0x01, /* Record class: IN. */
|
||||
+ 0x11, 0x33, 0x55, 0x77, /* Record TTL. */
|
||||
+ 0x00, 0x10, /* Record data length (16 bytes). */
|
||||
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */
|
||||
+ };
|
||||
+
|
||||
+/* Special offsets in valid_packet. */
|
||||
+enum
|
||||
+ {
|
||||
+ offset_of_first_record = 29,
|
||||
+ offset_of_second_record = 57,
|
||||
+ };
|
||||
+
|
||||
+/* Check that parsing valid_packet succeeds. */
|
||||
+static void
|
||||
+test_valid (void)
|
||||
+{
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet,
|
||||
+ sizeof (valid_packet)));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - valid_packet, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x12345678);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
|
||||
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
|
||||
+ TEST_COMPARE (c.current - valid_packet, offset_of_second_record);
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x11335577);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
|
||||
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
|
||||
+ TEST_VERIFY (c.current == c.end);
|
||||
+}
|
||||
+
|
||||
+/* Check that trying to parse a packet with a compressed QNAME fails. */
|
||||
+static void
|
||||
+test_compressed_qname (void)
|
||||
+{
|
||||
+ static const unsigned char packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x01, /* Question count. */
|
||||
+ 0x00, 0x00, /* Answer count. */
|
||||
+ 0x00, 0x00, 0x00, 0x00, /* Other counts. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x01, /* Question type: A. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ };
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
|
||||
+}
|
||||
+
|
||||
+/* Check that trying to parse a packet with two questions fails. */
|
||||
+static void
|
||||
+test_two_questions (void)
|
||||
+{
|
||||
+ static const unsigned char packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x02, /* Question count. */
|
||||
+ 0x00, 0x00, /* Answer count. */
|
||||
+ 0x00, 0x00, 0x00, 0x00, /* Other counts. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x01, /* Question type: A. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x1c, /* Question type: AAAA. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ };
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
|
||||
+}
|
||||
+
|
||||
+/* Used to check that parsing truncated packets does not over-read. */
|
||||
+static struct support_next_to_fault ntf;
|
||||
+
|
||||
+/* Truncated packet in the second resource record. */
|
||||
+static void
|
||||
+test_truncated_one_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x12345678);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
|
||||
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_second_record);
|
||||
+ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
|
||||
+}
|
||||
+
|
||||
+/* Truncated packet in the first resource record. */
|
||||
+static void
|
||||
+test_truncated_no_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
|
||||
+}
|
||||
+
|
||||
+/* Truncated packet before first resource record. */
|
||||
+static void
|
||||
+test_truncated_before_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ ntf = support_next_to_fault_allocate (sizeof (valid_packet));
|
||||
+
|
||||
+ test_valid ();
|
||||
+ test_compressed_qname ();
|
||||
+ test_two_questions ();
|
||||
+
|
||||
+ for (int length = offset_of_second_record; length < sizeof (valid_packet);
|
||||
+ ++length)
|
||||
+ test_truncated_one_rr (length);
|
||||
+ for (int length = offset_of_first_record; length < offset_of_second_record;
|
||||
+ ++length)
|
||||
+ test_truncated_no_rr (length);
|
||||
+ for (int length = 0; length < offset_of_first_record; ++length)
|
||||
+ test_truncated_before_rr (length);
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
447
glibc-upstream-2.34-322.patch
Normal file
447
glibc-upstream-2.34-322.patch
Normal file
@ -0,0 +1,447 @@
|
||||
commit d9c979abf9307ef3e27dbe65317430977bb322c7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Split getanswer_ptr from getanswer_r
|
||||
|
||||
And expand the use of name_ok and qtype in getanswer_ptr (the
|
||||
former also in getanswer_r).
|
||||
|
||||
After further cleanups, not much code will be shared between the
|
||||
two functions.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 0dcc43e9981005540bf39dc7bf33fbab62cf9e84)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 6e83fca1c5b1f98c..a6bf73a091968358 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -117,6 +117,11 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
int map, int32_t *ttlp, char **canonp);
|
||||
+static enum nss_status getanswer_ptr (const querybuf *answer, int anslen,
|
||||
+ const char *qname,
|
||||
+ struct hostent *result, char *buffer,
|
||||
+ size_t buflen, int *errnop,
|
||||
+ int *h_errnop, int32_t *ttlp);
|
||||
|
||||
static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
|
||||
const querybuf *answer2, int anslen2,
|
||||
@@ -562,9 +567,8 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
|
||||
- errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
|
||||
+ status = getanswer_ptr (host_buffer.buf, n, qbuf, result,
|
||||
+ buffer, buflen, errnop, h_errnop, ttlp);
|
||||
if (host_buffer.buf != orig_host_buffer)
|
||||
free (host_buffer.buf);
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
@@ -660,8 +664,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
int haveanswer, had_error;
|
||||
char *bp, **ap, **hap;
|
||||
char tbuf[MAXDNAME];
|
||||
- const char *tname;
|
||||
- int (*name_ok) (const char *);
|
||||
u_char packtmp[NS_MAXCDNAME];
|
||||
int have_to_map = 0;
|
||||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
@@ -680,22 +682,8 @@ getanswer_r (struct resolv_context *ctx,
|
||||
if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
linebuflen = INT_MAX;
|
||||
|
||||
- tname = qname;
|
||||
result->h_name = NULL;
|
||||
end_of_message = answer->buf + anslen;
|
||||
- switch (qtype)
|
||||
- {
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- name_ok = __libc_res_hnok;
|
||||
- break;
|
||||
- case T_PTR:
|
||||
- name_ok = __libc_res_dnok;
|
||||
- break;
|
||||
- default:
|
||||
- *errnop = ENOENT;
|
||||
- return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
|
||||
- }
|
||||
|
||||
/*
|
||||
* find first satisfactory answer
|
||||
@@ -730,7 +718,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- if (__glibc_unlikely (name_ok (bp) == 0))
|
||||
+ if (__glibc_unlikely (__libc_res_hnok (bp) == 0))
|
||||
{
|
||||
errno = EBADMSG;
|
||||
*errnop = EBADMSG;
|
||||
@@ -784,7 +772,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
n = -1;
|
||||
}
|
||||
|
||||
- if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -817,7 +805,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
|
||||
- if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
|
||||
+ if (type == T_CNAME)
|
||||
{
|
||||
/* A CNAME could also have a TTL entry. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
@@ -827,7 +815,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -858,7 +846,260 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (qtype == T_PTR && type == T_CNAME)
|
||||
+ if (type == T_A && qtype == T_AAAA && map)
|
||||
+ have_to_map = 1;
|
||||
+ else if (__glibc_unlikely (type != qtype))
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ switch (type)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ case T_AAAA:
|
||||
+ if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ /* Stop parsing at a record whose length is incorrect. */
|
||||
+ if (n != rrtype_to_rdata_length (type))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip records of the wrong type. */
|
||||
+ if (n != result->h_length)
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!haveanswer)
|
||||
+ {
|
||||
+ int nn;
|
||||
+
|
||||
+ /* 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;
|
||||
+ if (canonp != NULL)
|
||||
+ *canonp = bp;
|
||||
+ result->h_name = bp;
|
||||
+ nn = strlen (bp) + 1; /* for the \0 */
|
||||
+ bp += nn;
|
||||
+ linebuflen -= nn;
|
||||
+ }
|
||||
+
|
||||
+ /* Provide sufficient alignment for both address
|
||||
+ families. */
|
||||
+ enum { align = 4 };
|
||||
+ _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
+ "struct in_addr alignment");
|
||||
+ _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
+ "struct in6_addr alignment");
|
||||
+ {
|
||||
+ char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
+ linebuflen -= new_bp - bp;
|
||||
+ bp = new_bp;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n > linebuflen))
|
||||
+ goto too_small;
|
||||
+ bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
+ cp += n;
|
||||
+ linebuflen -= n;
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ if (had_error == 0)
|
||||
+ ++haveanswer;
|
||||
+ }
|
||||
+
|
||||
+ if (haveanswer > 0)
|
||||
+ {
|
||||
+ *ap = NULL;
|
||||
+ *hap = NULL;
|
||||
+ /*
|
||||
+ * Note: we sort even if host can take only one address
|
||||
+ * in its return structures - should give it the "best"
|
||||
+ * address in that case, not some random one
|
||||
+ */
|
||||
+ if (haveanswer > 1 && qtype == T_A
|
||||
+ && __resolv_context_sort_count (ctx) > 0)
|
||||
+ addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
+
|
||||
+ if (result->h_name == NULL)
|
||||
+ {
|
||||
+ n = strlen (qname) + 1; /* For the \0. */
|
||||
+ if (n > linebuflen)
|
||||
+ goto too_small;
|
||||
+ if (n >= MAXHOSTNAMELEN)
|
||||
+ goto no_recovery;
|
||||
+ result->h_name = bp;
|
||||
+ bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
+ linebuflen -= n;
|
||||
+ }
|
||||
+
|
||||
+ if (have_to_map)
|
||||
+ if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
+ goto too_small;
|
||||
+ *h_errnop = NETDB_SUCCESS;
|
||||
+ return NSS_STATUS_SUCCESS;
|
||||
+ }
|
||||
+ no_recovery:
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ *errnop = ENOENT;
|
||||
+ /* 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. */
|
||||
+ return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
+ ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
+}
|
||||
+
|
||||
+static enum nss_status
|
||||
+getanswer_ptr (const querybuf *answer, int anslen, const char *qname,
|
||||
+ struct hostent *result, char *buffer, size_t buflen,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
+{
|
||||
+ struct host_data
|
||||
+ {
|
||||
+ char *aliases[MAX_NR_ALIASES];
|
||||
+ unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
+ char *h_addr_ptrs[0];
|
||||
+ } *host_data;
|
||||
+ int linebuflen;
|
||||
+ const HEADER *hp;
|
||||
+ const u_char *end_of_message, *cp;
|
||||
+ int n, ancount, qdcount;
|
||||
+ int haveanswer, had_error;
|
||||
+ char *bp, **ap, **hap;
|
||||
+ char tbuf[MAXDNAME];
|
||||
+ const char *tname;
|
||||
+ u_char packtmp[NS_MAXCDNAME];
|
||||
+ uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
+ buffer += pad;
|
||||
+ buflen = buflen > pad ? buflen - pad : 0;
|
||||
+ if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
+ {
|
||||
+ /* The buffer is too small. */
|
||||
+ too_small:
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ host_data = (struct host_data *) buffer;
|
||||
+ linebuflen = buflen - sizeof (struct host_data);
|
||||
+ if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
+ linebuflen = INT_MAX;
|
||||
+
|
||||
+ tname = qname;
|
||||
+ result->h_name = NULL;
|
||||
+ end_of_message = answer->buf + anslen;
|
||||
+
|
||||
+ /*
|
||||
+ * find first satisfactory answer
|
||||
+ */
|
||||
+ hp = &answer->hdr;
|
||||
+ ancount = ntohs (hp->ancount);
|
||||
+ qdcount = ntohs (hp->qdcount);
|
||||
+ cp = answer->buf + HFIXEDSZ;
|
||||
+ if (__glibc_unlikely (qdcount != 1))
|
||||
+ {
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
+ goto too_small;
|
||||
+ bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
+ linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
+
|
||||
+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
+ packtmp, sizeof packtmp);
|
||||
+ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ {
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
+ goto too_small;
|
||||
+
|
||||
+ n = -1;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ if (__glibc_unlikely (__libc_res_dnok (bp) == 0))
|
||||
+ {
|
||||
+ errno = EBADMSG;
|
||||
+ *errnop = EBADMSG;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ cp += n + QFIXEDSZ;
|
||||
+
|
||||
+ ap = host_data->aliases;
|
||||
+ *ap = NULL;
|
||||
+ result->h_aliases = host_data->aliases;
|
||||
+ hap = host_data->h_addr_ptrs;
|
||||
+ *hap = NULL;
|
||||
+ result->h_addr_list = host_data->h_addr_ptrs;
|
||||
+ haveanswer = 0;
|
||||
+ had_error = 0;
|
||||
+
|
||||
+ while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ {
|
||||
+ int type, class;
|
||||
+
|
||||
+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
+ packtmp, sizeof packtmp);
|
||||
+ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ {
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
+ goto too_small;
|
||||
+
|
||||
+ n = -1;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+ cp += n; /* name */
|
||||
+
|
||||
+ if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ NS_GET16 (type, cp);
|
||||
+ NS_GET16 (class, cp);
|
||||
+ int32_t ttl;
|
||||
+ NS_GET32 (ttl, cp);
|
||||
+ NS_GET16 (n, cp); /* RDATA length. */
|
||||
+
|
||||
+ if (end_of_message - cp < n)
|
||||
+ {
|
||||
+ /* RDATA extends beyond the end of the packet. */
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (class != C_IN))
|
||||
+ {
|
||||
+ /* XXX - debug? syslog? */
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ if (type == T_CNAME)
|
||||
{
|
||||
/* A CNAME could also have a TTL entry. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
@@ -887,14 +1128,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (type == T_A && qtype == T_AAAA && map)
|
||||
- have_to_map = 1;
|
||||
- else if (__glibc_unlikely (type != qtype))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
switch (type)
|
||||
{
|
||||
case T_PTR:
|
||||
@@ -956,8 +1189,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
TTL in the chain. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
*ttlp = ttl;
|
||||
- if (canonp != NULL)
|
||||
- *canonp = bp;
|
||||
result->h_name = bp;
|
||||
nn = strlen (bp) + 1; /* for the \0 */
|
||||
bp += nn;
|
||||
@@ -984,7 +1215,8 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
break;
|
||||
default:
|
||||
- abort ();
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
if (had_error == 0)
|
||||
++haveanswer;
|
||||
@@ -994,14 +1226,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
{
|
||||
*ap = NULL;
|
||||
*hap = NULL;
|
||||
- /*
|
||||
- * Note: we sort even if host can take only one address
|
||||
- * in its return structures - should give it the "best"
|
||||
- * address in that case, not some random one
|
||||
- */
|
||||
- if (haveanswer > 1 && qtype == T_A
|
||||
- && __resolv_context_sort_count (ctx) > 0)
|
||||
- addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
|
||||
if (result->h_name == NULL)
|
||||
{
|
||||
@@ -1015,23 +1239,15 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
}
|
||||
|
||||
- if (have_to_map)
|
||||
- if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
- goto too_small;
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
no_recovery:
|
||||
*h_errnop = NO_RECOVERY;
|
||||
*errnop = ENOENT;
|
||||
- /* 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. */
|
||||
- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
-
|
||||
static enum nss_status
|
||||
gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
struct gaih_addrtuple ***patp,
|
507
glibc-upstream-2.34-323.patch
Normal file
507
glibc-upstream-2.34-323.patch
Normal file
@ -0,0 +1,507 @@
|
||||
commit 32e5db37684ffcbc6ae34fcc6cdcf28670506baa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr
|
||||
|
||||
The simplification takes advantage of the split from getanswer_r.
|
||||
It fixes various aliases issues, and optimizes NSS buffer usage.
|
||||
The new DNS packet parsing helpers are used, too.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit e32547d661a43da63368e488b6cfa9c53b4dcf92)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index a6bf73a091968358..2cd7170f20b60588 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -70,6 +70,7 @@
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
+#include <alloc_buffer.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -117,10 +118,9 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
int map, int32_t *ttlp, char **canonp);
|
||||
-static enum nss_status getanswer_ptr (const querybuf *answer, int anslen,
|
||||
- const char *qname,
|
||||
- struct hostent *result, char *buffer,
|
||||
- size_t buflen, int *errnop,
|
||||
+static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ char **hnamep, int *errnop,
|
||||
int *h_errnop, int32_t *ttlp);
|
||||
|
||||
static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
|
||||
@@ -457,36 +457,21 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
|
||||
static const u_char v6local[] = { 0,0, 0,1 };
|
||||
const u_char *uaddr = (const u_char *)addr;
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[MAX_NR_ADDRS + 1];
|
||||
- char linebuffer[0];
|
||||
- } *host_data = (struct host_data *) buffer;
|
||||
- union
|
||||
- {
|
||||
- querybuf *buf;
|
||||
- u_char *ptr;
|
||||
- } host_buffer;
|
||||
- querybuf *orig_host_buffer;
|
||||
char qbuf[MAXDNAME+1], *qp = NULL;
|
||||
size_t size;
|
||||
int n, status;
|
||||
int olderr = errno;
|
||||
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
-
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
-
|
||||
- host_data = (struct host_data *) buffer;
|
||||
+ /* Prepare the allocation buffer. Store the pointer array first, to
|
||||
+ benefit from buffer alignment. */
|
||||
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
|
||||
+ char **address_array = alloc_buffer_alloc_array (&abuf, char *, 2);
|
||||
+ if (address_array == NULL)
|
||||
+ {
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
|
||||
struct resolv_context *ctx = __resolv_context_get ();
|
||||
if (ctx == NULL)
|
||||
@@ -530,8 +515,6 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
|
||||
-
|
||||
switch (af)
|
||||
{
|
||||
case AF_INET:
|
||||
@@ -555,35 +538,52 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
break;
|
||||
}
|
||||
|
||||
- n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
|
||||
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
+ unsigned char dns_packet_buffer[1024];
|
||||
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
|
||||
+ n = __res_context_query (ctx, qbuf, C_IN, T_PTR,
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ &alt_dns_packet_buffer,
|
||||
+ NULL, NULL, NULL, NULL);
|
||||
if (n < 0)
|
||||
{
|
||||
*h_errnop = h_errno;
|
||||
__set_errno (olderr);
|
||||
- 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 errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- status = getanswer_ptr (host_buffer.buf, n, qbuf, result,
|
||||
- buffer, buflen, errnop, h_errnop, ttlp);
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ status = getanswer_ptr (alt_dns_packet_buffer, n,
|
||||
+ &abuf, &result->h_name, errnop, h_errnop, ttlp);
|
||||
+
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
+ __resolv_context_put (ctx);
|
||||
+
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
- {
|
||||
- __resolv_context_put (ctx);
|
||||
- return status;
|
||||
- }
|
||||
+ return status;
|
||||
|
||||
+ /* result->h_name has already been set by getanswer_ptr. */
|
||||
result->h_addrtype = af;
|
||||
result->h_length = len;
|
||||
- memcpy (host_data->host_addr, addr, len);
|
||||
- host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
|
||||
- host_data->h_addr_ptrs[1] = NULL;
|
||||
+ /* Increase the alignment to 4, in case there are applications out
|
||||
+ there that expect at least this level of address alignment. */
|
||||
+ address_array[0] = (char *) alloc_buffer_next (&abuf, uint32_t);
|
||||
+ alloc_buffer_copy_bytes (&abuf, uaddr, len);
|
||||
+ address_array[1] = NULL;
|
||||
+
|
||||
+ /* This check also covers allocation failure in getanswer_ptr. */
|
||||
+ if (alloc_buffer_has_failed (&abuf))
|
||||
+ {
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ result->h_addr_list = address_array;
|
||||
+ result->h_aliases = &address_array[1]; /* Points to NULL. */
|
||||
+
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
- __resolv_context_put (ctx);
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
libc_hidden_def (_nss_dns_gethostbyaddr2_r)
|
||||
@@ -962,287 +962,86 @@ getanswer_r (struct resolv_context *ctx,
|
||||
}
|
||||
|
||||
static enum nss_status
|
||||
-getanswer_ptr (const querybuf *answer, int anslen, const char *qname,
|
||||
- struct hostent *result, char *buffer, size_t buflen,
|
||||
+getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf, char **hnamep,
|
||||
int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
{
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[0];
|
||||
- } *host_data;
|
||||
- int linebuflen;
|
||||
- const HEADER *hp;
|
||||
- const u_char *end_of_message, *cp;
|
||||
- int n, ancount, qdcount;
|
||||
- int haveanswer, had_error;
|
||||
- char *bp, **ap, **hap;
|
||||
- char tbuf[MAXDNAME];
|
||||
- const char *tname;
|
||||
- u_char packtmp[NS_MAXCDNAME];
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- /* The buffer is too small. */
|
||||
- too_small:
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- host_data = (struct host_data *) buffer;
|
||||
- linebuflen = buflen - sizeof (struct host_data);
|
||||
- if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
- linebuflen = INT_MAX;
|
||||
-
|
||||
- tname = qname;
|
||||
- result->h_name = NULL;
|
||||
- end_of_message = answer->buf + anslen;
|
||||
-
|
||||
- /*
|
||||
- * find first satisfactory answer
|
||||
- */
|
||||
- hp = &answer->hdr;
|
||||
- ancount = ntohs (hp->ancount);
|
||||
- qdcount = ntohs (hp->qdcount);
|
||||
- cp = answer->buf + HFIXEDSZ;
|
||||
- if (__glibc_unlikely (qdcount != 1))
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
- goto too_small;
|
||||
- bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
- linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ struct ns_rr_cursor c;
|
||||
+ if (!__ns_rr_cursor_init (&c, packet, packetlen))
|
||||
{
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- *errnop = errno;
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (__glibc_unlikely (__libc_res_dnok (bp) == 0))
|
||||
- {
|
||||
- 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;
|
||||
+ 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];
|
||||
|
||||
- ap = host_data->aliases;
|
||||
- *ap = NULL;
|
||||
- result->h_aliases = host_data->aliases;
|
||||
- hap = host_data->h_addr_ptrs;
|
||||
- *hap = NULL;
|
||||
- result->h_addr_list = host_data->h_addr_ptrs;
|
||||
- haveanswer = 0;
|
||||
- had_error = 0;
|
||||
-
|
||||
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ while (ancount > 0)
|
||||
{
|
||||
- int type, class;
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ struct ns_rr_wire rr;
|
||||
+ if (!__ns_rr_cursor_next (&c, &rr))
|
||||
{
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n; /* name */
|
||||
-
|
||||
- if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- NS_GET16 (type, cp);
|
||||
- NS_GET16 (class, cp);
|
||||
- int32_t ttl;
|
||||
- NS_GET32 (ttl, cp);
|
||||
- NS_GET16 (n, cp); /* RDATA length. */
|
||||
+ /* Skip over records with the wrong class. */
|
||||
+ if (rr.rclass != C_IN)
|
||||
+ continue;
|
||||
|
||||
- if (end_of_message - cp < n)
|
||||
- {
|
||||
- /* RDATA extends beyond the end of the packet. */
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (class != C_IN))
|
||||
- {
|
||||
- /* XXX - debug? syslog? */
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
+ /* Update TTL for known record types. */
|
||||
+ if ((rr.rtype == T_CNAME || rr.rtype == T_PTR)
|
||||
+ && ttlp != NULL && *ttlp > rr.ttl)
|
||||
+ *ttlp = rr.ttl;
|
||||
|
||||
- if (type == T_CNAME)
|
||||
+ if (rr.rtype == T_CNAME)
|
||||
{
|
||||
- /* 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 || __libc_res_dnok (tbuf) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n;
|
||||
- /* Get canonical name. */
|
||||
- n = strlen (tbuf) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
+ /* 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)
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- tname = bp;
|
||||
- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- continue;
|
||||
+ expected_name = name_buffer;
|
||||
}
|
||||
-
|
||||
- switch (type)
|
||||
+ else if (rr.rtype == T_PTR
|
||||
+ && __ns_samebinaryname (rr.rname, expected_name))
|
||||
{
|
||||
- case T_PTR:
|
||||
- if (__glibc_unlikely (__strcasecmp (tname, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
+ /* Decompress the target of the PTR record. This is the
|
||||
+ host name we are looking for. We can only use it if it
|
||||
+ is syntactically valid. Historically, only one host name
|
||||
+ is returned here. If the recursive resolver performs DNS
|
||||
+ record rotation, the returned host name is essentially
|
||||
+ random, which is why multiple PTR records are rarely
|
||||
+ used. Use MAXHOSTNAMELEN instead of NS_MAXCDNAME for
|
||||
+ additional length checking. */
|
||||
+ char hname[MAXHOSTNAMELEN + 1];
|
||||
+ if (__ns_name_unpack (c.begin, c.end, rr.rdata,
|
||||
+ name_buffer, sizeof (name_buffer)) < 0
|
||||
+ || !__res_binary_hnok (expected_name)
|
||||
+ || __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0)
|
||||
{
|
||||
- ++had_error;
|
||||
- break;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
- /* bind would put multiple PTR records as aliases, but we don't do
|
||||
- that. */
|
||||
- result->h_name = bp;
|
||||
- *h_errnop = NETDB_SUCCESS;
|
||||
+ /* Successful allocation is checked by the caller. */
|
||||
+ *hnamep = alloc_buffer_copy_string (abuf, hname);
|
||||
return NSS_STATUS_SUCCESS;
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- /* Stop parsing at a record whose length is incorrect. */
|
||||
- if (n != rrtype_to_rdata_length (type))
|
||||
- {
|
||||
- ++had_error;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Skip records of the wrong type. */
|
||||
- if (n != result->h_length)
|
||||
- {
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
- if (!haveanswer)
|
||||
- {
|
||||
- int nn;
|
||||
-
|
||||
- /* 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;
|
||||
- result->h_name = bp;
|
||||
- nn = strlen (bp) + 1; /* for the \0 */
|
||||
- bp += nn;
|
||||
- linebuflen -= nn;
|
||||
- }
|
||||
-
|
||||
- /* Provide sufficient alignment for both address
|
||||
- families. */
|
||||
- enum { align = 4 };
|
||||
- _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
- "struct in_addr alignment");
|
||||
- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
- "struct in6_addr alignment");
|
||||
- {
|
||||
- char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
- linebuflen -= new_bp - bp;
|
||||
- bp = new_bp;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
- cp += n;
|
||||
- linebuflen -= n;
|
||||
- break;
|
||||
- default:
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
- if (had_error == 0)
|
||||
- ++haveanswer;
|
||||
}
|
||||
|
||||
- if (haveanswer > 0)
|
||||
- {
|
||||
- *ap = NULL;
|
||||
- *hap = NULL;
|
||||
-
|
||||
- if (result->h_name == NULL)
|
||||
- {
|
||||
- n = strlen (qname) + 1; /* For the \0. */
|
||||
- if (n > linebuflen)
|
||||
- goto too_small;
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- goto no_recovery;
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- }
|
||||
+ /* No PTR record found. */
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No caching of negative responses. */
|
||||
+ *ttlp = 0;
|
||||
|
||||
- *h_errnop = NETDB_SUCCESS;
|
||||
- return NSS_STATUS_SUCCESS;
|
||||
- }
|
||||
- no_recovery:
|
||||
*h_errnop = NO_RECOVERY;
|
||||
*errnop = ENOENT;
|
||||
return NSS_STATUS_TRYAGAIN;
|
311
glibc-upstream-2.34-324.patch
Normal file
311
glibc-upstream-2.34-324.patch
Normal file
@ -0,0 +1,311 @@
|
||||
commit 7267341ec1b5c591c2e7946d0604d3cf1423db7d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Remove remnants of IPv6 address mapping
|
||||
|
||||
res_use_inet6 always returns false since commit 3f8b44be0a658266adff5
|
||||
("resolv: Remove support for RES_USE_INET6 and the inet6 option").
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit a7fc30b522a0cd7c8c5e7e285b9531b704e02f04)
|
||||
|
||||
diff --git a/resolv/README b/resolv/README
|
||||
index 514e9bb617e710f1..2146bc3b27a6dc56 100644
|
||||
--- a/resolv/README
|
||||
+++ b/resolv/README
|
||||
@@ -146,6 +146,3 @@ res_libc.c is home-brewn, although parts of it are taken from res_data.c.
|
||||
|
||||
res_hconf.c and res_hconf.h were contributed by David Mosberger, and
|
||||
do not come from BIND.
|
||||
-
|
||||
-The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are
|
||||
-leftovers from BIND 4.9.7.
|
||||
diff --git a/resolv/mapv4v6addr.h b/resolv/mapv4v6addr.h
|
||||
deleted file mode 100644
|
||||
index 7f85f7d5e393ec5f..0000000000000000
|
||||
--- a/resolv/mapv4v6addr.h
|
||||
+++ /dev/null
|
||||
@@ -1,69 +0,0 @@
|
||||
-/*
|
||||
- * ++Copyright++ 1985, 1988, 1993
|
||||
- * -
|
||||
- * Copyright (c) 1985, 1988, 1993
|
||||
- * The Regents of the University of California. All rights reserved.
|
||||
- *
|
||||
- * Redistribution and use in source and binary forms, with or without
|
||||
- * modification, are permitted provided that the following conditions
|
||||
- * are met:
|
||||
- * 1. Redistributions of source code must retain the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer.
|
||||
- * 2. Redistributions in binary form must reproduce the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer in the
|
||||
- * documentation and/or other materials provided with the distribution.
|
||||
- * 4. Neither the name of the University nor the names of its contributors
|
||||
- * may be used to endorse or promote products derived from this software
|
||||
- * without specific prior written permission.
|
||||
- *
|
||||
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- * SUCH DAMAGE.
|
||||
- * -
|
||||
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
- *
|
||||
- * Permission to use, copy, modify, and distribute this software for any
|
||||
- * purpose with or without fee is hereby granted, provided that the above
|
||||
- * copyright notice and this permission notice appear in all copies, and that
|
||||
- * the name of Digital Equipment Corporation not be used in advertising or
|
||||
- * publicity pertaining to distribution of the document or software without
|
||||
- * specific, written prior permission.
|
||||
- *
|
||||
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
- * SOFTWARE.
|
||||
- * -
|
||||
- * --Copyright--
|
||||
- */
|
||||
-
|
||||
-#include <string.h>
|
||||
-#include <arpa/nameser.h>
|
||||
-
|
||||
-static void
|
||||
-map_v4v6_address (const char *src, char *dst)
|
||||
-{
|
||||
- u_char *p = (u_char *) dst;
|
||||
- int i;
|
||||
-
|
||||
- /* Move the IPv4 part to the right position. */
|
||||
- memcpy (dst + 12, src, INADDRSZ);
|
||||
-
|
||||
- /* Mark this ipv6 addr as a mapped ipv4. */
|
||||
- for (i = 0; i < 10; i++)
|
||||
- *p++ = 0x00;
|
||||
- *p++ = 0xff;
|
||||
- *p = 0xff;
|
||||
-}
|
||||
diff --git a/resolv/mapv4v6hostent.h b/resolv/mapv4v6hostent.h
|
||||
deleted file mode 100644
|
||||
index c11038adf33f154d..0000000000000000
|
||||
--- a/resolv/mapv4v6hostent.h
|
||||
+++ /dev/null
|
||||
@@ -1,84 +0,0 @@
|
||||
-/*
|
||||
- * ++Copyright++ 1985, 1988, 1993
|
||||
- * -
|
||||
- * Copyright (c) 1985, 1988, 1993
|
||||
- * The Regents of the University of California. All rights reserved.
|
||||
- *
|
||||
- * Redistribution and use in source and binary forms, with or without
|
||||
- * modification, are permitted provided that the following conditions
|
||||
- * are met:
|
||||
- * 1. Redistributions of source code must retain the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer.
|
||||
- * 2. Redistributions in binary form must reproduce the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer in the
|
||||
- * documentation and/or other materials provided with the distribution.
|
||||
- * 4. Neither the name of the University nor the names of its contributors
|
||||
- * may be used to endorse or promote products derived from this software
|
||||
- * without specific prior written permission.
|
||||
- *
|
||||
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- * SUCH DAMAGE.
|
||||
- * -
|
||||
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
- *
|
||||
- * Permission to use, copy, modify, and distribute this software for any
|
||||
- * purpose with or without fee is hereby granted, provided that the above
|
||||
- * copyright notice and this permission notice appear in all copies, and that
|
||||
- * the name of Digital Equipment Corporation not be used in advertising or
|
||||
- * publicity pertaining to distribution of the document or software without
|
||||
- * specific, written prior permission.
|
||||
- *
|
||||
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
- * SOFTWARE.
|
||||
- * -
|
||||
- * --Copyright--
|
||||
- */
|
||||
-
|
||||
-#include <arpa/nameser.h>
|
||||
-#include <sys/socket.h>
|
||||
-
|
||||
-typedef union {
|
||||
- int32_t al;
|
||||
- char ac;
|
||||
-} align;
|
||||
-
|
||||
-static int
|
||||
-map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
|
||||
-{
|
||||
- char **ap;
|
||||
-
|
||||
- if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
|
||||
- return 0;
|
||||
- hp->h_addrtype = AF_INET6;
|
||||
- hp->h_length = IN6ADDRSZ;
|
||||
- for (ap = hp->h_addr_list; *ap; ap++)
|
||||
- {
|
||||
- int i = sizeof (align) - ((u_long) *bpp % sizeof (align));
|
||||
-
|
||||
- if (*lenp < (i + IN6ADDRSZ))
|
||||
- /* Out of memory. */
|
||||
- return 1;
|
||||
- *bpp += i;
|
||||
- *lenp -= i;
|
||||
- map_v4v6_address (*ap, *bpp);
|
||||
- *ap = *bpp;
|
||||
- *bpp += IN6ADDRSZ;
|
||||
- *lenp -= IN6ADDRSZ;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 2cd7170f20b60588..f8dc5a0a7d1eb156 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -88,10 +88,6 @@
|
||||
#include <resolv/resolv-internal.h>
|
||||
#include <resolv/resolv_context.h>
|
||||
|
||||
-/* Get implementations of some internal functions. */
|
||||
-#include <resolv/mapv4v6addr.h>
|
||||
-#include <resolv/mapv4v6hostent.h>
|
||||
-
|
||||
#define RESOLVSORT
|
||||
|
||||
#if PACKETSZ > 65536
|
||||
@@ -117,7 +113,7 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
const char *qname, int qtype,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
- int map, int32_t *ttlp, char **canonp);
|
||||
+ int32_t *ttlp, char **canonp);
|
||||
static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
struct alloc_buffer *abuf,
|
||||
char **hnamep, int *errnop,
|
||||
@@ -198,7 +194,6 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
char tmp[NS_MAXDNAME];
|
||||
int size, type, n;
|
||||
const char *cp;
|
||||
- int map = 0;
|
||||
int olderr = errno;
|
||||
enum nss_status status;
|
||||
|
||||
@@ -259,32 +254,12 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
*errnop = EAGAIN;
|
||||
else
|
||||
__set_errno (olderr);
|
||||
-
|
||||
- /* If we are looking for an IPv6 address and mapping is enabled
|
||||
- by having the RES_USE_INET6 bit in _res.options set, we try
|
||||
- another lookup. */
|
||||
- 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,
|
||||
- NULL, NULL, NULL, NULL);
|
||||
-
|
||||
- if (n < 0)
|
||||
- {
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
- return status;
|
||||
- }
|
||||
-
|
||||
- map = 1;
|
||||
-
|
||||
- result->h_addrtype = AF_INET;
|
||||
- result->h_length = INADDRSZ;
|
||||
}
|
||||
+ else
|
||||
+ status = getanswer_r
|
||||
+ (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
+ errnop, h_errnop, ttlp, canonp);
|
||||
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
- errnop, h_errnop, map, ttlp, canonp);
|
||||
if (host_buffer.buf != orig_host_buffer)
|
||||
free (host_buffer.buf);
|
||||
return status;
|
||||
@@ -330,13 +305,8 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- status = NSS_STATUS_NOTFOUND;
|
||||
- if (res_use_inet6 ())
|
||||
- status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
|
||||
- buflen, errnop, h_errnop, NULL, NULL);
|
||||
- if (status == NSS_STATUS_NOTFOUND)
|
||||
- status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
|
||||
- buflen, errnop, h_errnop, NULL, NULL);
|
||||
+ status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
|
||||
+ buflen, errnop, h_errnop, NULL, NULL);
|
||||
__resolv_context_put (ctx);
|
||||
return status;
|
||||
}
|
||||
@@ -649,7 +619,7 @@ static enum nss_status
|
||||
getanswer_r (struct resolv_context *ctx,
|
||||
const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
struct hostent *result, char *buffer, size_t buflen,
|
||||
- int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
{
|
||||
struct host_data
|
||||
{
|
||||
@@ -665,7 +635,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
char *bp, **ap, **hap;
|
||||
char tbuf[MAXDNAME];
|
||||
u_char packtmp[NS_MAXCDNAME];
|
||||
- int have_to_map = 0;
|
||||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
buffer += pad;
|
||||
buflen = buflen > pad ? buflen - pad : 0;
|
||||
@@ -846,9 +815,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (type == T_A && qtype == T_AAAA && map)
|
||||
- have_to_map = 1;
|
||||
- else if (__glibc_unlikely (type != qtype))
|
||||
+ if (__glibc_unlikely (type != qtype))
|
||||
{
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
@@ -945,9 +912,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
}
|
||||
|
||||
- if (have_to_map)
|
||||
- if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
- goto too_small;
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
565
glibc-upstream-2.34-325.patch
Normal file
565
glibc-upstream-2.34-325.patch
Normal file
@ -0,0 +1,565 @@
|
||||
commit 9abc40d9b514fc51cd1a052d32d092a827c6e21a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305)
|
||||
|
||||
Allocate the pointer arrays only at the end, when their sizes
|
||||
are known. This addresses bug 29305.
|
||||
|
||||
Skip over invalid names instead of failing lookups. This partially
|
||||
fixes bug 12154 (for gethostbyname, fixing getaddrinfo requires
|
||||
different changes).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit d101d836e7e4bd1d4e4972b0e0bd0a55c9b650fa)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index f8dc5a0a7d1eb156..10c21e1e827cde12 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -108,12 +108,19 @@ typedef union querybuf
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
-static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
- const querybuf *answer, int anslen,
|
||||
- const char *qname, int qtype,
|
||||
- struct hostent *result, char *buffer,
|
||||
- size_t buflen, int *errnop, int *h_errnop,
|
||||
- int32_t *ttlp, char **canonp);
|
||||
+/* For historic reasons, pointers to IP addresses are char *, so use a
|
||||
+ single list type for addresses and host names. */
|
||||
+#define DYNARRAY_STRUCT ptrlist
|
||||
+#define DYNARRAY_ELEMENT char *
|
||||
+#define DYNARRAY_PREFIX ptrlist_
|
||||
+#include <malloc/dynarray-skeleton.c>
|
||||
+
|
||||
+static enum nss_status getanswer_r (unsigned char *packet, size_t packetlen,
|
||||
+ uint16_t qtype, struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *addresses,
|
||||
+ struct ptrlist *aliases,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp);
|
||||
+static void addrsort (struct resolv_context *ctx, char **ap, int num);
|
||||
static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
struct alloc_buffer *abuf,
|
||||
char **hnamep, int *errnop,
|
||||
@@ -185,12 +192,6 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
{
|
||||
- union
|
||||
- {
|
||||
- querybuf *buf;
|
||||
- u_char *ptr;
|
||||
- } host_buffer;
|
||||
- querybuf *orig_host_buffer;
|
||||
char tmp[NS_MAXDNAME];
|
||||
int size, type, n;
|
||||
const char *cp;
|
||||
@@ -224,10 +225,12 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
&& (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
|
||||
name = cp;
|
||||
|
||||
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
|
||||
+ unsigned char dns_packet_buffer[1024];
|
||||
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
|
||||
|
||||
- n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
|
||||
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
+ n = __res_context_search (ctx, name, C_IN, type,
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
|
||||
if (n < 0)
|
||||
{
|
||||
switch (errno)
|
||||
@@ -256,12 +259,77 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
__set_errno (olderr);
|
||||
}
|
||||
else
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
- errnop, h_errnop, ttlp, canonp);
|
||||
+ {
|
||||
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
|
||||
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ struct ptrlist addresses;
|
||||
+ ptrlist_init (&addresses);
|
||||
+ struct ptrlist aliases;
|
||||
+ ptrlist_init (&aliases);
|
||||
+
|
||||
+ status = getanswer_r (alt_dns_packet_buffer, n, type,
|
||||
+ &abuf, &addresses, &aliases,
|
||||
+ errnop, h_errnop, ttlp);
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (ptrlist_has_failed (&addresses)
|
||||
+ || ptrlist_has_failed (&aliases))
|
||||
+ {
|
||||
+ /* malloc failure. Do not retry using the ERANGE protocol. */
|
||||
+ *errnop = ENOMEM;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ status = NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+
|
||||
+ /* Reserve the address and alias arrays in the result
|
||||
+ buffer. Both are NULL-terminated, but the first element
|
||||
+ of the alias array is stored in h_name, so no extra space
|
||||
+ for the NULL terminator is needed there. */
|
||||
+ result->h_addr_list
|
||||
+ = alloc_buffer_alloc_array (&abuf, char *,
|
||||
+ ptrlist_size (&addresses) + 1);
|
||||
+ result->h_aliases
|
||||
+ = alloc_buffer_alloc_array (&abuf, char *,
|
||||
+ ptrlist_size (&aliases));
|
||||
+ if (alloc_buffer_has_failed (&abuf))
|
||||
+ {
|
||||
+ /* Retry using the ERANGE protocol. */
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ status = NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Copy the address list and NULL-terminate it. */
|
||||
+ memcpy (result->h_addr_list, ptrlist_begin (&addresses),
|
||||
+ ptrlist_size (&addresses) * sizeof (char *));
|
||||
+ result->h_addr_list[ptrlist_size (&addresses)] = NULL;
|
||||
+
|
||||
+ /* Sort the address list if requested. */
|
||||
+ if (type == T_A && __resolv_context_sort_count (ctx) > 0)
|
||||
+ addrsort (ctx, result->h_addr_list, ptrlist_size (&addresses));
|
||||
+
|
||||
+ /* Copy the aliases, excluding the last one. */
|
||||
+ memcpy (result->h_aliases, ptrlist_begin (&aliases),
|
||||
+ (ptrlist_size (&aliases) - 1) * sizeof (char *));
|
||||
+ result->h_aliases[ptrlist_size (&aliases) - 1] = NULL;
|
||||
+
|
||||
+ /* The last alias goes into h_name. */
|
||||
+ assert (ptrlist_size (&aliases) >= 1);
|
||||
+ result->h_name = ptrlist_end (&aliases)[-1];
|
||||
+
|
||||
+ /* This is also the canonical name. */
|
||||
+ if (canonp != NULL)
|
||||
+ *canonp = result->h_name;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ptrlist_free (&aliases);
|
||||
+ ptrlist_free (&addresses);
|
||||
+ }
|
||||
+
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -615,314 +683,128 @@ addrsort (struct resolv_context *ctx, char **ap, int num)
|
||||
break;
|
||||
}
|
||||
|
||||
-static enum nss_status
|
||||
-getanswer_r (struct resolv_context *ctx,
|
||||
- const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
- struct hostent *result, char *buffer, size_t buflen,
|
||||
- int *errnop, int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
+/* Convert the uncompressed, binary domain name CDNAME into its
|
||||
+ textual representation and add it to the end of ALIASES, allocating
|
||||
+ space for a copy of the name from ABUF. Skip adding the name if it
|
||||
+ is not a valid host name, and return false in that case, otherwise
|
||||
+ true. */
|
||||
+static bool
|
||||
+getanswer_r_store_alias (const unsigned char *cdname,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *aliases)
|
||||
{
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[0];
|
||||
- } *host_data;
|
||||
- int linebuflen;
|
||||
- const HEADER *hp;
|
||||
- const u_char *end_of_message, *cp;
|
||||
- int n, ancount, qdcount;
|
||||
- int haveanswer, had_error;
|
||||
- char *bp, **ap, **hap;
|
||||
- char tbuf[MAXDNAME];
|
||||
- u_char packtmp[NS_MAXCDNAME];
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- /* The buffer is too small. */
|
||||
- too_small:
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- host_data = (struct host_data *) buffer;
|
||||
- linebuflen = buflen - sizeof (struct host_data);
|
||||
- if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
- linebuflen = INT_MAX;
|
||||
-
|
||||
- result->h_name = NULL;
|
||||
- end_of_message = answer->buf + anslen;
|
||||
-
|
||||
- /*
|
||||
- * find first satisfactory answer
|
||||
- */
|
||||
- hp = &answer->hdr;
|
||||
- ancount = ntohs (hp->ancount);
|
||||
- qdcount = ntohs (hp->qdcount);
|
||||
- cp = answer->buf + HFIXEDSZ;
|
||||
- if (__glibc_unlikely (qdcount != 1))
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
- goto too_small;
|
||||
- bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
- linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
+ /* Filter out domain names that are not host names. */
|
||||
+ if (!__res_binary_hnok (cdname))
|
||||
+ return false;
|
||||
+
|
||||
+ /* Note: Not NS_MAXCDNAME, so that __ns_name_ntop implicitly checks
|
||||
+ for length. */
|
||||
+ char dname[MAXHOSTNAMELEN + 1];
|
||||
+ if (__ns_name_ntop (cdname, dname, sizeof (dname)) < 0)
|
||||
+ return false;
|
||||
+ /* Do not report an error on allocation failure, instead store NULL
|
||||
+ or do nothing. getanswer_r's caller will see NSS_STATUS_SUCCESS
|
||||
+ and detect the memory allocation failure or buffer space
|
||||
+ exhaustion, and report it accordingly. */
|
||||
+ ptrlist_add (aliases, alloc_buffer_copy_string (abuf, dname));
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- *errnop = errno;
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (__glibc_unlikely (__libc_res_hnok (bp) == 0))
|
||||
+static enum nss_status __attribute__ ((noinline))
|
||||
+getanswer_r (unsigned char *packet, size_t packetlen, uint16_t qtype,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *addresses, struct ptrlist *aliases,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
+{
|
||||
+ 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;
|
||||
|
||||
- if (qtype == T_A || qtype == T_AAAA)
|
||||
+ /* Treat the QNAME just like an alias. Error out if it is not a
|
||||
+ valid host name. */
|
||||
+ if (ns_rr_cursor_rcode (&c) == NXDOMAIN
|
||||
+ || !getanswer_r_store_alias (ns_rr_cursor_qname (&c), abuf, aliases))
|
||||
{
|
||||
- /* res_send() has already verified that the query name is the
|
||||
- * same as the one we sent; this just gets the expanded name
|
||||
- * (i.e., with the succeeding search-domain tacked on).
|
||||
- */
|
||||
- n = strlen (bp) + 1; /* for the \0 */
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- *errnop = ENOENT;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- result->h_name = bp;
|
||||
- bp += n;
|
||||
- linebuflen -= n;
|
||||
- if (linebuflen < 0)
|
||||
- goto too_small;
|
||||
- /* The qname can be abbreviated, but h_name is now absolute. */
|
||||
- qname = result->h_name;
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No negative caching. */
|
||||
+ *ttlp = 0;
|
||||
+ *h_errnop = HOST_NOT_FOUND;
|
||||
+ *errnop = ENOENT;
|
||||
+ return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- ap = host_data->aliases;
|
||||
- *ap = NULL;
|
||||
- result->h_aliases = host_data->aliases;
|
||||
- hap = host_data->h_addr_ptrs;
|
||||
- *hap = NULL;
|
||||
- result->h_addr_list = host_data->h_addr_ptrs;
|
||||
- haveanswer = 0;
|
||||
- had_error = 0;
|
||||
+ 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];
|
||||
|
||||
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ for (; ancount > 0; --ancount)
|
||||
{
|
||||
- int type, class;
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n; /* name */
|
||||
-
|
||||
- if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
+ struct ns_rr_wire rr;
|
||||
+ if (!__ns_rr_cursor_next (&c, &rr))
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- NS_GET16 (type, cp);
|
||||
- NS_GET16 (class, cp);
|
||||
- int32_t ttl;
|
||||
- NS_GET32 (ttl, cp);
|
||||
- NS_GET16 (n, cp); /* RDATA length. */
|
||||
-
|
||||
- if (end_of_message - cp < n)
|
||||
- {
|
||||
- /* RDATA extends beyond the end of the packet. */
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
+ /* Skip over records with the wrong class. */
|
||||
+ if (rr.rclass != C_IN)
|
||||
+ continue;
|
||||
|
||||
- if (__glibc_unlikely (class != C_IN))
|
||||
- {
|
||||
- /* XXX - debug? syslog? */
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
+ /* Update TTL for recognized 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)
|
||||
{
|
||||
- /* A CNAME could also have a TTL entry. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
-
|
||||
- if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
|
||||
- continue;
|
||||
- n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
- tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n;
|
||||
- /* Store alias. */
|
||||
- *ap++ = bp;
|
||||
- n = strlen (bp) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- bp += n;
|
||||
- linebuflen -= n;
|
||||
- /* Get canonical name. */
|
||||
- n = strlen (tbuf) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
+ /* 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)
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- continue;
|
||||
+ /* And store the new name as an alias. */
|
||||
+ getanswer_r_store_alias (name_buffer, abuf, aliases);
|
||||
+ expected_name = name_buffer;
|
||||
}
|
||||
-
|
||||
- if (__glibc_unlikely (type != qtype))
|
||||
+ else if (rr.rtype == qtype
|
||||
+ && __ns_samebinaryname (rr.rname, expected_name)
|
||||
+ && rr.rdlength == rrtype_to_rdata_length (qtype))
|
||||
{
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
+ /* Make a copy of the address and store it. Increase the
|
||||
+ alignment to 4, in case there are applications out there
|
||||
+ that expect at least this level of address alignment. */
|
||||
+ ptrlist_add (addresses, (char *) alloc_buffer_next (abuf, uint32_t));
|
||||
+ alloc_buffer_copy_bytes (abuf, rr.rdata, rr.rdlength);
|
||||
}
|
||||
-
|
||||
- switch (type)
|
||||
- {
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- /* Stop parsing at a record whose length is incorrect. */
|
||||
- if (n != rrtype_to_rdata_length (type))
|
||||
- {
|
||||
- ++had_error;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Skip records of the wrong type. */
|
||||
- if (n != result->h_length)
|
||||
- {
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
- if (!haveanswer)
|
||||
- {
|
||||
- int nn;
|
||||
-
|
||||
- /* 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;
|
||||
- if (canonp != NULL)
|
||||
- *canonp = bp;
|
||||
- result->h_name = bp;
|
||||
- nn = strlen (bp) + 1; /* for the \0 */
|
||||
- bp += nn;
|
||||
- linebuflen -= nn;
|
||||
- }
|
||||
-
|
||||
- /* Provide sufficient alignment for both address
|
||||
- families. */
|
||||
- enum { align = 4 };
|
||||
- _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
- "struct in_addr alignment");
|
||||
- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
- "struct in6_addr alignment");
|
||||
- {
|
||||
- char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
- linebuflen -= new_bp - bp;
|
||||
- bp = new_bp;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
- cp += n;
|
||||
- linebuflen -= n;
|
||||
- break;
|
||||
- default:
|
||||
- abort ();
|
||||
- }
|
||||
- if (had_error == 0)
|
||||
- ++haveanswer;
|
||||
}
|
||||
|
||||
- if (haveanswer > 0)
|
||||
+ if (ptrlist_size (addresses) == 0)
|
||||
{
|
||||
- *ap = NULL;
|
||||
- *hap = NULL;
|
||||
- /*
|
||||
- * Note: we sort even if host can take only one address
|
||||
- * in its return structures - should give it the "best"
|
||||
- * address in that case, not some random one
|
||||
- */
|
||||
- if (haveanswer > 1 && qtype == T_A
|
||||
- && __resolv_context_sort_count (ctx) > 0)
|
||||
- addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
-
|
||||
- if (result->h_name == NULL)
|
||||
- {
|
||||
- n = strlen (qname) + 1; /* For the \0. */
|
||||
- if (n > linebuflen)
|
||||
- goto too_small;
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- goto no_recovery;
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- }
|
||||
+ /* No address record found. */
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No caching of negative responses. */
|
||||
+ *ttlp = 0;
|
||||
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ *errnop = ENOENT;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
- no_recovery:
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- *errnop = ENOENT;
|
||||
- /* 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. */
|
||||
- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
}
|
||||
|
||||
static enum nss_status
|
51
glibc-upstream-2.34-326.patch
Normal file
51
glibc-upstream-2.34-326.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit c36e7cca3571b0c92b09409c1df86a142596c210
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154)
|
||||
|
||||
If the name is not a host name, skip adding it to the result, instead
|
||||
of reporting query failure. This fixes bug 12154 for getaddrinfo.
|
||||
|
||||
This commit still keeps the old parsing code, and only adjusts when
|
||||
a host name is copied.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 32b599ac8c21c4c332cc3900a792a1395bca79c7)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 10c21e1e827cde12..1cb3be71f04d98eb 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -971,12 +971,12 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
|
||||
n = -1;
|
||||
}
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (buffer) == 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
- if (*firstp && canon == NULL)
|
||||
+ if (*firstp && canon == NULL && __libc_res_hnok (buffer))
|
||||
{
|
||||
h_name = buffer;
|
||||
buffer += h_namelen;
|
||||
@@ -1022,14 +1022,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
|
||||
n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
cp += n;
|
||||
|
||||
- if (*firstp)
|
||||
+ if (*firstp && __libc_res_hnok (tbuf))
|
||||
{
|
||||
/* Reclaim buffer space. */
|
||||
if (h_name + h_namelen == buffer)
|
449
glibc-upstream-2.34-327.patch
Normal file
449
glibc-upstream-2.34-327.patch
Normal file
@ -0,0 +1,449 @@
|
||||
commit 480c820493add16e8dda6f3189d834223e1f4f39
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add new tst-resolv-invalid-cname
|
||||
|
||||
This test checks resolution through CNAME chains that do not contain
|
||||
host names (bug 12154).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 9caf782276ecea4bc86fc94fbb52779736f3106d)
|
||||
|
||||
Conflicts:
|
||||
resolv/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index fded244d61068060..ea1518ec2da860c1 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -99,6 +99,7 @@ tests += \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-byaddr \
|
||||
tst-resolv-edns \
|
||||
+ tst-resolv-invalid-cname \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
tst-resolv-nondecimal \
|
||||
@@ -279,6 +280,8 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-invalid-cname: $(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 --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..ae2d4419b1978c02
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-invalid-cname.c
|
||||
@@ -0,0 +1,406 @@
|
||||
+/* Test handling of CNAMEs with non-host domain names (bug 12154).
|
||||
+ 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 <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xmemstream.h>
|
||||
+
|
||||
+/* Query strings describe the CNAME chain in the response. They have
|
||||
+ the format "bitsBITS.countCOUNT.example.", where BITS and COUNT are
|
||||
+ replaced by unsigned decimal numbers. COUNT is the number of CNAME
|
||||
+ records in the response. BITS has two bits for each CNAME record,
|
||||
+ describing a special prefix that is added to that CNAME.
|
||||
+
|
||||
+ 0: No special leading label.
|
||||
+ 1: Starting with "*.".
|
||||
+ 2: Starting with "-x.".
|
||||
+ 3: Starting with "star.*.".
|
||||
+
|
||||
+ The first CNAME in the response using the two least significant
|
||||
+ bits.
|
||||
+
|
||||
+ For PTR queries, the QNAME format is different, it is either
|
||||
+ COUNT.BITS.168.192.in-addr.arpa. (with BITS and COUNT still
|
||||
+ decimal), or:
|
||||
+
|
||||
+COUNT.BITS0.BITS1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
+
|
||||
+ where BITS and COUNT are hexadecimal. */
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+
|
||||
+ /* The only other query type besides A is PTR. */
|
||||
+ if (qtype != T_A && qtype != T_AAAA)
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int bits, bits1, count;
|
||||
+ char *tail = NULL;
|
||||
+ if (sscanf (qname, "bits%u.count%u.%ms", &bits, &count, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "example");
|
||||
+ else if (strstr (qname, "in-addr.arpa") != NULL
|
||||
+ && sscanf (qname, "%u.%u.%ms", &bits, &count, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "168.192.in-addr.arpa");
|
||||
+ else if (sscanf (qname, "%x.%x.%x.%ms", &bits, &bits1, &count, &tail) == 4)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ bits |= bits1 << 4;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ unsigned int original_bits = bits;
|
||||
+ for (int unique = 0; unique < count; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+
|
||||
+ static const char bits_to_prefix[4][8] = { "", "*.", "-x.", "star.*." };
|
||||
+ char *new_name = xasprintf ("%sunique%d.example",
|
||||
+ bits_to_prefix[bits & 3], unique);
|
||||
+ bits >>= 2;
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ /* Actual answer record. */
|
||||
+ resolv_response_open_record (b, previous_name, qclass, qtype, 60);
|
||||
+ switch (qtype)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 168, count, original_bits};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ }
|
||||
+ break;
|
||||
+ case T_AAAA:
|
||||
+ {
|
||||
+ char ipv6[16] =
|
||||
+ {
|
||||
+ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
+ count, original_bits
|
||||
+ };
|
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case T_PTR:
|
||||
+ {
|
||||
+ char *name = xasprintf ("bits%u.count%u.example",
|
||||
+ original_bits, count);
|
||||
+ resolv_response_add_name (b, name);
|
||||
+ free (name);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+/* Controls which name resolution function is invoked. */
|
||||
+enum test_mode
|
||||
+ {
|
||||
+ byname, /* gethostbyname. */
|
||||
+ byname2, /* gethostbyname2. */
|
||||
+ gai, /* getaddrinfo without AI_CANONNAME. */
|
||||
+ gai_canon, /* getaddrinfo with AI_CANONNAME. */
|
||||
+
|
||||
+ test_mode_num /* Number of enum values. */
|
||||
+ };
|
||||
+
|
||||
+static const char *
|
||||
+test_mode_to_string (enum test_mode mode)
|
||||
+{
|
||||
+ switch (mode)
|
||||
+ {
|
||||
+ case byname:
|
||||
+ return "byname";
|
||||
+ case byname2:
|
||||
+ return "byname2";
|
||||
+ case gai:
|
||||
+ return "gai";
|
||||
+ case gai_canon:
|
||||
+ return "gai_canon";
|
||||
+ case test_mode_num:
|
||||
+ /* Report error below. */
|
||||
+ }
|
||||
+ FAIL_EXIT1 ("invalid test_mode: %d", mode);
|
||||
+}
|
||||
+
|
||||
+/* Append the name and aliases to OUT. */
|
||||
+static void
|
||||
+append_names (FILE *out, const char *qname, int bits, int count,
|
||||
+ enum test_mode mode)
|
||||
+{
|
||||
+ /* Largest valid index which has a corresponding zero in bits
|
||||
+ (meaning a syntactically valid CNAME). */
|
||||
+ int last_valid_cname = -1;
|
||||
+
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ if ((bits & (3 << (i * 2))) == 0)
|
||||
+ last_valid_cname = i;
|
||||
+
|
||||
+ if (mode != gai)
|
||||
+ {
|
||||
+ const char *label;
|
||||
+ if (mode == gai_canon)
|
||||
+ label = "canonname";
|
||||
+ else
|
||||
+ label = "name";
|
||||
+ if (last_valid_cname >= 0)
|
||||
+ fprintf (out, "%s: unique%d.example\n", label, last_valid_cname);
|
||||
+ else
|
||||
+ fprintf (out, "%s: %s\n", label, qname);
|
||||
+ }
|
||||
+
|
||||
+ if (mode == byname || mode == byname2)
|
||||
+ {
|
||||
+ if (last_valid_cname >= 0)
|
||||
+ fprintf (out, "alias: %s\n", qname);
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ {
|
||||
+ if ((bits & (3 << (i * 2))) == 0 && i != last_valid_cname)
|
||||
+ fprintf (out, "alias: unique%d.example\n", i);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Append the address information to OUT. */
|
||||
+static void
|
||||
+append_addresses (FILE *out, int af, int bits, int count, enum test_mode mode)
|
||||
+{
|
||||
+ int last = count * 256 + bits;
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ {
|
||||
+ if (af == AF_INET || af == AF_UNSPEC)
|
||||
+ fprintf (out, "address: STREAM/TCP 192.168.%d.%d 80\n", count, bits);
|
||||
+ if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
+ {
|
||||
+ if (last == 0)
|
||||
+ fprintf (out, "address: STREAM/TCP 2001:db8:: 80\n");
|
||||
+ else
|
||||
+ fprintf (out, "address: STREAM/TCP 2001:db8::%x 80\n", last);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_VERIFY (af != AF_UNSPEC);
|
||||
+ if (af == AF_INET)
|
||||
+ fprintf (out, "address: 192.168.%d.%d\n", count, bits);
|
||||
+ if (af == AF_INET6)
|
||||
+ {
|
||||
+ if (last == 0)
|
||||
+ fprintf (out, "address: 2001:db8::\n");
|
||||
+ else
|
||||
+ fprintf (out, "address: 2001:db8::%x\n", last);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Perform one test using a forward lookup. */
|
||||
+static void
|
||||
+check_forward (int af, int bits, int count, enum test_mode mode)
|
||||
+{
|
||||
+ char *qname = xasprintf ("bits%d.count%d.example", bits, count);
|
||||
+ char *label = xasprintf ("af=%d bits=%d count=%d mode=%s qname=%s",
|
||||
+ af, bits, count, test_mode_to_string (mode), qname);
|
||||
+
|
||||
+ struct xmemstream expected;
|
||||
+ xopen_memstream (&expected);
|
||||
+ if (mode == gai_canon)
|
||||
+ fprintf (expected.out, "flags: AI_CANONNAME\n");
|
||||
+ append_names (expected.out, qname, bits, count, mode);
|
||||
+ append_addresses (expected.out, af, bits, count, mode);
|
||||
+ xfclose_memstream (&expected);
|
||||
+
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ {
|
||||
+ struct addrinfo *ai;
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_family = af,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ };
|
||||
+ if (mode == gai_canon)
|
||||
+ hints.ai_flags |= AI_CANONNAME;
|
||||
+ int ret = getaddrinfo (qname, "80", &hints, &ai);
|
||||
+ check_addrinfo (label, ai, ret, expected.buffer);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ struct hostent *e;
|
||||
+ if (mode == gai)
|
||||
+ {
|
||||
+ TEST_COMPARE (af, AF_INET);
|
||||
+ e = gethostbyname (qname);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (af != AF_INET)
|
||||
+ TEST_COMPARE (af, AF_INET6);
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+ }
|
||||
+ check_hostent (label, e, expected.buffer);
|
||||
+ }
|
||||
+
|
||||
+ free (expected.buffer);
|
||||
+ free (label);
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+/* Perform one check using a reverse lookup. */
|
||||
+
|
||||
+static void
|
||||
+check_reverse (int af, int bits, int count)
|
||||
+{
|
||||
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
|
||||
+
|
||||
+ char *label = xasprintf ("af=%d bits=%d count=%d", af, bits, count);
|
||||
+ char *fqdn = xasprintf ("bits%d.count%d.example", bits, count);
|
||||
+
|
||||
+ struct xmemstream expected;
|
||||
+ xopen_memstream (&expected);
|
||||
+ fprintf (expected.out, "name: %s\n", fqdn);
|
||||
+ append_addresses (expected.out, af, bits, count, byname);
|
||||
+ xfclose_memstream (&expected);
|
||||
+
|
||||
+ char addr[16] = { 0 };
|
||||
+ socklen_t addrlen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ addr[0] = 192;
|
||||
+ addr[1] = 168;
|
||||
+ addr[2] = count;
|
||||
+ addr[3] = bits;
|
||||
+ addrlen = 4;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ addr[0] = 0x20;
|
||||
+ addr[1] = 0x01;
|
||||
+ addr[2] = 0x0d;
|
||||
+ addr[3] = 0xb8;
|
||||
+ addr[14] = count;
|
||||
+ addr[15] = bits;
|
||||
+ addrlen = 16;
|
||||
+ }
|
||||
+
|
||||
+ struct hostent *e = gethostbyaddr (addr, addrlen, af);
|
||||
+ check_hostent (label, e, expected.buffer);
|
||||
+
|
||||
+ /* getnameinfo check is different. There is no generic check_*
|
||||
+ function for it. */
|
||||
+ {
|
||||
+ struct sockaddr_in sin = { };
|
||||
+ struct sockaddr_in6 sin6 = { };
|
||||
+ void *sa;
|
||||
+ socklen_t salen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ sin.sin_family = AF_INET;
|
||||
+ memcpy (&sin.sin_addr, addr, addrlen);
|
||||
+ sin.sin_port = htons (80);
|
||||
+ sa = &sin;
|
||||
+ salen = sizeof (sin);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ sin6.sin6_family = AF_INET6;
|
||||
+ memcpy (&sin6.sin6_addr, addr, addrlen);
|
||||
+ sin6.sin6_port = htons (80);
|
||||
+ sa = &sin6;
|
||||
+ salen = sizeof (sin6);
|
||||
+ }
|
||||
+
|
||||
+ char host[64];
|
||||
+ char service[64];
|
||||
+ int ret = getnameinfo (sa, salen, host,
|
||||
+ sizeof (host), service, sizeof (service),
|
||||
+ NI_NAMEREQD | NI_NUMERICSERV);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_COMPARE_STRING (host, fqdn);
|
||||
+ TEST_COMPARE_STRING (service, "80");
|
||||
+ }
|
||||
+
|
||||
+ free (expected.buffer);
|
||||
+ free (fqdn);
|
||||
+ free (label);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int count = 0; count <= 3; ++count)
|
||||
+ for (int bits = 0; bits <= 1 << (count * 2); ++bits)
|
||||
+ {
|
||||
+ if (count > 0 && bits == count)
|
||||
+ /* The last bits value is only checked if count == 0. */
|
||||
+ continue;
|
||||
+
|
||||
+ for (enum test_mode mode = 0; mode < test_mode_num; ++mode)
|
||||
+ {
|
||||
+ check_forward (AF_INET, bits, count, mode);
|
||||
+ if (mode != byname)
|
||||
+ check_forward (AF_INET6, bits, count, mode);
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ check_forward (AF_UNSPEC, bits, count, mode);
|
||||
+ }
|
||||
+
|
||||
+ check_reverse (AF_INET, bits, count);
|
||||
+ check_reverse (AF_INET6, bits, count);
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
31
glibc-upstream-2.34-329.patch
Normal file
31
glibc-upstream-2.34-329.patch
Normal file
@ -0,0 +1,31 @@
|
||||
commit 044755e2faeeca13bb77b2e9e638a45e6e90a5fa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 13:30:03 2022 +0200
|
||||
|
||||
resolv: Fix building tst-resolv-invalid-cname for earlier C standards
|
||||
|
||||
This fixes this compiler error:
|
||||
|
||||
tst-resolv-invalid-cname.c: In function ‘test_mode_to_string’:
|
||||
tst-resolv-invalid-cname.c:164:10: error: label at end of compound statement
|
||||
case test_mode_num:
|
||||
^~~~~~~~~~~~~
|
||||
|
||||
Fixes commit 9caf782276ecea4bc86fc94fbb52779736f3106d
|
||||
("resolv: Add new tst-resolv-invalid-cname").
|
||||
|
||||
(cherry picked from commit d09aa4a17229bcaa2ec7642006b12612498582e7)
|
||||
|
||||
diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c
|
||||
index ae2d4419b1978c02..63dac90e02d6cbc7 100644
|
||||
--- a/resolv/tst-resolv-invalid-cname.c
|
||||
+++ b/resolv/tst-resolv-invalid-cname.c
|
||||
@@ -162,7 +162,7 @@ test_mode_to_string (enum test_mode mode)
|
||||
case gai_canon:
|
||||
return "gai_canon";
|
||||
case test_mode_num:
|
||||
- /* Report error below. */
|
||||
+ break; /* Report error below. */
|
||||
}
|
||||
FAIL_EXIT1 ("invalid test_mode: %d", mode);
|
||||
}
|
33
glibc-upstream-2.34-330.patch
Normal file
33
glibc-upstream-2.34-330.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit a2e259014f8a0e5f3ff938314f3087b74255804d
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:31:51 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index da624f322d06d0ee..a04e0158451c8fff 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -298,12 +298,12 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
|
||||
- oldval | FUTEX_WAITERS,
|
||||
- oldval)
|
||||
- != 0)
|
||||
+ int val;
|
||||
+ if ((val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
+ oldval)) != oldval)
|
||||
{
|
||||
- oldval = mutex->__data.__lock;
|
||||
+ oldval = val;
|
||||
continue;
|
||||
}
|
||||
oldval |= FUTEX_WAITERS;
|
33
glibc-upstream-2.34-331.patch
Normal file
33
glibc-upstream-2.34-331.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit ed8300c054cae4aeb0bbfa043f5fccc91a4adbf5
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:54:01 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit 49302b8fdf9103b6fc0a398678668a22fa19574c)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 11ad7005d07afc6e..90cede9446e33fcf 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -234,12 +234,12 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
|
||||
- oldval | FUTEX_WAITERS,
|
||||
- oldval)
|
||||
- != 0)
|
||||
+ int val;
|
||||
+ if ((val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
+ oldval)) != oldval)
|
||||
{
|
||||
- oldval = mutex->__data.__lock;
|
||||
+ oldval = val;
|
||||
continue;
|
||||
}
|
||||
oldval |= FUTEX_WAITERS;
|
46
glibc-upstream-2.34-332.patch
Normal file
46
glibc-upstream-2.34-332.patch
Normal file
@ -0,0 +1,46 @@
|
||||
commit a6b81f605dfba8650ea1f80122f41eb8e6c73dc7
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Nov 2 18:33:07 2021 -0700
|
||||
|
||||
Add LLL_MUTEX_READ_LOCK [BZ #28537]
|
||||
|
||||
CAS instruction is expensive. From the x86 CPU's point of view, getting
|
||||
a cache line for writing is more expensive than reading. See Appendix
|
||||
A.2 Spinlock in:
|
||||
|
||||
https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/xeon-lock-scaling-analysis-paper.pdf
|
||||
|
||||
The full compare and swap will grab the cache line exclusive and cause
|
||||
excessive cache line bouncing.
|
||||
|
||||
Add LLL_MUTEX_READ_LOCK to do an atomic load and skip CAS in spinlock
|
||||
loop if compare may fail to reduce cache line bouncing on contended locks.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit d672a98a1af106bd68deb15576710cd61363f7a6)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index a04e0158451c8fff..9f40928cc6b9a067 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -65,6 +65,11 @@ lll_mutex_lock_optimized (pthread_mutex_t *mutex)
|
||||
# define PTHREAD_MUTEX_VERSIONS 1
|
||||
#endif
|
||||
|
||||
+#ifndef LLL_MUTEX_READ_LOCK
|
||||
+# define LLL_MUTEX_READ_LOCK(mutex) \
|
||||
+ atomic_load_relaxed (&(mutex)->__data.__lock)
|
||||
+#endif
|
||||
+
|
||||
static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
__attribute_noinline__;
|
||||
|
||||
@@ -142,6 +147,8 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
break;
|
||||
}
|
||||
atomic_spin_nop ();
|
||||
+ if (LLL_MUTEX_READ_LOCK (mutex) != 0)
|
||||
+ continue;
|
||||
}
|
||||
while (LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
|
66
glibc-upstream-2.34-333.patch
Normal file
66
glibc-upstream-2.34-333.patch
Normal file
@ -0,0 +1,66 @@
|
||||
commit 6bcfbee7277e4faa4b693bd965931f0d1883005d
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Fri Nov 12 11:47:42 2021 -0800
|
||||
|
||||
Move assignment out of the CAS condition
|
||||
|
||||
Update
|
||||
|
||||
commit 49302b8fdf9103b6fc0a398678668a22fa19574c
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:54:01 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
and
|
||||
|
||||
commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:31:51 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
by moving assignment out of the CAS condition.
|
||||
|
||||
(cherry picked from commit 120ac6d238825452e8024e2f627da33b2508dfd3)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index 9f40928cc6b9a067..49901ffa0a96d659 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -305,10 +305,9 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- int val;
|
||||
- if ((val = atomic_compare_and_exchange_val_acq
|
||||
- (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
- oldval)) != oldval)
|
||||
+ int val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
|
||||
+ if (val != oldval)
|
||||
{
|
||||
oldval = val;
|
||||
continue;
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 90cede9446e33fcf..2e5506db06ccb1ec 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -234,10 +234,9 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- int val;
|
||||
- if ((val = atomic_compare_and_exchange_val_acq
|
||||
- (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
- oldval)) != oldval)
|
||||
+ int val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
|
||||
+ if (val != oldval)
|
||||
{
|
||||
oldval = val;
|
||||
continue;
|
38
glibc-upstream-2.34-334.patch
Normal file
38
glibc-upstream-2.34-334.patch
Normal file
@ -0,0 +1,38 @@
|
||||
commit 43760d33d78f9ea8c8af942b570112ee801b99df
|
||||
Author: Jangwoong Kim <6812skiii@gmail.com>
|
||||
Date: Tue Dec 14 21:30:51 2021 +0900
|
||||
|
||||
nptl: Effectively skip CAS in spinlock loop
|
||||
|
||||
The commit:
|
||||
"Add LLL_MUTEX_READ_LOCK [BZ #28537]"
|
||||
SHA1: d672a98a1af106bd68deb15576710cd61363f7a6
|
||||
|
||||
introduced LLL_MUTEX_READ_LOCK, to skip CAS in spinlock loop
|
||||
if atomic load fails. But, "continue" inside of do-while loop
|
||||
does not skip the evaluation of escape expression, thus CAS
|
||||
is not skipped.
|
||||
|
||||
Replace do-while with while and skip LLL_MUTEX_TRYLOCK if
|
||||
LLL_MUTEX_READ_LOCK fails.
|
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
(cherry picked from commit 6b8dbbd03ac88f169b65b5c7d7278576a11d2e44)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index 49901ffa0a96d659..bbe754a272b97d91 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -147,10 +147,9 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
break;
|
||||
}
|
||||
atomic_spin_nop ();
|
||||
- if (LLL_MUTEX_READ_LOCK (mutex) != 0)
|
||||
- continue;
|
||||
}
|
||||
- while (LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
+ while (LLL_MUTEX_READ_LOCK (mutex) != 0
|
||||
+ || LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
|
||||
mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
|
||||
}
|
68
glibc-upstream-2.34-335.patch
Normal file
68
glibc-upstream-2.34-335.patch
Normal file
@ -0,0 +1,68 @@
|
||||
commit 04efdcfac405723c23b25d124817bcfc1697e2d8
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Apr 27 15:13:02 2022 -0500
|
||||
|
||||
sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h
|
||||
|
||||
'get_fast_jitter' is meant to be used purely for performance
|
||||
purposes. In all cases it's used it should be acceptable to get no
|
||||
randomness (see default case). An example use case is in setting
|
||||
jitter for retries between threads at a lock. There is a
|
||||
performance benefit to having jitter, but only if the jitter can
|
||||
be generated very quickly and ultimately there is no serious issue
|
||||
if no jitter is generated.
|
||||
|
||||
The implementation generally uses 'HP_TIMING_NOW' iff it is
|
||||
inlined (avoid any potential syscall paths).
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
(cherry picked from commit 911c63a51c690dd1a97dfc587097277029baf00f)
|
||||
|
||||
diff --git a/sysdeps/generic/fast-jitter.h b/sysdeps/generic/fast-jitter.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..4dd53e3475c3dfe6
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/generic/fast-jitter.h
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* Fallback for fast jitter just return 0.
|
||||
+ Copyright (C) 2019-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/>. */
|
||||
+
|
||||
+#ifndef _FAST_JITTER_H
|
||||
+# define _FAST_JITTER_H
|
||||
+
|
||||
+# include <stdint.h>
|
||||
+# include <hp-timing.h>
|
||||
+
|
||||
+/* Baseline just return 0. We could create jitter using a clock or
|
||||
+ 'random_bits' but that may imply a syscall and the goal of
|
||||
+ 'get_fast_jitter' is minimal overhead "randomness" when such
|
||||
+ randomness helps performance. Adding high overhead the function
|
||||
+ defeats the purpose. */
|
||||
+static inline uint32_t
|
||||
+get_fast_jitter (void)
|
||||
+{
|
||||
+# if HP_TIMING_INLINE
|
||||
+ hp_timing_t jitter;
|
||||
+ HP_TIMING_NOW (jitter);
|
||||
+ return (uint32_t) jitter;
|
||||
+# else
|
||||
+ return 0;
|
||||
+# endif
|
||||
+}
|
||||
+
|
||||
+#endif
|
209
glibc-upstream-2.34-336.patch
Normal file
209
glibc-upstream-2.34-336.patch
Normal file
@ -0,0 +1,209 @@
|
||||
commit ea69248445fb9b80da02ee0c7261cba4b1a5532e
|
||||
Author: Wangyang Guo <wangyang.guo@intel.com>
|
||||
Date: Fri May 6 01:50:10 2022 +0000
|
||||
|
||||
nptl: Add backoff mechanism to spinlock loop
|
||||
|
||||
When mutiple threads waiting for lock at the same time, once lock owner
|
||||
releases the lock, waiters will see lock available and all try to lock,
|
||||
which may cause an expensive CAS storm.
|
||||
|
||||
Binary exponential backoff with random jitter is introduced. As try-lock
|
||||
attempt increases, there is more likely that a larger number threads
|
||||
compete for adaptive mutex lock, so increase wait time in exponential.
|
||||
A random jitter is also added to avoid synchronous try-lock from other
|
||||
threads.
|
||||
|
||||
v2: Remove read-check before try-lock for performance.
|
||||
|
||||
v3:
|
||||
1. Restore read-check since it works well in some platform.
|
||||
2. Make backoff arch dependent, and enable it for x86_64.
|
||||
3. Limit max backoff to reduce latency in large critical section.
|
||||
|
||||
v4: Fix strict-prototypes error in sysdeps/nptl/pthread_mutex_backoff.h
|
||||
|
||||
v5: Commit log updated for regression in large critical section.
|
||||
|
||||
Result of pthread-mutex-locks bench
|
||||
|
||||
Test Platform: Xeon 8280L (2 socket, 112 CPUs in total)
|
||||
First Row: thread number
|
||||
First Col: critical section length
|
||||
Values: backoff vs upstream, time based, low is better
|
||||
|
||||
non-critical-length: 1
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 0.99 0.58 0.52 0.49 0.43 0.44 0.46 0.52 0.54
|
||||
1 0.98 0.43 0.56 0.50 0.44 0.45 0.50 0.56 0.57
|
||||
2 0.99 0.41 0.57 0.51 0.45 0.47 0.48 0.60 0.61
|
||||
4 0.99 0.45 0.59 0.53 0.48 0.49 0.52 0.64 0.65
|
||||
8 1.00 0.66 0.71 0.63 0.56 0.59 0.66 0.72 0.71
|
||||
16 0.97 0.78 0.91 0.73 0.67 0.70 0.79 0.80 0.80
|
||||
32 0.95 1.17 0.98 0.87 0.82 0.86 0.89 0.90 0.90
|
||||
64 0.96 0.95 1.01 1.01 0.98 1.00 1.03 0.99 0.99
|
||||
128 0.99 1.01 1.01 1.17 1.08 1.12 1.02 0.97 1.02
|
||||
|
||||
non-critical-length: 32
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 1.03 0.97 0.75 0.65 0.58 0.58 0.56 0.70 0.70
|
||||
1 0.94 0.95 0.76 0.65 0.58 0.58 0.61 0.71 0.72
|
||||
2 0.97 0.96 0.77 0.66 0.58 0.59 0.62 0.74 0.74
|
||||
4 0.99 0.96 0.78 0.66 0.60 0.61 0.66 0.76 0.77
|
||||
8 0.99 0.99 0.84 0.70 0.64 0.66 0.71 0.80 0.80
|
||||
16 0.98 0.97 0.95 0.76 0.70 0.73 0.81 0.85 0.84
|
||||
32 1.04 1.12 1.04 0.89 0.82 0.86 0.93 0.91 0.91
|
||||
64 0.99 1.15 1.07 1.00 0.99 1.01 1.05 0.99 0.99
|
||||
128 1.00 1.21 1.20 1.22 1.25 1.31 1.12 1.10 0.99
|
||||
|
||||
non-critical-length: 128
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 1.02 1.00 0.99 0.67 0.61 0.61 0.61 0.74 0.73
|
||||
1 0.95 0.99 1.00 0.68 0.61 0.60 0.60 0.74 0.74
|
||||
2 1.00 1.04 1.00 0.68 0.59 0.61 0.65 0.76 0.76
|
||||
4 1.00 0.96 0.98 0.70 0.63 0.63 0.67 0.78 0.77
|
||||
8 1.01 1.02 0.89 0.73 0.65 0.67 0.71 0.81 0.80
|
||||
16 0.99 0.96 0.96 0.79 0.71 0.73 0.80 0.84 0.84
|
||||
32 0.99 0.95 1.05 0.89 0.84 0.85 0.94 0.92 0.91
|
||||
64 1.00 0.99 1.16 1.04 1.00 1.02 1.06 0.99 0.99
|
||||
128 1.00 1.06 0.98 1.14 1.39 1.26 1.08 1.02 0.98
|
||||
|
||||
There is regression in large critical section. But adaptive mutex is
|
||||
aimed for "quick" locks. Small critical section is more common when
|
||||
users choose to use adaptive pthread_mutex.
|
||||
|
||||
Signed-off-by: Wangyang Guo <wangyang.guo@intel.com>
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
(cherry picked from commit 8162147872491bb5b48e91543b19c49a29ae6b6d)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index bbe754a272b97d91..8f3f687f2a151d16 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -139,14 +139,26 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
int cnt = 0;
|
||||
int max_cnt = MIN (max_adaptive_count (),
|
||||
mutex->__data.__spins * 2 + 10);
|
||||
+ int spin_count, exp_backoff = 1;
|
||||
+ unsigned int jitter = get_jitter ();
|
||||
do
|
||||
{
|
||||
- if (cnt++ >= max_cnt)
|
||||
+ /* In each loop, spin count is exponential backoff plus
|
||||
+ random jitter, random range is [0, exp_backoff-1]. */
|
||||
+ spin_count = exp_backoff + (jitter & (exp_backoff - 1));
|
||||
+ cnt += spin_count;
|
||||
+ if (cnt >= max_cnt)
|
||||
{
|
||||
+ /* If cnt exceeds max spin count, just go to wait
|
||||
+ queue. */
|
||||
LLL_MUTEX_LOCK (mutex);
|
||||
break;
|
||||
}
|
||||
- atomic_spin_nop ();
|
||||
+ do
|
||||
+ atomic_spin_nop ();
|
||||
+ while (--spin_count > 0);
|
||||
+ /* Prepare for next loop. */
|
||||
+ exp_backoff = get_next_backoff (exp_backoff);
|
||||
}
|
||||
while (LLL_MUTEX_READ_LOCK (mutex) != 0
|
||||
|| LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
|
||||
index b968afc4c6b61b92..ed186ce3df1fde0c 100644
|
||||
--- a/sysdeps/nptl/pthreadP.h
|
||||
+++ b/sysdeps/nptl/pthreadP.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <kernel-features.h>
|
||||
#include <errno.h>
|
||||
#include <internal-signals.h>
|
||||
+#include <pthread_mutex_backoff.h>
|
||||
#include "pthread_mutex_conf.h"
|
||||
|
||||
|
||||
diff --git a/sysdeps/nptl/pthread_mutex_backoff.h b/sysdeps/nptl/pthread_mutex_backoff.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..5b26c22ac789f54f
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/nptl/pthread_mutex_backoff.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Pthread mutex backoff configuration.
|
||||
+ 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/>. */
|
||||
+#ifndef _PTHREAD_MUTEX_BACKOFF_H
|
||||
+#define _PTHREAD_MUTEX_BACKOFF_H 1
|
||||
+
|
||||
+static inline unsigned int
|
||||
+get_jitter (void)
|
||||
+{
|
||||
+ /* Arch dependent random jitter, return 0 disables random. */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+get_next_backoff (int backoff)
|
||||
+{
|
||||
+ /* Next backoff, return 1 disables mutex backoff. */
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
diff --git a/sysdeps/x86_64/nptl/pthread_mutex_backoff.h b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..ec74c3d9db61864e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h
|
||||
@@ -0,0 +1,39 @@
|
||||
+/* Pthread mutex backoff configuration.
|
||||
+ 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/>. */
|
||||
+#ifndef _PTHREAD_MUTEX_BACKOFF_H
|
||||
+#define _PTHREAD_MUTEX_BACKOFF_H 1
|
||||
+
|
||||
+#include <fast-jitter.h>
|
||||
+
|
||||
+static inline unsigned int
|
||||
+get_jitter (void)
|
||||
+{
|
||||
+ return get_fast_jitter ();
|
||||
+}
|
||||
+
|
||||
+#define MAX_BACKOFF 16
|
||||
+
|
||||
+static inline int
|
||||
+get_next_backoff (int backoff)
|
||||
+{
|
||||
+ /* Binary expontial backoff. Limiting max backoff
|
||||
+ can reduce latency in large critical section. */
|
||||
+ return (backoff < MAX_BACKOFF) ? backoff << 1 : backoff;
|
||||
+}
|
||||
+
|
||||
+#endif
|
26
glibc-upstream-2.34-337.patch
Normal file
26
glibc-upstream-2.34-337.patch
Normal file
@ -0,0 +1,26 @@
|
||||
commit 95f5089d4a57cd1e738be908c7a628cb7d0ce512
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86: include BMI1 and BMI2 in x86-64-v3 level
|
||||
|
||||
The "System V Application Binary Interface AMD64 Architecture Processor
|
||||
Supplement" mandates the BMI1 and BMI2 CPU features for the x86-64-v3
|
||||
level.
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit b80f16adbd979831bf25ea491e1261e81885c2b6)
|
||||
|
||||
diff --git a/sysdeps/x86/get-isa-level.h b/sysdeps/x86/get-isa-level.h
|
||||
index aa80f56ca635e54b..785c25a835edf004 100644
|
||||
--- a/sysdeps/x86/get-isa-level.h
|
||||
+++ b/sysdeps/x86/get-isa-level.h
|
||||
@@ -47,6 +47,8 @@ get_isa_level (const struct cpu_features *cpu_features)
|
||||
isa_level |= GNU_PROPERTY_X86_ISA_1_V2;
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, F16C)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, FMA)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
111
glibc-upstream-2.34-338.patch
Normal file
111
glibc-upstream-2.34-338.patch
Normal file
@ -0,0 +1,111 @@
|
||||
commit 414fc856ff4e011e62b88a21d30294637a152dc7
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 str(n)casecmp implementations
|
||||
|
||||
The AVX2 str(n)casecmp implementations use the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 10f79d3670b036925da63dc532b122d27ce65ff8)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 8d649e263eb24b8a..ca64b34c146a76f9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -386,13 +386,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strcasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcasecmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
@@ -407,13 +410,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strcasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_l_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_l_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcasecmp_l_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp_l,
|
||||
@@ -542,13 +548,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strncasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncasecmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
@@ -564,13 +573,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strncasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ & CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_l_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_l_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncasecmp_l_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp_l,
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
index 40819caf5ab10337..e61d6e9497bce9d9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
@@ -32,6 +32,7 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
55
glibc-upstream-2.34-339.patch
Normal file
55
glibc-upstream-2.34-339.patch
Normal file
@ -0,0 +1,55 @@
|
||||
commit e1561d8cf005a23bcaf514802854b493829a25b1
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 strcmp implementation
|
||||
|
||||
The AVX2 strcmp implementation uses the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 4d64c6445735e9b34e2ac8e369312cbfc2f88e17)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index ca64b34c146a76f9..70931f15985334af 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -503,10 +503,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strcmp.c. */
|
||||
IFUNC_IMPL (i, name, strcmp,
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c
|
||||
index b457fb4c150e4407..0c0cd20a03278a2b 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strcmp.c
|
||||
+++ b/sysdeps/x86_64/multiarch/strcmp.c
|
||||
@@ -40,11 +40,11 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2))
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW))
|
||||
return OPTIMIZE (evex);
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM))
|
62
glibc-upstream-2.34-340.patch
Normal file
62
glibc-upstream-2.34-340.patch
Normal file
@ -0,0 +1,62 @@
|
||||
commit b9cbb8dd48b545f3b36b5d411481dc0bd118ee94
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 strncmp implementation
|
||||
|
||||
The AVX2 strncmp implementations uses the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit fc7de1d9b99ae1676bc626ddca422d7abee0eb48)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 70931f15985334af..34d5f6efe5421014 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -1022,15 +1022,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strncmp.c. */
|
||||
IFUNC_IMPL (i, name, strncmp,
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSE4_2),
|
||||
__strncmp_sse42)
|
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c
|
||||
index f94a421784bfe923..7632d7b2dd4447aa 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strncmp.c
|
||||
+++ b/sysdeps/x86_64/multiarch/strncmp.c
|
||||
@@ -39,11 +39,11 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2))
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW))
|
||||
return OPTIMIZE (evex);
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM))
|
51
glibc-upstream-2.34-341.patch
Normal file
51
glibc-upstream-2.34-341.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit 67e863742d98c990b3d3b814b80042c0fa0d50a5
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations
|
||||
|
||||
The AVX2 wcs(n)cmp implementations use the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit f31a5a884ed84bd37032729d4d1eb9d06c9f3c29)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 34d5f6efe5421014..e76a991dc671c1a9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -693,10 +693,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcscmp.c. */
|
||||
IFUNC_IMPL (i, name, wcscmp,
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcscmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcscmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
@@ -709,10 +711,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcsncmp.c. */
|
||||
IFUNC_IMPL (i, name, wcsncmp,
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsncmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcsncmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
61
glibc-upstream-2.34-342.patch
Normal file
61
glibc-upstream-2.34-342.patch
Normal file
@ -0,0 +1,61 @@
|
||||
commit 94b9c1b6409e34f3f0b2339f77d7ee78087422eb
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations
|
||||
|
||||
The AVX2 memchr, rawmemchr and wmemchr implementations use the 'bzhi'
|
||||
and 'sarx' instructions, which belongs to the BMI2 CPU feature.
|
||||
|
||||
Fixes: acfd088a1963 ("x86: Optimize memchr-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit e3e7fab7fe5186d18ca2046d99ba321c27db30ad)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index e76a991dc671c1a9..81640cf00664e3ed 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -41,10 +41,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/memchr.c. */
|
||||
IFUNC_IMPL (i, name, memchr,
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__memchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__memchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
@@ -283,10 +285,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/rawmemchr.c. */
|
||||
IFUNC_IMPL (i, name, rawmemchr,
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__rawmemchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__rawmemchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
@@ -787,10 +791,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wmemchr.c. */
|
||||
IFUNC_IMPL (i, name, wmemchr,
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wmemchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wmemchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
56
glibc-upstream-2.34-343.patch
Normal file
56
glibc-upstream-2.34-343.patch
Normal file
@ -0,0 +1,56 @@
|
||||
commit 36d6b9be3d7008a78e1f6e2e2db1947b76b206d8
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation
|
||||
|
||||
The AVX2 memrchr implementation uses the 'shlxl' instruction, which
|
||||
belongs to the BMI2 CPU feature and uses the 'lzcnt' instruction, which
|
||||
belongs to the LZCNT CPU feature.
|
||||
|
||||
Fixes: af5306a735eb ("x86: Optimize memrchr-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 3c0c78afabfed4b6fc161c159e628fbf14ff370b)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
index 6de72f72724b81ba..52bd00ea5cab6b22 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
@@ -31,6 +31,7 @@ IFUNC_SELECTOR (void)
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 81640cf00664e3ed..d1fc1e75d6706413 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -174,15 +174,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/memrchr.c. */
|
||||
IFUNC_IMPL (i, name, memrchr,
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)),
|
||||
__memrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__memrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)),
|
||||
__memrchr_evex)
|
||||
|
||||
IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_sse2))
|
78
glibc-upstream-2.34-344.patch
Normal file
78
glibc-upstream-2.34-344.patch
Normal file
@ -0,0 +1,78 @@
|
||||
commit e570b865b53f33453d97160791a7d97e38bcc6e8
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations
|
||||
|
||||
The AVX2 strrchr and wcsrchr implementation uses the 'blsmsk'
|
||||
instruction which belongs to the BMI1 CPU feature and the 'shrx'
|
||||
instruction, which belongs to the BMI2 CPU feature.
|
||||
|
||||
Fixes: df7e295d18ff ("x86: Optimize {str|wcs}rchr-avx2")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 7e8283170c5d6805b609a040801d819e362a6292)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
index 52bd00ea5cab6b22..877f007dd6e38fe8 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
@@ -30,6 +30,7 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index d1fc1e75d6706413..84f9e73e2b7df816 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -498,15 +498,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strrchr.c. */
|
||||
IFUNC_IMPL (i, name, strrchr,
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strrchr_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_sse2))
|
||||
|
||||
@@ -687,15 +693,20 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcsrchr.c. */
|
||||
IFUNC_IMPL (i, name, wcsrchr,
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcsrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
&& CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
&& CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsrchr_evex)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr, 1, __wcsrchr_sse2))
|
46
glibc-upstream-2.34-345.patch
Normal file
46
glibc-upstream-2.34-345.patch
Normal file
@ -0,0 +1,46 @@
|
||||
commit e3976287b22422787f3cc6fc9adda58304b55bd9
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Oct 4 18:40:25 2022 -0400
|
||||
|
||||
nscd: Drop local address tuple variable [BZ #29607]
|
||||
|
||||
When a request needs to be resent (e.g. due to insufficient buffer
|
||||
space), the references to subsequent tuples in the local variable are
|
||||
stale and should not be used. This used to work by accident before, but
|
||||
since 1d495912a it no longer does. Instead of trying to reset it, just
|
||||
let gethostbyname4_r write into TUMPBUF6 for us, thus maintaining a
|
||||
consistent state at all times. This is now consistent with what is done
|
||||
in gaih_inet for getaddrinfo.
|
||||
|
||||
Resolves: BZ #29607
|
||||
Reported-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 6e33e5c4b73cea7b8aa3de0947123db16200fb65)
|
||||
|
||||
diff --git a/nscd/aicache.c b/nscd/aicache.c
|
||||
index 737ace11cc276021..3b300ad9b7db2297 100644
|
||||
--- a/nscd/aicache.c
|
||||
+++ b/nscd/aicache.c
|
||||
@@ -111,11 +111,10 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
"gethostbyname4_r");
|
||||
if (fct4 != NULL)
|
||||
{
|
||||
- struct gaih_addrtuple atmem;
|
||||
struct gaih_addrtuple *at;
|
||||
while (1)
|
||||
{
|
||||
- at = &atmem;
|
||||
+ at = NULL;
|
||||
rc6 = 0;
|
||||
herrno = 0;
|
||||
status[1] = DL_CALL_FCT (fct4, (key, &at,
|
||||
@@ -138,7 +137,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
goto next_nip;
|
||||
|
||||
/* We found the data. Count the addresses and the size. */
|
||||
- for (const struct gaih_addrtuple *at2 = at = &atmem; at2 != NULL;
|
||||
+ for (const struct gaih_addrtuple *at2 = at; at2 != NULL;
|
||||
at2 = at2->next)
|
||||
{
|
||||
++naddrs;
|
83
glibc.spec
83
glibc.spec
@ -148,7 +148,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 47%{?dist}
|
||||
Release: 48%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -595,6 +595,45 @@ Patch387: glibc-rh2117712-3.patch
|
||||
Patch388: glibc-rh2117712-4.patch
|
||||
Patch389: glibc-rh2117712-5.patch
|
||||
Patch390: glibc-rh2117712-6.patch
|
||||
Patch391: glibc-upstream-2.34-309.patch
|
||||
Patch392: glibc-upstream-2.34-310.patch
|
||||
Patch393: glibc-upstream-2.34-311.patch
|
||||
Patch394: glibc-upstream-2.34-312.patch
|
||||
# glibc-2.34-313-gbc5cb538e5 backported above as glibc-rh2118666.patch.
|
||||
Patch395: glibc-upstream-2.34-314.patch
|
||||
Patch396: glibc-upstream-2.34-315.patch
|
||||
Patch397: glibc-upstream-2.34-316.patch
|
||||
Patch398: glibc-upstream-2.34-317.patch
|
||||
Patch399: glibc-upstream-2.34-318.patch
|
||||
Patch400: glibc-upstream-2.34-319.patch
|
||||
Patch401: glibc-upstream-2.34-320.patch
|
||||
Patch402: glibc-upstream-2.34-321.patch
|
||||
Patch403: glibc-upstream-2.34-322.patch
|
||||
Patch404: glibc-upstream-2.34-323.patch
|
||||
Patch405: glibc-upstream-2.34-324.patch
|
||||
Patch406: glibc-upstream-2.34-325.patch
|
||||
Patch407: glibc-upstream-2.34-326.patch
|
||||
Patch408: glibc-upstream-2.34-327.patch
|
||||
# glibc-2.34-328-g2def56a349 conflicts with glibc-rh2096191-2.patch;
|
||||
# glibc-rh2129005.patch contains the original master branch commit instead.
|
||||
Patch409: glibc-rh2129005.patch
|
||||
Patch410: glibc-upstream-2.34-329.patch
|
||||
Patch411: glibc-upstream-2.34-330.patch
|
||||
Patch412: glibc-upstream-2.34-331.patch
|
||||
Patch413: glibc-upstream-2.34-332.patch
|
||||
Patch414: glibc-upstream-2.34-333.patch
|
||||
Patch415: glibc-upstream-2.34-334.patch
|
||||
Patch416: glibc-upstream-2.34-335.patch
|
||||
Patch417: glibc-upstream-2.34-336.patch
|
||||
Patch418: glibc-upstream-2.34-337.patch
|
||||
Patch419: glibc-upstream-2.34-338.patch
|
||||
Patch420: glibc-upstream-2.34-339.patch
|
||||
Patch421: glibc-upstream-2.34-340.patch
|
||||
Patch422: glibc-upstream-2.34-341.patch
|
||||
Patch423: glibc-upstream-2.34-342.patch
|
||||
Patch424: glibc-upstream-2.34-343.patch
|
||||
Patch425: glibc-upstream-2.34-344.patch
|
||||
Patch426: glibc-upstream-2.34-345.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -2651,6 +2690,48 @@ fi
|
||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||
|
||||
%changelog
|
||||
* Thu Oct 13 2022 Arjun Shankar <arjun@redhat.com> - 2.34-48
|
||||
- Handle non-hostname CNAME aliases during name resolution (#2129005)
|
||||
- Sync with upstream branch release/2.34/master,
|
||||
commit e3976287b22422787f3cc6fc9adda58304b55bd9:
|
||||
- nscd: Drop local address tuple variable [BZ #29607]
|
||||
- x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations
|
||||
- x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation
|
||||
- x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations
|
||||
- x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations
|
||||
- x86-64: Require BMI2 for AVX2 strncmp implementation
|
||||
- x86-64: Require BMI2 for AVX2 strcmp implementation
|
||||
- x86-64: Require BMI2 for AVX2 str(n)casecmp implementations
|
||||
- x86: include BMI1 and BMI2 in x86-64-v3 level
|
||||
- nptl: Add backoff mechanism to spinlock loop
|
||||
- sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h
|
||||
- nptl: Effectively skip CAS in spinlock loop
|
||||
- Move assignment out of the CAS condition
|
||||
- Add LLL_MUTEX_READ_LOCK [BZ #28537]
|
||||
- Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
|
||||
- Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
|
||||
- resolv: Fix building tst-resolv-invalid-cname for earlier C standards
|
||||
- nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces
|
||||
- resolv: Add new tst-resolv-invalid-cname
|
||||
- nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154)
|
||||
(#2129005)
|
||||
- nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305)
|
||||
- nss_dns: Remove remnants of IPv6 address mapping
|
||||
- nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr
|
||||
- nss_dns: Split getanswer_ptr from getanswer_r
|
||||
- resolv: Add DNS packet parsing helpers geared towards wire format
|
||||
- resolv: Add internal __ns_name_length_uncompressed function
|
||||
- resolv: Add the __ns_samebinaryname function
|
||||
- resolv: Add internal __res_binary_hnok function
|
||||
- resolv: Add tst-resolv-aliases
|
||||
- resolv: Add tst-resolv-byaddr for testing reverse lookup
|
||||
- gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
|
||||
- elf: Fix hwcaps string size overestimation
|
||||
- nscd: Fix netlink cache invalidation if epoll is used [BZ #29415]
|
||||
- Apply asm redirections in wchar.h before first use
|
||||
- Apply asm redirections in stdio.h before first use [BZ #27087]
|
||||
- elf: Call __libc_early_init for reused namespaces (bug 29528)
|
||||
|
||||
* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-47
|
||||
- Simplify the glibc system call profile (#2117712)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user