Merge branch 'master' into f20

This commit is contained in:
Tomas Hozza 2013-10-29 15:18:12 +01:00
commit c159c78652
3 changed files with 223 additions and 138 deletions

View File

@ -26,7 +26,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
Name: bind
License: ISC
Version: 9.9.4
Release: 3%{?PATCHVER}%{?PREVER}%{?dist}
Release: 4%{?PATCHVER}%{?PREVER}%{?dist}
Epoch: 32
Url: http://www.isc.org/products/BIND/
Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@ -82,8 +82,8 @@ Patch137:bind99-rrl.patch
# Install dns/update.h header for bind-dyndb-ldap plugin
Patch138:bind-9.9.3-include-update-h.patch
Patch139:bind99-ISC-Bugs-34738.patch
# reported upstream -> [ISC-Bugs #34870]
Patch140:bind99-ISC-Bugs-34870.patch
# upstream patch [ISC-Bugs #34870]
Patch140:bind99-ISC-Bugs-34870-v2.patch
# SDB patches
Patch11: bind-9.3.2b2-sdbsrc.patch
@ -787,6 +787,9 @@ rm -rf ${RPM_BUILD_ROOT}
%endif
%changelog
* Tue Oct 29 2013 Tomas Hozza <thozza@redhat.com> 32:9.9.4-4
- Use upstream version of patch for previously fixed #794940
* Fri Oct 18 2013 Tomas Hozza <thozza@redhat.com> 32:9.9.4-3
- Fix race condition on send buffers in dighost.c (#794940)

View File

@ -0,0 +1,217 @@
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 2b7b970..491192d 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -180,6 +180,7 @@ isc_boolean_t validated = ISC_TRUE;
isc_entropy_t *entp = NULL;
isc_mempool_t *commctx = NULL;
isc_boolean_t debugging = ISC_FALSE;
+isc_boolean_t debugtiming = ISC_FALSE;
isc_boolean_t memdebugging = ISC_FALSE;
char *progname = NULL;
isc_mutex_t lookup_lock;
@@ -539,6 +540,12 @@ debug(const char *format, ...) {
if (debugging) {
fflush(stdout);
+ if (debugtiming) {
+ struct timeval tv;
+ (void)gettimeofday(&tv, NULL);
+ fprintf(stderr, "%ld.%06ld: ", (long)tv.tv_sec,
+ (long)tv.tv_usec);
+ }
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
@@ -2365,8 +2372,10 @@ send_done(isc_task_t *_task, isc_event_t *event) {
for (b = ISC_LIST_HEAD(sevent->bufferlist);
b != NULL;
- b = ISC_LIST_HEAD(sevent->bufferlist))
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+ isc_mem_free(mctx, b);
+ }
query = event->ev_arg;
query->waiting_senddone = ISC_FALSE;
@@ -2558,6 +2567,17 @@ send_tcp_connect(dig_query_t *query) {
}
}
+static isc_buffer_t *
+clone_buffer(isc_buffer_t *source) {
+ isc_buffer_t *buffer;
+ buffer = isc_mem_allocate(mctx, sizeof(*buffer));
+ if (buffer == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ *buffer = *source;
+ return (buffer);
+}
+
/*%
* Send a UDP packet to the remote nameserver, possible starting the
* recv action as well. Also make sure that the timer is running and
@@ -2567,6 +2587,7 @@ static void
send_udp(dig_query_t *query) {
dig_lookup_t *l = NULL;
isc_result_t result;
+ isc_buffer_t *sendbuf;
debug("send_udp(%p)", query);
@@ -2613,14 +2634,16 @@ send_udp(dig_query_t *query) {
debug("recvcount=%d", recvcount);
}
ISC_LIST_INIT(query->sendlist);
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ sendbuf = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
debug("sending a request");
TIME_NOW(&query->time_sent);
INSIST(query->sock != NULL);
query->waiting_senddone = ISC_TRUE;
- result = isc_socket_sendtov(query->sock, &query->sendlist,
- global_task, send_done, query,
- &query->sockaddr, NULL);
+ result = isc_socket_sendtov2(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL,
+ ISC_SOCKFLAG_NORETRY);
check_result(result, "isc_socket_sendtov");
sendcount++;
}
@@ -2782,6 +2805,7 @@ static void
launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_result_t result;
dig_lookup_t *l;
+ isc_buffer_t *buffer;
INSIST(!free_now);
@@ -2805,9 +2829,13 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
ISC_LIST_INIT(query->sendlist);
ISC_LINK_INIT(&query->slbuf, link);
- ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
- if (include_question)
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ buffer = clone_buffer(&query->slbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ if (include_question) {
+ buffer = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ }
+
ISC_LINK_INIT(&query->lengthbuf, link);
ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
diff --git a/bin/dig/host.c b/bin/dig/host.c
index 49fe991..3cb3ddf 100644
--- a/bin/dig/host.c
+++ b/bin/dig/host.c
@@ -638,6 +638,8 @@ pre_parse_args(int argc, char **argv) {
case 'w': break;
case 'C': break;
case 'D':
+ if (debugging)
+ debugtiming = ISC_TRUE;
debugging = ISC_TRUE;
break;
case 'N': break;
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
index f04440c..41463d1 100644
--- a/bin/dig/include/dig/dig.h
+++ b/bin/dig/include/dig/dig.h
@@ -275,7 +275,7 @@ extern isc_boolean_t validated;
extern isc_taskmgr_t *taskmgr;
extern isc_task_t *global_task;
extern isc_boolean_t free_now;
-extern isc_boolean_t debugging, memdebugging;
+extern isc_boolean_t debugging, debugtiming, memdebugging;
extern char *progname;
extern int tries;
diff --git a/lib/isc/include/isc/namespace.h b/lib/isc/include/isc/namespace.h
index f8744d8..e9bda5e 100644
--- a/lib/isc/include/isc/namespace.h
+++ b/lib/isc/include/isc/namespace.h
@@ -106,6 +106,7 @@
#define isc_socket_sendv isc__socket_sendv
#define isc_socket_sendtov isc__socket_sendtov
#define isc_socket_sendto2 isc__socket_sendto2
+#define isc_socket_sendtov2 isc__socket_sendtov2
#define isc_socket_cleanunix isc__socket_cleanunix
#define isc_socket_permunix isc__socket_permunix
#define isc_socket_bind isc__socket_bind
diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h
index 9d086b4..c5a753a 100644
--- a/lib/isc/include/isc/socket.h
+++ b/lib/isc/include/isc/socket.h
@@ -866,6 +866,11 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
isc_result_t
+isc_socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ unsigned int flags);
+isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index dc0b141..9b99acb 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -505,6 +505,11 @@ isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ unsigned int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
@@ -4791,15 +4796,25 @@ ISC_SOCKETFUNC_SCOPE isc_result_t
isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg)
{
- return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL,
- NULL));
+ return (isc__socket_sendtov2(sock, buflist, task, action, arg, NULL,
+ NULL, 0));
}
ISC_SOCKETFUNC_SCOPE isc_result_t
-isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
+ return (isc__socket_sendtov2(sock, buflist, task, action, arg, address,
+ pktinfo, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov2(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ unsigned int flags)
+{
isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socketevent_t *dev;
isc__socketmgr_t *manager;
@@ -4832,7 +4847,7 @@ isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
buffer = ISC_LIST_HEAD(*buflist);
}
- return (socket_send(sock, dev, task, address, pktinfo, 0));
+ return (socket_send(sock, dev, task, address, pktinfo, flags));
}
ISC_SOCKETFUNC_SCOPE isc_result_t

View File

@ -1,135 +0,0 @@
From 527e971a732d645d411df842ec4f8c401248ca0c Mon Sep 17 00:00:00 2001
From: Tomas Hozza <thozza@redhat.com>
Date: Fri, 18 Oct 2013 10:47:21 +0200
Subject: [PATCH] Dynamically allocate send buffers when sending query
This prevents race condition, when the same buffer could be added into
multiple bufferlists. One case when this happens is when timeout of sent
UDP query expires before send_done() is called.
New function isc_buffer_cloneused() has been added, so dynamically
allocated copy of used region of a buffer can be created easily.
(It should be added into buffer.c but to prevent API change it is
in dighost.c)
All functions creating a send socket event with send_done() callback
have been modified to make dynamically allocated copies of every buffer
added into query->sendlist. This list is then bounded to the send socket
event. This way the same buffer can not be anymore added to the same
bufferlist. Previously allocated copies of buffers are freed in
send_done() callback.
Signed-off-by: Tomas Hozza <thozza@redhat.com>
---
bin/dig/dighost.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 53 insertions(+), 5 deletions(-)
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 0d41529..7899c49 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -362,6 +362,36 @@ struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
"isc_mutex_unlock");\
}
+static isc_result_t
+isc_buffer_cloneused(isc_mem_t *mctx, isc_buffer_t *src_buffer, isc_buffer_t **dynbuffer) {
+ /*
+ * Make 'dynbuffer' refer to a dynamically allocated copy of used region of 'src_buffer'.
+ */
+ isc_result_t result;
+ isc_region_t used_region;
+ isc_buffer_t *tmpbuf = NULL;
+
+ REQUIRE(dynbuffer != NULL);
+ REQUIRE(*dynbuffer == NULL);
+ REQUIRE(src_buffer != NULL);
+ REQUIRE(ISC_BUFFER_VALID(src_buffer));
+
+ result = isc_buffer_allocate(mctx, &tmpbuf, src_buffer->length);
+ if (result != ISC_R_SUCCESS)
+ return result;
+
+ isc_buffer_usedregion(src_buffer, &used_region);
+ result = isc_buffer_copyregion(tmpbuf, &used_region);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&tmpbuf);
+ return result;
+ }
+
+ *dynbuffer = tmpbuf;
+
+ return (ISC_R_SUCCESS);
+}
+
static void
cancel_lookup(dig_lookup_t *lookup);
@@ -2416,8 +2446,10 @@ send_done(isc_task_t *_task, isc_event_t *event) {
for (b = ISC_LIST_HEAD(sevent->bufferlist);
b != NULL;
- b = ISC_LIST_HEAD(sevent->bufferlist))
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+ isc_buffer_free(&b);
+ }
query = event->ev_arg;
query->waiting_senddone = ISC_FALSE;
@@ -2617,6 +2649,7 @@ send_tcp_connect(dig_query_t *query) {
static void
send_udp(dig_query_t *query) {
dig_lookup_t *l = NULL;
+ isc_buffer_t *tmpbuf = NULL;
isc_result_t result;
debug("send_udp(%p)", query);
@@ -2663,8 +2696,14 @@ send_udp(dig_query_t *query) {
recvcount++;
debug("recvcount=%d", recvcount);
}
+ /*
+ * Make a copy of the query send buffer so it is not reused
+ * in multiple socket send events. The buffer is freed in send_done().
+ */
+ result = isc_buffer_cloneused(mctx, &query->sendbuf, &tmpbuf);
+ check_result(result, "isc_buffer_cloneused");
ISC_LIST_INIT(query->sendlist);
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
debug("sending a request");
TIME_NOW(&query->time_sent);
INSIST(query->sock != NULL);
@@ -2838,6 +2877,7 @@ static void
launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_result_t result;
dig_lookup_t *l;
+ isc_buffer_t *tmpbuf = NULL;
INSIST(!free_now);
@@ -2861,9 +2901,17 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
ISC_LIST_INIT(query->sendlist);
ISC_LINK_INIT(&query->slbuf, link);
- ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
- if (include_question)
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+
+ /* need to clone send buffers as they are freed in send_done() */
+ result = isc_buffer_cloneused(mctx, &query->slbuf, &tmpbuf);
+ check_result(result, "isc_buffer_cloneused");
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
+ if (include_question) {
+ tmpbuf = NULL;
+ result = isc_buffer_cloneused(mctx, &query->sendbuf, &tmpbuf);
+ check_result(result, "isc_buffer_cloneused");
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
+ }
ISC_LINK_INIT(&query->lengthbuf, link);
ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
--
1.8.3.1