From c44c77178e0bf420483b0dd0af43839bf636a6cc Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 29 Jun 2015 19:44:42 +0530 Subject: [PATCH] Fix race in getaddrinfo() in libirs, which caused assertion failure in delv (#39873) --- CHANGES | 6 ++++++ lib/irs/getaddrinfo.c | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0ab5a34137..d94615460e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +4149. [bug] Fixed a race condition in the getaddrinfo() + implementation in libirs, which caused the delv + utility to crash with an assertion failure when using + the '@server' syntax with a hostname argument. + [RT #39899] + 4148. [bug] Fix a bug when printing zone names with '/' character in XML and JSON statistics output. [RT #39873] diff --git a/lib/irs/getaddrinfo.c b/lib/irs/getaddrinfo.c index cda7b18bff..093af0739b 100644 --- a/lib/irs/getaddrinfo.c +++ b/lib/irs/getaddrinfo.c @@ -138,6 +138,7 @@ #include #include #include +#include #include #include @@ -531,6 +532,7 @@ typedef struct gai_statehead { int ai_port; isc_appctx_t *actx; dns_client_t *dnsclient; + isc_mutex_t list_lock; ISC_LIST(struct gai_resstate) resstates; unsigned int activestates; } gai_statehead_t; @@ -858,6 +860,7 @@ process_answer(isc_task_t *task, isc_event_t *event) { * and have any answer, we can stop now by canceling the * others. */ + LOCK(&resstate->head->list_lock); if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) { if ((resstate->trans4 != NULL && resstate->trans4->ai_sentinel.ai_next != NULL) || @@ -889,6 +892,7 @@ process_answer(isc_task_t *task, isc_event_t *event) { resstate, link); } } + UNLOCK(&resstate->head->list_lock); } } @@ -929,11 +933,19 @@ resolve_name(int family, const char *hostname, int flags, head.ai_port = port; head.actx = actx; head.dnsclient = client; + result = isc_mutex_init(&head.list_lock); + if (result != ISC_R_SUCCESS) { + return (EAI_FAIL); + } + ISC_LIST_INIT(head.resstates); result = make_resstates(mctx, hostname, &head, conf); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&head.list_lock); return (EAI_FAIL); + } + LOCK(&head.list_lock); for (resstate = ISC_LIST_HEAD(head.resstates); resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) { if (resstate->trans4 != NULL) { @@ -967,6 +979,8 @@ resolve_name(int family, const char *hostname, int flags, resstate->trans6->is_inprogress= ISC_FALSE; } } + UNLOCK(&head.list_lock); + if (!all_fail) { /* Start all the events */ isc_app_ctxrun(actx); @@ -1038,6 +1052,7 @@ resolve_name(int family, const char *hostname, int flags, irs_context_destroy(&irsctx); #endif + DESTROYLOCK(&head.list_lock); return (error); }