forked from rpms/glibc
import glibc-2.28-127.el8_3.2
This commit is contained in:
parent
d24c9cf076
commit
f43c687a7a
62
SOURCES/glibc-rh1904153-1.patch
Normal file
62
SOURCES/glibc-rh1904153-1.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
Partial backport of:
|
||||||
|
|
||||||
|
commit 333221862ecbebde60dd16e7ca17d26444e62f50
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Apr 8 11:19:38 2019 +0200
|
||||||
|
|
||||||
|
resolv: Remove RES_INSECURE1, RES_INSECURE2
|
||||||
|
|
||||||
|
Always perform the associated security checks.
|
||||||
|
|
||||||
|
The constants and their debug output handling are preserve in this
|
||||||
|
backport.
|
||||||
|
|
||||||
|
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||||
|
index 705ecb7189d215c2..c9b02cca130bc20d 100644
|
||||||
|
--- a/resolv/res_send.c
|
||||||
|
+++ b/resolv/res_send.c
|
||||||
|
@@ -1324,31 +1324,25 @@ send_dg(res_state statp,
|
||||||
|
*/
|
||||||
|
goto wait;
|
||||||
|
}
|
||||||
|
- if (!(statp->options & RES_INSECURE1) &&
|
||||||
|
- !res_ourserver_p(statp, &from)) {
|
||||||
|
- /*
|
||||||
|
- * response from wrong server? ignore it.
|
||||||
|
- * XXX - potential security hazard could
|
||||||
|
- * be detected here.
|
||||||
|
- */
|
||||||
|
- goto wait;
|
||||||
|
- }
|
||||||
|
- if (!(statp->options & RES_INSECURE2)
|
||||||
|
- && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
|
||||||
|
+
|
||||||
|
+ /* Paranoia check. Due to the connected UDP socket,
|
||||||
|
+ the kernel has already filtered invalid addresses
|
||||||
|
+ for us. */
|
||||||
|
+ if (!res_ourserver_p(statp, &from))
|
||||||
|
+ goto wait;
|
||||||
|
+
|
||||||
|
+ /* Check for the correct header layout and a matching
|
||||||
|
+ question. */
|
||||||
|
+ if ((recvresp1 || !res_queriesmatch(buf, buf + buflen,
|
||||||
|
*thisansp,
|
||||||
|
*thisansp
|
||||||
|
+ *thisanssizp))
|
||||||
|
&& (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
|
||||||
|
*thisansp,
|
||||||
|
*thisansp
|
||||||
|
- + *thisanssizp))) {
|
||||||
|
- /*
|
||||||
|
- * response contains wrong query? ignore it.
|
||||||
|
- * XXX - potential security hazard could
|
||||||
|
- * be detected here.
|
||||||
|
- */
|
||||||
|
- goto wait;
|
||||||
|
- }
|
||||||
|
+ + *thisanssizp)))
|
||||||
|
+ goto wait;
|
||||||
|
+
|
||||||
|
if (anhp->rcode == SERVFAIL ||
|
||||||
|
anhp->rcode == NOTIMP ||
|
||||||
|
anhp->rcode == REFUSED) {
|
51
SOURCES/glibc-rh1904153-2.patch
Normal file
51
SOURCES/glibc-rh1904153-2.patch
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
Backport the support/ changes from this commit, to avoid future
|
||||||
|
conflicts:
|
||||||
|
|
||||||
|
commit 446997ff1433d33452b81dfa9e626b8dccf101a4
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Oct 30 17:26:58 2019 +0100
|
||||||
|
|
||||||
|
resolv: Implement trust-ad option for /etc/resolv.conf [BZ #20358]
|
||||||
|
|
||||||
|
This introduces a concept of trusted name servers, for which the
|
||||||
|
AD bit is passed through to applications. For untrusted name
|
||||||
|
servers (the default), the AD bit in responses are cleared, to
|
||||||
|
provide a safe default.
|
||||||
|
|
||||||
|
This approach is very similar to the one suggested by Pavel Šimerda
|
||||||
|
in <https://bugzilla.redhat.com/show_bug.cgi?id=1164339#c15>.
|
||||||
|
|
||||||
|
The DNS test framework in support/ is enhanced with support for
|
||||||
|
setting the AD bit in responses.
|
||||||
|
|
||||||
|
Tested on x86_64-linux-gnu.
|
||||||
|
|
||||||
|
Change-Id: Ibfe0f7c73ea221c35979842c5c3b6ed486495ccc
|
||||||
|
|
||||||
|
diff --git a/support/resolv_test.c b/support/resolv_test.c
|
||||||
|
index 3f2a09f36f445878..28af227cb5ed901c 100644
|
||||||
|
--- a/support/resolv_test.c
|
||||||
|
+++ b/support/resolv_test.c
|
||||||
|
@@ -182,6 +182,8 @@ resolv_response_init (struct resolv_response_builder *b,
|
||||||
|
if (flags.tc)
|
||||||
|
b->buffer[2] |= 0x02;
|
||||||
|
b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */
|
||||||
|
+ if (flags.ad)
|
||||||
|
+ b->buffer[3] |= 0x20;
|
||||||
|
|
||||||
|
/* Fill in the initial section count values. */
|
||||||
|
b->buffer[4] = flags.qdcount >> 8;
|
||||||
|
diff --git a/support/resolv_test.h b/support/resolv_test.h
|
||||||
|
index 4c2e6c1b417f5fcd..be736aead40cd0cc 100644
|
||||||
|
--- a/support/resolv_test.h
|
||||||
|
+++ b/support/resolv_test.h
|
||||||
|
@@ -134,6 +134,9 @@ struct resolv_response_flags
|
||||||
|
/* If true, the TC (truncation) flag will be set. */
|
||||||
|
bool tc;
|
||||||
|
|
||||||
|
+ /* If true, the AD (authenticated data) flag will be set. */
|
||||||
|
+ bool ad;
|
||||||
|
+
|
||||||
|
/* Initial section count values. Can be used to artificially
|
||||||
|
increase the counts, for malformed packet testing.*/
|
||||||
|
unsigned short qdcount;
|
293
SOURCES/glibc-rh1904153-3.patch
Normal file
293
SOURCES/glibc-rh1904153-3.patch
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
commit 873e239a4c3d8ec235c27439c1bdc5bbf8aa1818
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Oct 14 10:54:39 2020 +0200
|
||||||
|
|
||||||
|
support: Provide a way to reorder responses within the DNS test server
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 3c940aa6a7bdfc99..37d5dcc92a5c6dee 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -35,6 +35,8 @@ libsupport-routines = \
|
||||||
|
ignore_stderr \
|
||||||
|
next_to_fault \
|
||||||
|
oom_error \
|
||||||
|
+ resolv_response_context_duplicate \
|
||||||
|
+ resolv_response_context_free \
|
||||||
|
resolv_test \
|
||||||
|
set_fortify_handler \
|
||||||
|
support-xfstat \
|
||||||
|
diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..f9c5c3462ad053ec
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/resolv_response_context_duplicate.c
|
||||||
|
@@ -0,0 +1,37 @@
|
||||||
|
+/* Duplicate a response context used in DNS resolver tests.
|
||||||
|
+ Copyright (C) 2020 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 <string.h>
|
||||||
|
+#include <support/resolv_test.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+struct resolv_response_context *
|
||||||
|
+resolv_response_context_duplicate (const struct resolv_response_context *ctx)
|
||||||
|
+{
|
||||||
|
+ struct resolv_response_context *result = xmalloc (sizeof (*result));
|
||||||
|
+ memcpy (result, ctx, sizeof (*result));
|
||||||
|
+ if (result->client_address != NULL)
|
||||||
|
+ {
|
||||||
|
+ result->client_address = xmalloc (result->client_address_length);
|
||||||
|
+ memcpy (result->client_address, ctx->client_address,
|
||||||
|
+ result->client_address_length);
|
||||||
|
+ }
|
||||||
|
+ result->query_buffer = xmalloc (result->query_length);
|
||||||
|
+ memcpy (result->query_buffer, ctx->query_buffer, result->query_length);
|
||||||
|
+ return result;
|
||||||
|
+}
|
||||||
|
diff --git a/support/resolv_response_context_free.c b/support/resolv_response_context_free.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..b88c05ffd4acfdd4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/resolv_response_context_free.c
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+/* Free a response context used in DNS resolver tests.
|
||||||
|
+ Copyright (C) 2020 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 <stdlib.h>
|
||||||
|
+#include <support/resolv_test.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+resolv_response_context_free (struct resolv_response_context *ctx)
|
||||||
|
+{
|
||||||
|
+ free (ctx->query_buffer);
|
||||||
|
+ free (ctx->client_address);
|
||||||
|
+ free (ctx);
|
||||||
|
+}
|
||||||
|
diff --git a/support/resolv_test.c b/support/resolv_test.c
|
||||||
|
index 28af227cb5ed901c..8cca4e6cf723de28 100644
|
||||||
|
--- a/support/resolv_test.c
|
||||||
|
+++ b/support/resolv_test.c
|
||||||
|
@@ -434,9 +434,9 @@ resolv_response_buffer (const struct resolv_response_builder *b)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static struct resolv_response_builder *
|
||||||
|
-response_builder_allocate
|
||||||
|
- (const unsigned char *query_buffer, size_t query_length)
|
||||||
|
+struct resolv_response_builder *
|
||||||
|
+resolv_response_builder_allocate (const unsigned char *query_buffer,
|
||||||
|
+ size_t query_length)
|
||||||
|
{
|
||||||
|
struct resolv_response_builder *b = xmalloc (sizeof (*b));
|
||||||
|
memset (b, 0, offsetof (struct resolv_response_builder, buffer));
|
||||||
|
@@ -445,8 +445,8 @@ response_builder_allocate
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-response_builder_free (struct resolv_response_builder *b)
|
||||||
|
+void
|
||||||
|
+resolv_response_builder_free (struct resolv_response_builder *b)
|
||||||
|
{
|
||||||
|
tdestroy (b->compression_offsets, free);
|
||||||
|
free (b);
|
||||||
|
@@ -661,13 +661,17 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
|
||||||
|
|
||||||
|
struct resolv_response_context ctx =
|
||||||
|
{
|
||||||
|
+ .test = obj,
|
||||||
|
+ .client_address = &peer,
|
||||||
|
+ .client_address_length = peerlen,
|
||||||
|
.query_buffer = query,
|
||||||
|
.query_length = length,
|
||||||
|
.server_index = server_index,
|
||||||
|
.tcp = false,
|
||||||
|
.edns = qinfo.edns,
|
||||||
|
};
|
||||||
|
- struct resolv_response_builder *b = response_builder_allocate (query, length);
|
||||||
|
+ struct resolv_response_builder *b
|
||||||
|
+ = resolv_response_builder_allocate (query, length);
|
||||||
|
obj->config.response_callback
|
||||||
|
(&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||||||
|
|
||||||
|
@@ -684,7 +688,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
|
||||||
|
if (b->offset >= 12)
|
||||||
|
printf ("info: UDP server %d: sending response:"
|
||||||
|
" %zu bytes, RCODE %d (for %s/%u/%u)\n",
|
||||||
|
- server_index, b->offset, b->buffer[3] & 0x0f,
|
||||||
|
+ ctx.server_index, b->offset, b->buffer[3] & 0x0f,
|
||||||
|
qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||||||
|
else
|
||||||
|
printf ("info: UDP server %d: sending response: %zu bytes"
|
||||||
|
@@ -694,23 +698,31 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
|
||||||
|
if (b->truncate_bytes > 0)
|
||||||
|
printf ("info: truncated by %u bytes\n", b->truncate_bytes);
|
||||||
|
}
|
||||||
|
- size_t to_send = b->offset;
|
||||||
|
- if (to_send < b->truncate_bytes)
|
||||||
|
- to_send = 0;
|
||||||
|
- else
|
||||||
|
- to_send -= b->truncate_bytes;
|
||||||
|
-
|
||||||
|
- /* Ignore most errors here because the other end may have closed
|
||||||
|
- the socket. */
|
||||||
|
- if (sendto (obj->servers[server_index].socket_udp,
|
||||||
|
- b->buffer, to_send, 0,
|
||||||
|
- (struct sockaddr *) &peer, peerlen) < 0)
|
||||||
|
- TEST_VERIFY_EXIT (errno != EBADF);
|
||||||
|
+ resolv_response_send_udp (&ctx, b);
|
||||||
|
}
|
||||||
|
- response_builder_free (b);
|
||||||
|
+ resolv_response_builder_free (b);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+resolv_response_send_udp (const struct resolv_response_context *ctx,
|
||||||
|
+ struct resolv_response_builder *b)
|
||||||
|
+{
|
||||||
|
+ TEST_VERIFY_EXIT (!ctx->tcp);
|
||||||
|
+ size_t to_send = b->offset;
|
||||||
|
+ if (to_send < b->truncate_bytes)
|
||||||
|
+ to_send = 0;
|
||||||
|
+ else
|
||||||
|
+ to_send -= b->truncate_bytes;
|
||||||
|
+
|
||||||
|
+ /* Ignore most errors here because the other end may have closed
|
||||||
|
+ the socket. */
|
||||||
|
+ if (sendto (ctx->test->servers[ctx->server_index].socket_udp,
|
||||||
|
+ b->buffer, to_send, 0,
|
||||||
|
+ ctx->client_address, ctx->client_address_length) < 0)
|
||||||
|
+ TEST_VERIFY_EXIT (errno != EBADF);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* UDP thread_callback function. Variant for one thread per
|
||||||
|
server. */
|
||||||
|
static void
|
||||||
|
@@ -897,14 +909,15 @@ server_thread_tcp_client (void *arg)
|
||||||
|
|
||||||
|
struct resolv_response_context ctx =
|
||||||
|
{
|
||||||
|
+ .test = closure->obj,
|
||||||
|
.query_buffer = query_buffer,
|
||||||
|
.query_length = query_length,
|
||||||
|
.server_index = closure->server_index,
|
||||||
|
.tcp = true,
|
||||||
|
.edns = qinfo.edns,
|
||||||
|
};
|
||||||
|
- struct resolv_response_builder *b = response_builder_allocate
|
||||||
|
- (query_buffer, query_length);
|
||||||
|
+ struct resolv_response_builder *b
|
||||||
|
+ = resolv_response_builder_allocate (query_buffer, query_length);
|
||||||
|
closure->obj->config.response_callback
|
||||||
|
(&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||||||
|
|
||||||
|
@@ -936,7 +949,7 @@ server_thread_tcp_client (void *arg)
|
||||||
|
writev_fully (closure->client_socket, buffers, 2);
|
||||||
|
}
|
||||||
|
bool close_flag = b->close;
|
||||||
|
- response_builder_free (b);
|
||||||
|
+ resolv_response_builder_free (b);
|
||||||
|
free (query_buffer);
|
||||||
|
if (close_flag)
|
||||||
|
break;
|
||||||
|
diff --git a/support/resolv_test.h b/support/resolv_test.h
|
||||||
|
index be736aead40cd0cc..ff5571dace92c936 100644
|
||||||
|
--- a/support/resolv_test.h
|
||||||
|
+++ b/support/resolv_test.h
|
||||||
|
@@ -35,25 +35,36 @@ struct resolv_edns_info
|
||||||
|
uint16_t payload_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* This opaque struct collects information about the resolver testing
|
||||||
|
+ currently in progress. */
|
||||||
|
+struct resolv_test;
|
||||||
|
+
|
||||||
|
/* This struct provides context information when the response callback
|
||||||
|
specified in struct resolv_redirect_config is invoked. */
|
||||||
|
struct resolv_response_context
|
||||||
|
{
|
||||||
|
- const unsigned char *query_buffer;
|
||||||
|
+ struct resolv_test *test;
|
||||||
|
+ void *client_address;
|
||||||
|
+ size_t client_address_length;
|
||||||
|
+ unsigned char *query_buffer;
|
||||||
|
size_t query_length;
|
||||||
|
int server_index;
|
||||||
|
bool tcp;
|
||||||
|
struct resolv_edns_info edns;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Produces a deep copy of the context. */
|
||||||
|
+struct resolv_response_context *
|
||||||
|
+ resolv_response_context_duplicate (const struct resolv_response_context *);
|
||||||
|
+
|
||||||
|
+/* Frees the copy. For the context passed to the response function,
|
||||||
|
+ this happens implicitly. */
|
||||||
|
+void resolv_response_context_free (struct resolv_response_context *);
|
||||||
|
+
|
||||||
|
/* This opaque struct is used to construct responses from within the
|
||||||
|
response callback function. */
|
||||||
|
struct resolv_response_builder;
|
||||||
|
|
||||||
|
-/* This opaque struct collects information about the resolver testing
|
||||||
|
- currently in progress. */
|
||||||
|
-struct resolv_test;
|
||||||
|
-
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* Maximum number of test servers supported by the framework. */
|
||||||
|
@@ -188,6 +199,22 @@ void resolv_response_close (struct resolv_response_builder *);
|
||||||
|
/* The size of the response packet built so far. */
|
||||||
|
size_t resolv_response_length (const struct resolv_response_builder *);
|
||||||
|
|
||||||
|
+/* Allocates a response builder tied to a specific query packet,
|
||||||
|
+ starting at QUERY_BUFFER, containing QUERY_LENGTH bytes. */
|
||||||
|
+struct resolv_response_builder *
|
||||||
|
+ resolv_response_builder_allocate (const unsigned char *query_buffer,
|
||||||
|
+ size_t query_length);
|
||||||
|
+
|
||||||
|
+/* Deallocates a response buffer. */
|
||||||
|
+void resolv_response_builder_free (struct resolv_response_builder *);
|
||||||
|
+
|
||||||
|
+/* Sends a UDP response using a specific context. This can be used to
|
||||||
|
+ reorder or duplicate responses, along with
|
||||||
|
+ resolv_response_context_duplicate and
|
||||||
|
+ response_builder_allocate. */
|
||||||
|
+void resolv_response_send_udp (const struct resolv_response_context *,
|
||||||
|
+ struct resolv_response_builder *);
|
||||||
|
+
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* SUPPORT_RESOLV_TEST_H */
|
36
SOURCES/glibc-rh1904153-4.patch
Normal file
36
SOURCES/glibc-rh1904153-4.patch
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
commit 08443b19965f48862b02c2fd7b33a39d66daf2ff
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Oct 14 10:54:39 2020 +0200
|
||||||
|
|
||||||
|
support: Provide a way to clear the RA bit in DNS server responses
|
||||||
|
|
||||||
|
diff --git a/support/resolv_test.c b/support/resolv_test.c
|
||||||
|
index 8cca4e6cf723de28..9323f1d55b0be8f1 100644
|
||||||
|
--- a/support/resolv_test.c
|
||||||
|
+++ b/support/resolv_test.c
|
||||||
|
@@ -181,7 +181,9 @@ resolv_response_init (struct resolv_response_builder *b,
|
||||||
|
b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */
|
||||||
|
if (flags.tc)
|
||||||
|
b->buffer[2] |= 0x02;
|
||||||
|
- b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */
|
||||||
|
+ b->buffer[3] = flags.rcode;
|
||||||
|
+ if (!flags.clear_ra)
|
||||||
|
+ b->buffer[3] |= 0x80;
|
||||||
|
if (flags.ad)
|
||||||
|
b->buffer[3] |= 0x20;
|
||||||
|
|
||||||
|
diff --git a/support/resolv_test.h b/support/resolv_test.h
|
||||||
|
index ff5571dace92c936..825abb9ff2897a43 100644
|
||||||
|
--- a/support/resolv_test.h
|
||||||
|
+++ b/support/resolv_test.h
|
||||||
|
@@ -148,6 +148,10 @@ struct resolv_response_flags
|
||||||
|
/* If true, the AD (authenticated data) flag will be set. */
|
||||||
|
bool ad;
|
||||||
|
|
||||||
|
+ /* If true, do not set the RA (recursion available) flag in the
|
||||||
|
+ response. */
|
||||||
|
+ bool clear_ra;
|
||||||
|
+
|
||||||
|
/* Initial section count values. Can be used to artificially
|
||||||
|
increase the counts, for malformed packet testing.*/
|
||||||
|
unsigned short qdcount;
|
442
SOURCES/glibc-rh1904153-5.patch
Normal file
442
SOURCES/glibc-rh1904153-5.patch
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
commit f1f00c072138af90ae6da180f260111f09afe7a3
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Oct 14 10:54:39 2020 +0200
|
||||||
|
|
||||||
|
resolv: Handle transaction ID collisions in parallel queries (bug 26600)
|
||||||
|
|
||||||
|
If the transaction IDs are equal, the old check attributed both
|
||||||
|
responses to the first query, not recognizing the second response.
|
||||||
|
This fixes bug 26600.
|
||||||
|
|
||||||
|
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||||
|
index 72a0f196506ac489..cee5225f8933f245 100644
|
||||||
|
--- a/resolv/Makefile
|
||||||
|
+++ b/resolv/Makefile
|
||||||
|
@@ -62,6 +62,11 @@ tests += \
|
||||||
|
tst-resolv-search \
|
||||||
|
tst-resolv-trailing \
|
||||||
|
|
||||||
|
+# This test calls __res_context_send directly, which is not exported
|
||||||
|
+# from libresolv.
|
||||||
|
+tests-internal += tst-resolv-txnid-collision
|
||||||
|
+tests-static += tst-resolv-txnid-collision
|
||||||
|
+
|
||||||
|
# These tests need libdl.
|
||||||
|
ifeq (yes,$(build-shared))
|
||||||
|
tests += \
|
||||||
|
@@ -202,6 +207,8 @@ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||||
|
$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
|
||||||
|
$(objpfx)tst-resolv-threads: \
|
||||||
|
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||||
|
+$(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \
|
||||||
|
+ $(static-thread-library)
|
||||||
|
$(objpfx)tst-resolv-canonname: \
|
||||||
|
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||||
|
|
||||||
|
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||||
|
index c9b02cca130bc20d..ac19627634281c2f 100644
|
||||||
|
--- a/resolv/res_send.c
|
||||||
|
+++ b/resolv/res_send.c
|
||||||
|
@@ -1315,15 +1315,6 @@ send_dg(res_state statp,
|
||||||
|
*terrno = EMSGSIZE;
|
||||||
|
return close_and_return_error (statp, resplen2);
|
||||||
|
}
|
||||||
|
- if ((recvresp1 || hp->id != anhp->id)
|
||||||
|
- && (recvresp2 || hp2->id != anhp->id)) {
|
||||||
|
- /*
|
||||||
|
- * response from old query, ignore it.
|
||||||
|
- * XXX - potential security hazard could
|
||||||
|
- * be detected here.
|
||||||
|
- */
|
||||||
|
- goto wait;
|
||||||
|
- }
|
||||||
|
|
||||||
|
/* Paranoia check. Due to the connected UDP socket,
|
||||||
|
the kernel has already filtered invalid addresses
|
||||||
|
@@ -1333,15 +1324,24 @@ send_dg(res_state statp,
|
||||||
|
|
||||||
|
/* Check for the correct header layout and a matching
|
||||||
|
question. */
|
||||||
|
- if ((recvresp1 || !res_queriesmatch(buf, buf + buflen,
|
||||||
|
- *thisansp,
|
||||||
|
- *thisansp
|
||||||
|
- + *thisanssizp))
|
||||||
|
- && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
|
||||||
|
- *thisansp,
|
||||||
|
- *thisansp
|
||||||
|
- + *thisanssizp)))
|
||||||
|
- goto wait;
|
||||||
|
+ int matching_query = 0; /* Default to no matching query. */
|
||||||
|
+ if (!recvresp1
|
||||||
|
+ && anhp->id == hp->id
|
||||||
|
+ && res_queriesmatch (buf, buf + buflen,
|
||||||
|
+ *thisansp, *thisansp + *thisanssizp))
|
||||||
|
+ matching_query = 1;
|
||||||
|
+ if (!recvresp2
|
||||||
|
+ && anhp->id == hp2->id
|
||||||
|
+ && res_queriesmatch (buf2, buf2 + buflen2,
|
||||||
|
+ *thisansp, *thisansp + *thisanssizp))
|
||||||
|
+ matching_query = 2;
|
||||||
|
+ if (matching_query == 0)
|
||||||
|
+ /* Spurious UDP packet. Drop it and continue
|
||||||
|
+ waiting. */
|
||||||
|
+ {
|
||||||
|
+ need_recompute = 1;
|
||||||
|
+ goto wait;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (anhp->rcode == SERVFAIL ||
|
||||||
|
anhp->rcode == NOTIMP ||
|
||||||
|
@@ -1356,7 +1356,7 @@ send_dg(res_state statp,
|
||||||
|
/* No data from the first reply. */
|
||||||
|
resplen = 0;
|
||||||
|
/* We are waiting for a possible second reply. */
|
||||||
|
- if (hp->id == anhp->id)
|
||||||
|
+ if (matching_query == 1)
|
||||||
|
recvresp1 = 1;
|
||||||
|
else
|
||||||
|
recvresp2 = 1;
|
||||||
|
@@ -1387,7 +1387,7 @@ send_dg(res_state statp,
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
/* Mark which reply we received. */
|
||||||
|
- if (recvresp1 == 0 && hp->id == anhp->id)
|
||||||
|
+ if (matching_query == 1)
|
||||||
|
recvresp1 = 1;
|
||||||
|
else
|
||||||
|
recvresp2 = 1;
|
||||||
|
diff --git a/resolv/tst-resolv-txnid-collision.c b/resolv/tst-resolv-txnid-collision.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..611d37362f3e5e89
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/resolv/tst-resolv-txnid-collision.c
|
||||||
|
@@ -0,0 +1,329 @@
|
||||||
|
+/* Test parallel queries with transaction ID collisions.
|
||||||
|
+ Copyright (C) 2020 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 <resolv-internal.h>
|
||||||
|
+#include <resolv_context.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/check_nss.h>
|
||||||
|
+#include <support/resolv_test.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/test-driver.h>
|
||||||
|
+
|
||||||
|
+/* Result of parsing a DNS question name.
|
||||||
|
+
|
||||||
|
+ A question name has the form reorder-N-M-rcode-C.example.net, where
|
||||||
|
+ N and M are either 0 and 1, corresponding to the reorder member,
|
||||||
|
+ and C is a number that will be stored in the rcode field.
|
||||||
|
+
|
||||||
|
+ Also see parse_qname below. */
|
||||||
|
+struct parsed_qname
|
||||||
|
+{
|
||||||
|
+ /* The DNS response code requested from the first server. The
|
||||||
|
+ second server always responds with RCODE zero. */
|
||||||
|
+ int rcode;
|
||||||
|
+
|
||||||
|
+ /* Indicates whether to perform reordering in the responses from the
|
||||||
|
+ respective server. */
|
||||||
|
+ bool reorder[2];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Fills *PARSED based on QNAME. */
|
||||||
|
+static void
|
||||||
|
+parse_qname (struct parsed_qname *parsed, const char *qname)
|
||||||
|
+{
|
||||||
|
+ int reorder0;
|
||||||
|
+ int reorder1;
|
||||||
|
+ int rcode;
|
||||||
|
+ char *suffix;
|
||||||
|
+ if (sscanf (qname, "reorder-%d-%d.rcode-%d.%ms",
|
||||||
|
+ &reorder0, &reorder1, &rcode, &suffix) == 4)
|
||||||
|
+ {
|
||||||
|
+ if (reorder0 != 0)
|
||||||
|
+ TEST_COMPARE (reorder0, 1);
|
||||||
|
+ if (reorder1 != 0)
|
||||||
|
+ TEST_COMPARE (reorder1, 1);
|
||||||
|
+ TEST_VERIFY (rcode >= 0 && rcode <= 15);
|
||||||
|
+ TEST_COMPARE_STRING (suffix, "example.net");
|
||||||
|
+ free (suffix);
|
||||||
|
+
|
||||||
|
+ parsed->rcode = rcode;
|
||||||
|
+ parsed->reorder[0] = reorder0;
|
||||||
|
+ parsed->reorder[1] = reorder1;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ FAIL_EXIT1 ("unexpected query: %s", qname);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Used to construct a response. The first server responds with an
|
||||||
|
+ error, the second server succeeds. */
|
||||||
|
+static void
|
||||||
|
+build_response (const struct resolv_response_context *ctx,
|
||||||
|
+ struct resolv_response_builder *b,
|
||||||
|
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||||
|
+{
|
||||||
|
+ struct parsed_qname parsed;
|
||||||
|
+ parse_qname (&parsed, qname);
|
||||||
|
+
|
||||||
|
+ switch (ctx->server_index)
|
||||||
|
+ {
|
||||||
|
+ case 0:
|
||||||
|
+ {
|
||||||
|
+ struct resolv_response_flags flags = { 0 };
|
||||||
|
+ if (parsed.rcode == 0)
|
||||||
|
+ /* Simulate a delegation in case a NODATA (RCODE zero)
|
||||||
|
+ response is requested. */
|
||||||
|
+ flags.clear_ra = true;
|
||||||
|
+ else
|
||||||
|
+ flags.rcode = parsed.rcode;
|
||||||
|
+
|
||||||
|
+ resolv_response_init (b, flags);
|
||||||
|
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 1:
|
||||||
|
+ {
|
||||||
|
+ struct resolv_response_flags flags = { 0, };
|
||||||
|
+ resolv_response_init (b, flags);
|
||||||
|
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||||
|
+
|
||||||
|
+ resolv_response_section (b, ns_s_an);
|
||||||
|
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||||||
|
+ if (qtype == T_A)
|
||||||
|
+ {
|
||||||
|
+ char ipv4[4] = { 192, 0, 2, 1 };
|
||||||
|
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ char ipv6[16]
|
||||||
|
+ = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
||||||
|
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||||
|
+ }
|
||||||
|
+ resolv_response_close_record (b);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Used to reorder responses. */
|
||||||
|
+struct resolv_response_context *previous_query;
|
||||||
|
+
|
||||||
|
+/* Used to keep track of the queries received. */
|
||||||
|
+static int previous_server_index = -1;
|
||||||
|
+static uint16_t previous_qtype;
|
||||||
|
+
|
||||||
|
+/* For each server, buffer the first query and then send both answers
|
||||||
|
+ to the second query, reordered if requested. */
|
||||||
|
+static void
|
||||||
|
+response (const struct resolv_response_context *ctx,
|
||||||
|
+ struct resolv_response_builder *b,
|
||||||
|
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||||
|
+{
|
||||||
|
+ TEST_VERIFY (qtype == T_A || qtype == T_AAAA);
|
||||||
|
+ if (ctx->server_index != 0)
|
||||||
|
+ TEST_COMPARE (ctx->server_index, 1);
|
||||||
|
+
|
||||||
|
+ struct parsed_qname parsed;
|
||||||
|
+ parse_qname (&parsed, qname);
|
||||||
|
+
|
||||||
|
+ if (previous_query == NULL)
|
||||||
|
+ {
|
||||||
|
+ /* No buffered query. Record this query and do not send a
|
||||||
|
+ response. */
|
||||||
|
+ TEST_COMPARE (previous_qtype, 0);
|
||||||
|
+ previous_query = resolv_response_context_duplicate (ctx);
|
||||||
|
+ previous_qtype = qtype;
|
||||||
|
+ resolv_response_drop (b);
|
||||||
|
+ previous_server_index = ctx->server_index;
|
||||||
|
+
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: buffering first query for: %s\n", qname);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ TEST_VERIFY (previous_query != 0);
|
||||||
|
+ TEST_COMPARE (ctx->server_index, previous_server_index);
|
||||||
|
+ TEST_VERIFY (previous_qtype != qtype); /* Not a duplicate. */
|
||||||
|
+
|
||||||
|
+ /* If reordering, send a response for this query explicitly, and
|
||||||
|
+ then skip the implicit send. */
|
||||||
|
+ if (parsed.reorder[ctx->server_index])
|
||||||
|
+ {
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: sending reordered second response for: %s\n",
|
||||||
|
+ qname);
|
||||||
|
+ build_response (ctx, b, qname, qclass, qtype);
|
||||||
|
+ resolv_response_send_udp (ctx, b);
|
||||||
|
+ resolv_response_drop (b);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Build a response for the previous query and send it, thus
|
||||||
|
+ reordering the two responses. */
|
||||||
|
+ {
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: sending first response for: %s\n", qname);
|
||||||
|
+ struct resolv_response_builder *btmp
|
||||||
|
+ = resolv_response_builder_allocate (previous_query->query_buffer,
|
||||||
|
+ previous_query->query_length);
|
||||||
|
+ build_response (ctx, btmp, qname, qclass, previous_qtype);
|
||||||
|
+ resolv_response_send_udp (ctx, btmp);
|
||||||
|
+ resolv_response_builder_free (btmp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If not reordering, send the reply as usual. */
|
||||||
|
+ if (!parsed.reorder[ctx->server_index])
|
||||||
|
+ {
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: sending non-reordered second response for: %s\n",
|
||||||
|
+ qname);
|
||||||
|
+ build_response (ctx, b, qname, qclass, qtype);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Unbuffer the response and prepare for the next query. */
|
||||||
|
+ resolv_response_context_free (previous_query);
|
||||||
|
+ previous_query = NULL;
|
||||||
|
+ previous_qtype = 0;
|
||||||
|
+ previous_server_index = -1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Runs a query for QNAME and checks for the expected reply. See
|
||||||
|
+ struct parsed_qname for the expected format for QNAME. */
|
||||||
|
+static void
|
||||||
|
+test_qname (const char *qname, int rcode)
|
||||||
|
+{
|
||||||
|
+ struct resolv_context *ctx = __resolv_context_get ();
|
||||||
|
+ TEST_VERIFY_EXIT (ctx != NULL);
|
||||||
|
+
|
||||||
|
+ unsigned char q1[512];
|
||||||
|
+ int q1len = res_mkquery (QUERY, qname, C_IN, T_A, NULL, 0, NULL,
|
||||||
|
+ q1, sizeof (q1));
|
||||||
|
+ TEST_VERIFY_EXIT (q1len > 12);
|
||||||
|
+
|
||||||
|
+ unsigned char q2[512];
|
||||||
|
+ int q2len = res_mkquery (QUERY, qname, C_IN, T_AAAA, NULL, 0, NULL,
|
||||||
|
+ q2, sizeof (q2));
|
||||||
|
+ TEST_VERIFY_EXIT (q2len > 12);
|
||||||
|
+
|
||||||
|
+ /* Produce a transaction ID collision. */
|
||||||
|
+ memcpy (q2, q1, 2);
|
||||||
|
+
|
||||||
|
+ unsigned char ans1[512];
|
||||||
|
+ unsigned char *ans1p = ans1;
|
||||||
|
+ unsigned char *ans2p = NULL;
|
||||||
|
+ int nans2p = 0;
|
||||||
|
+ int resplen2 = 0;
|
||||||
|
+ int ans2p_malloced = 0;
|
||||||
|
+
|
||||||
|
+ /* Perform a parallel A/AAAA query. */
|
||||||
|
+ int resplen1 = __res_context_send (ctx, q1, q1len, q2, q2len,
|
||||||
|
+ ans1, sizeof (ans1), &ans1p,
|
||||||
|
+ &ans2p, &nans2p,
|
||||||
|
+ &resplen2, &ans2p_malloced);
|
||||||
|
+
|
||||||
|
+ TEST_VERIFY (resplen1 > 12);
|
||||||
|
+ TEST_VERIFY (resplen2 > 12);
|
||||||
|
+ if (resplen1 <= 12 || resplen2 <= 12)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (rcode == 1 || rcode == 3)
|
||||||
|
+ {
|
||||||
|
+ /* Format Error and Name Error responses does not trigger
|
||||||
|
+ switching to the next server. */
|
||||||
|
+ TEST_COMPARE (ans1p[3] & 0x0f, rcode);
|
||||||
|
+ TEST_COMPARE (ans2p[3] & 0x0f, rcode);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* The response should be successful. */
|
||||||
|
+ TEST_COMPARE (ans1p[3] & 0x0f, 0);
|
||||||
|
+ TEST_COMPARE (ans2p[3] & 0x0f, 0);
|
||||||
|
+
|
||||||
|
+ /* Due to bug 19691, the answer may not be in the slot matching the
|
||||||
|
+ query. Assume that the AAAA response is the longer one. */
|
||||||
|
+ unsigned char *a_answer;
|
||||||
|
+ int a_answer_length;
|
||||||
|
+ unsigned char *aaaa_answer;
|
||||||
|
+ int aaaa_answer_length;
|
||||||
|
+ if (resplen2 > resplen1)
|
||||||
|
+ {
|
||||||
|
+ a_answer = ans1p;
|
||||||
|
+ a_answer_length = resplen1;
|
||||||
|
+ aaaa_answer = ans2p;
|
||||||
|
+ aaaa_answer_length = resplen2;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ a_answer = ans2p;
|
||||||
|
+ a_answer_length = resplen2;
|
||||||
|
+ aaaa_answer = ans1p;
|
||||||
|
+ aaaa_answer_length = resplen1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ {
|
||||||
|
+ char *expected = xasprintf ("name: %s\n"
|
||||||
|
+ "address: 192.0.2.1\n",
|
||||||
|
+ qname);
|
||||||
|
+ check_dns_packet (qname, a_answer, a_answer_length, expected);
|
||||||
|
+ free (expected);
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ char *expected = xasprintf ("name: %s\n"
|
||||||
|
+ "address: 2001:db8::1\n",
|
||||||
|
+ qname);
|
||||||
|
+ check_dns_packet (qname, aaaa_answer, aaaa_answer_length, expected);
|
||||||
|
+ free (expected);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ans2p_malloced)
|
||||||
|
+ free (ans2p);
|
||||||
|
+
|
||||||
|
+ __resolv_context_put (ctx);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ struct resolv_test *aux = resolv_test_start
|
||||||
|
+ ((struct resolv_redirect_config)
|
||||||
|
+ {
|
||||||
|
+ .response_callback = response,
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ for (int rcode = 0; rcode <= 5; ++rcode)
|
||||||
|
+ for (int do_reorder_0 = 0; do_reorder_0 < 2; ++do_reorder_0)
|
||||||
|
+ for (int do_reorder_1 = 0; do_reorder_1 < 2; ++do_reorder_1)
|
||||||
|
+ {
|
||||||
|
+ char *qname = xasprintf ("reorder-%d-%d.rcode-%d.example.net",
|
||||||
|
+ do_reorder_0, do_reorder_1, rcode);
|
||||||
|
+ test_qname (qname, rcode);
|
||||||
|
+ free (qname);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ resolv_test_end (aux);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
31
SOURCES/glibc-rh1904153-6.patch
Normal file
31
SOURCES/glibc-rh1904153-6.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
commit b8b53b338f6da91e86d115a39da860cefac736ad
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 15 12:33:13 2020 +0200
|
||||||
|
|
||||||
|
resolv: Serialize processing in resolv/tst-resolv-txnid-collision
|
||||||
|
|
||||||
|
When switching name servers, response processing by two server
|
||||||
|
threads clobbers the global test state. (There is still some
|
||||||
|
risk that this test is negatively impact by packet drops and
|
||||||
|
packet reordering, but this applies to many of the resolver tests
|
||||||
|
and is difficult to avoid.)
|
||||||
|
|
||||||
|
Fixes commit f1f00c072138af90ae6da180f260111f09afe7a3 ("resolv:
|
||||||
|
Handle transaction ID collisions in parallel queries (bug 26600)").
|
||||||
|
|
||||||
|
diff --git a/resolv/tst-resolv-txnid-collision.c b/resolv/tst-resolv-txnid-collision.c
|
||||||
|
index 611d37362f3e5e89..189b76f1268f4e4d 100644
|
||||||
|
--- a/resolv/tst-resolv-txnid-collision.c
|
||||||
|
+++ b/resolv/tst-resolv-txnid-collision.c
|
||||||
|
@@ -309,6 +309,11 @@ do_test (void)
|
||||||
|
((struct resolv_redirect_config)
|
||||||
|
{
|
||||||
|
.response_callback = response,
|
||||||
|
+
|
||||||
|
+ /* The response callback use global state (the previous_*
|
||||||
|
+ variables), and query processing must therefore be
|
||||||
|
+ serialized. */
|
||||||
|
+ .single_thread_udp = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int rcode = 0; rcode <= 5; ++rcode)
|
97
SOURCES/glibc-rh1913750-1.patch
Normal file
97
SOURCES/glibc-rh1913750-1.patch
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
commit d3c57027470b78dba79c6d931e4e409b1fecfc80
|
||||||
|
Author: Patrick McGehearty <patrick.mcgehearty@oracle.com>
|
||||||
|
Date: Mon Sep 28 20:11:28 2020 +0000
|
||||||
|
|
||||||
|
Reversing calculation of __x86_shared_non_temporal_threshold
|
||||||
|
|
||||||
|
The __x86_shared_non_temporal_threshold determines when memcpy on x86
|
||||||
|
uses non_temporal stores to avoid pushing other data out of the last
|
||||||
|
level cache.
|
||||||
|
|
||||||
|
This patch proposes to revert the calculation change made by H.J. Lu's
|
||||||
|
patch of June 2, 2017.
|
||||||
|
|
||||||
|
H.J. Lu's patch selected a threshold suitable for a single thread
|
||||||
|
getting maximum performance. It was tuned using the single threaded
|
||||||
|
large memcpy micro benchmark on an 8 core processor. The last change
|
||||||
|
changes the threshold from using 3/4 of one thread's share of the
|
||||||
|
cache to using 3/4 of the entire cache of a multi-threaded system
|
||||||
|
before switching to non-temporal stores. Multi-threaded systems with
|
||||||
|
more than a few threads are server-class and typically have many
|
||||||
|
active threads. If one thread consumes 3/4 of the available cache for
|
||||||
|
all threads, it will cause other active threads to have data removed
|
||||||
|
from the cache. Two examples show the range of the effect. John
|
||||||
|
McCalpin's widely parallel Stream benchmark, which runs in parallel
|
||||||
|
and fetches data sequentially, saw a 20% slowdown with this patch on
|
||||||
|
an internal system test of 128 threads. This regression was discovered
|
||||||
|
when comparing OL8 performance to OL7. An example that compares
|
||||||
|
normal stores to non-temporal stores may be found at
|
||||||
|
https://vgatherps.github.io/2018-09-02-nontemporal/. A simple test
|
||||||
|
shows performance loss of 400 to 500% due to a failure to use
|
||||||
|
nontemporal stores. These performance losses are most likely to occur
|
||||||
|
when the system load is heaviest and good performance is critical.
|
||||||
|
|
||||||
|
The tunable x86_non_temporal_threshold can be used to override the
|
||||||
|
default for the knowledgable user who really wants maximum cache
|
||||||
|
allocation to a single thread in a multi-threaded system.
|
||||||
|
The manual entry for the tunable has been expanded to provide
|
||||||
|
more information about its purpose.
|
||||||
|
|
||||||
|
modified: sysdeps/x86/cacheinfo.c
|
||||||
|
modified: manual/tunables.texi
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
manual/tunables.texi
|
||||||
|
(Downstream uses the glibc.tune namespace, upstream uses
|
||||||
|
glibc.cpu.)
|
||||||
|
sysdeps/x86/cacheinfo.c
|
||||||
|
(Downstream does not have rep_movsb_threshold,
|
||||||
|
x86_rep_stosb_threshold tunables.)
|
||||||
|
|
||||||
|
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||||
|
index 3dc6f9a44592c030..3e1e519dff153b09 100644
|
||||||
|
--- a/manual/tunables.texi
|
||||||
|
+++ b/manual/tunables.texi
|
||||||
|
@@ -364,7 +364,11 @@ set shared cache size in bytes for use in memory and string routines.
|
||||||
|
|
||||||
|
@deftp Tunable glibc.tune.x86_non_temporal_threshold
|
||||||
|
The @code{glibc.tune.x86_non_temporal_threshold} tunable allows the user
|
||||||
|
-to set threshold in bytes for non temporal store.
|
||||||
|
+to set threshold in bytes for non temporal store. Non temporal stores
|
||||||
|
+give a hint to the hardware to move data directly to memory without
|
||||||
|
+displacing other data from the cache. This tunable is used by some
|
||||||
|
+platforms to determine when to use non temporal stores in operations
|
||||||
|
+like memmove and memcpy.
|
||||||
|
|
||||||
|
This tunable is specific to i386 and x86-64.
|
||||||
|
@end deftp
|
||||||
|
diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
|
||||||
|
index b9444ddd52051e05..42b468d0c4885bad 100644
|
||||||
|
--- a/sysdeps/x86/cacheinfo.c
|
||||||
|
+++ b/sysdeps/x86/cacheinfo.c
|
||||||
|
@@ -778,14 +778,20 @@ intel_bug_no_cache_info:
|
||||||
|
__x86_shared_cache_size = shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* The large memcpy micro benchmark in glibc shows that 6 times of
|
||||||
|
- shared cache size is the approximate value above which non-temporal
|
||||||
|
- store becomes faster on a 8-core processor. This is the 3/4 of the
|
||||||
|
- total shared cache size. */
|
||||||
|
+ /* The default setting for the non_temporal threshold is 3/4 of one
|
||||||
|
+ thread's share of the chip's cache. For most Intel and AMD processors
|
||||||
|
+ with an initial release date between 2017 and 2020, a thread's typical
|
||||||
|
+ share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4
|
||||||
|
+ threshold leaves 125 KBytes to 500 KBytes of the thread's data
|
||||||
|
+ in cache after a maximum temporal copy, which will maintain
|
||||||
|
+ in cache a reasonable portion of the thread's stack and other
|
||||||
|
+ active data. If the threshold is set higher than one thread's
|
||||||
|
+ share of the cache, it has a substantial risk of negatively
|
||||||
|
+ impacting the performance of other threads running on the chip. */
|
||||||
|
__x86_shared_non_temporal_threshold
|
||||||
|
= (cpu_features->non_temporal_threshold != 0
|
||||||
|
? cpu_features->non_temporal_threshold
|
||||||
|
- : __x86_shared_cache_size * threads * 3 / 4);
|
||||||
|
+ : __x86_shared_cache_size * 3 / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
64
SOURCES/glibc-rh1913750-2.patch
Normal file
64
SOURCES/glibc-rh1913750-2.patch
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
commit 8813b2682e4094e43b0cf1634e99619f1b8b2c62
|
||||||
|
Author: Sajan Karumanchi <sajan.karumanchi@amd.com>
|
||||||
|
Date: Wed Oct 28 13:05:33 2020 +0530
|
||||||
|
|
||||||
|
x86: Optimizing memcpy for AMD Zen architecture.
|
||||||
|
|
||||||
|
Modifying the shareable cache '__x86_shared_cache_size', which is a
|
||||||
|
factor in computing the non-temporal threshold parameter
|
||||||
|
'__x86_shared_non_temporal_threshold' to optimize memcpy for AMD Zen
|
||||||
|
architectures.
|
||||||
|
In the existing implementation, the shareable cache is computed as 'L3
|
||||||
|
per thread, L2 per core'. Recomputing this shareable cache as 'L3 per
|
||||||
|
CCX(Core-Complex)' has brought in performance gains.
|
||||||
|
As per the large bench variant results, this patch also addresses the
|
||||||
|
regression problem on AMD Zen architectures.
|
||||||
|
|
||||||
|
Backport of commit 59803e81f96b479c17f583b31eac44b57591a1bf upstream,
|
||||||
|
with the fix from cb3a749a22a55645dc6a52659eea765300623f98 ("x86:
|
||||||
|
Restore processing of cache size tunables in init_cacheinfo") applied.
|
||||||
|
|
||||||
|
Reviewed-by: Premachandra Mallappa <premachandra.mallappa@amd.com>
|
||||||
|
Co-Authored-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
Backport is off the release/2.32/master branch upstream, to minimize
|
||||||
|
conflicts. Adjusted for missing "basic" member in struct cpu_features.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
|
||||||
|
index 42b468d0c4885bad..57c36d030a76c8b2 100644
|
||||||
|
--- a/sysdeps/x86/cacheinfo.c
|
||||||
|
+++ b/sysdeps/x86/cacheinfo.c
|
||||||
|
@@ -722,7 +722,7 @@ intel_bug_no_cache_info:
|
||||||
|
threads = 1 << ((ecx >> 12) & 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (threads == 0)
|
||||||
|
+ if (threads == 0 || cpu_features->family >= 0x17)
|
||||||
|
{
|
||||||
|
/* If APIC ID width is not available, use logical
|
||||||
|
processor count. */
|
||||||
|
@@ -737,8 +737,22 @@ intel_bug_no_cache_info:
|
||||||
|
if (threads > 0)
|
||||||
|
shared /= threads;
|
||||||
|
|
||||||
|
- /* Account for exclusive L2 and L3 caches. */
|
||||||
|
- shared += core;
|
||||||
|
+ /* Get shared cache per ccx for Zen architectures. */
|
||||||
|
+ if (cpu_features->family >= 0x17)
|
||||||
|
+ {
|
||||||
|
+ unsigned int eax;
|
||||||
|
+
|
||||||
|
+ /* Get number of threads share the L3 cache in CCX. */
|
||||||
|
+ __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx);
|
||||||
|
+
|
||||||
|
+ unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1;
|
||||||
|
+ shared *= threads_per_ccx;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Account for exclusive L2 and L3 caches. */
|
||||||
|
+ shared += core;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_PREFETCHW
|
@ -1,6 +1,6 @@
|
|||||||
%define glibcsrcdir glibc-2.28
|
%define glibcsrcdir glibc-2.28
|
||||||
%define glibcversion 2.28
|
%define glibcversion 2.28
|
||||||
%define glibcrelease 127%{?dist}
|
%define glibcrelease 127%{?dist}.2
|
||||||
# Pre-release tarballs are pulled in from git using a command that is
|
# Pre-release tarballs are pulled in from git using a command that is
|
||||||
# effectively:
|
# effectively:
|
||||||
#
|
#
|
||||||
@ -486,6 +486,14 @@ Patch352: glibc-rh1642150-4.patch
|
|||||||
Patch353: glibc-rh1836867.patch
|
Patch353: glibc-rh1836867.patch
|
||||||
Patch354: glibc-rh1821531-1.patch
|
Patch354: glibc-rh1821531-1.patch
|
||||||
Patch355: glibc-rh1821531-2.patch
|
Patch355: glibc-rh1821531-2.patch
|
||||||
|
Patch356: glibc-rh1904153-1.patch
|
||||||
|
Patch357: glibc-rh1904153-2.patch
|
||||||
|
Patch358: glibc-rh1904153-3.patch
|
||||||
|
Patch359: glibc-rh1904153-4.patch
|
||||||
|
Patch360: glibc-rh1904153-5.patch
|
||||||
|
Patch361: glibc-rh1904153-6.patch
|
||||||
|
Patch362: glibc-rh1913750-1.patch
|
||||||
|
Patch363: glibc-rh1913750-2.patch
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Continued list of core "glibc" package information:
|
# Continued list of core "glibc" package information:
|
||||||
@ -2384,6 +2392,12 @@ fi
|
|||||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Jan 5 2021 Florian Weimer <fweimer@redhat.com> - 2.28-127.2
|
||||||
|
- x86: Update auto-tuning of memcpy non-temporal threshold (#1913750)
|
||||||
|
|
||||||
|
* Mon Dec 7 2020 Florian Weimer <fweimer@redhat.com> - 2.28-127.1
|
||||||
|
- resolv: Handle DNS transaction ID collisions (#1904153)
|
||||||
|
|
||||||
* Tue Jun 09 2020 Carlos O'Donell <calros@redhat.com> - 2.28-127
|
* Tue Jun 09 2020 Carlos O'Donell <calros@redhat.com> - 2.28-127
|
||||||
- Improve performance of library strstr() function (#1821531)
|
- Improve performance of library strstr() function (#1821531)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user