diff --git a/bind.spec b/bind.spec index cf76487..865b3c7 100644 --- a/bind.spec +++ b/bind.spec @@ -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 32:9.9.4-4 +- Use upstream version of patch for previously fixed #794940 + * Fri Oct 18 2013 Tomas Hozza 32:9.9.4-3 - Fix race condition on send buffers in dighost.c (#794940) diff --git a/bind99-ISC-Bugs-34870-v2.patch b/bind99-ISC-Bugs-34870-v2.patch new file mode 100644 index 0000000..1e861bc --- /dev/null +++ b/bind99-ISC-Bugs-34870-v2.patch @@ -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 diff --git a/bind99-ISC-Bugs-34870.patch b/bind99-ISC-Bugs-34870.patch deleted file mode 100644 index 158794a..0000000 --- a/bind99-ISC-Bugs-34870.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 527e971a732d645d411df842ec4f8c401248ca0c Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -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 ---- - 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 -