From patchwork Tue Jul 4 11:57:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 783914 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3x22Z46fQBz9s82 for ; Tue, 4 Jul 2017 21:57:48 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="sbq6LCg+"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:from:cc:message-id:date :mime-version:in-reply-to:content-type; q=dns; s=default; b=cKft wSsNqqaUKZX7oQ7VwDsEPTnT0M7TMg4x7wjOXv3QhhfTYz3cBQSsGrkweC++BFZT AwZEk4b8mYOuc3rc1iVK+dy7s50xO9X6nN+hOj5ApHW1nlLkLznOPQviMPmxwweY JillqtOHR/54osZumcpAV5m8C7obeACnu4qkgEY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:from:cc:message-id:date :mime-version:in-reply-to:content-type; s=default; bh=G2AA05boPH 1VV3hao3UjqqsUjg8=; b=sbq6LCg+o8D+t2Bh/0Li2m/Ial/RSM3fdUvKPDQ+Vm /nU67cQrc/vaC9kv0hXuxsKSLetp4TNg4wT4EjqKZP49KyI0SUR5pS34NHqAMcW2 9cdLCkVlwI4FjPcCM1gzUlP981dc8Jwuca9+YCb3ft5606kbGN5TkchZzphpeFMu U= Received: (qmail 58031 invoked by alias); 4 Jul 2017 11:57:42 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 52087 invoked by uid 89); 4 Jul 2017 11:57:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=2599 X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B2FA1267C4 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com B2FA1267C4 Subject: Re: [PATCH] resolv: Mirror the entire resolver configuration in struct resolv_conf To: Andreas Schwab References: <20170630193802.80D6C439942F0@oldenburg.str.redhat.com> <5bb0919b-0dfe-df45-5033-ca610fee52d6@redhat.com> <2392bdc6-f77a-33ee-3953-b80b9aec2af7@redhat.com> <53d9a512-86e1-ee3c-f425-4446a0df167d@redhat.com> <97c300e6-26ce-8ed7-9d89-14baf4eb0466@redhat.com> From: Florian Weimer Cc: GNU C Library Message-ID: <40d78bcf-4ef7-9a75-4093-30c271cf49ad@redhat.com> Date: Tue, 4 Jul 2017 13:57:30 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: On 07/04/2017 01:40 PM, Andreas Schwab wrote: > On Jul 04 2017, Florian Weimer wrote: > >> On 07/04/2017 12:14 PM, Andreas Schwab wrote: >>> On Jul 04 2017, Florian Weimer wrote: >>> >>>> I meant a link to something like the SRPM or the source repository from >>>> which the SRPM is built. >>> >>> Yes, that's exactly linked from the top (Overview etc.). >> >> If I do that, I end up at >> >> http://software.opensuse.org//download.html?project=home%3AAndreas_Schwab%3Aglibc&package=glibc >> >> which offers only glibc-2.22-118.1.src.rpm as the newest version. > > Since the build failed no srpm was created, and publishing is disabled > anyway. If you have an OBS account you can check out the sources via > command line. Okay, in this case, please try the attached patch to get more logging. It's on to of commit 89f6307c5d270ed4f11cee373031fa9f2222f2b9. (It adds two missing conformance checks as well, but they go in the wrong direction for this; i.e. they would cause only additional asserts.) With the patch, I get output like this on mismatch: Fatal glibc error: resolv.conf mismatch after loading resolv_conf options: 0x000002c1 resolv_conf nameserver 0: [10.16.36.29]:53 resolv_conf nameserver 1: [10.11.5.19]:53 resolv_conf nameserver 2: [10.5.30.160]:53 resolv_conf search list 0: khw.lab.eng.bos.redhat.com resolv_conf search list 1: redhat.com resolv_conf search list 2: str.redhat.com resolv_conf search list 3: corp.redhat.com resolv_conf search list 4: engineering.redhat.com resolv_conf search list 5: debian.org resolv_conf search list 6: enyo.de _res options: 0x000002c1 _res nscount: 2 _res nameserver 0: [10.16.36.29]:53 _res nameserver 1: [10.11.5.19]:53 _res _ext nscount: 0 _res default domain: khw.lab.eng.bos.redhat.com _res search list 0: khw.lab.eng.bos.redhat.com _res search list 1: redhat.com _res search list 2: str.redhat.com _res search list 3: corp.redhat.com _res search list 4: engineering.redhat.com _res search list 5: debian.org _res nsort: 0 mismatch detected at nscount Thanks, Florian From 51c852cb13f9cbca3803b05372bc5a5f4b12bebb Mon Sep 17 00:00:00 2001 Message-Id: <51c852cb13f9cbca3803b05372bc5a5f4b12bebb.1499169412.git.fweimer@redhat.com> From: Florian Weimer Date: Tue, 4 Jul 2017 13:56:33 +0200 Subject: [PATCH] resolv: Add logging to resolv_conf processing To: libc-alpha@sourceware.org --- resolv/resolv_conf.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 178 insertions(+), 14 deletions(-) diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c index 0ed36cd..375c072 100644 --- a/resolv/resolv_conf.c +++ b/resolv/resolv_conf.c @@ -19,9 +19,11 @@ #include #include +#include #include #include #include +#include #include /* _res._u._ext.__glibc_extension_index is used as an index into a @@ -257,9 +259,9 @@ same_address (const struct sockaddr *left, const struct sockaddr *right) } /* Check that *RESP and CONF match. Used by __resolv_conf_get. */ -static bool +static __attribute__ ((noinline, noclone)) bool resolv_conf_matches (const struct __res_state *resp, - const struct resolv_conf *conf) + const struct resolv_conf *conf, FILE *fp) { /* NB: Do not compare the options, retrans, retry, ndots. These can be changed by applicaiton. */ @@ -272,23 +274,46 @@ resolv_conf_matches (const struct __res_state *resp, nserv = MAXNS; /* _ext.nscount is 0 until initialized by res_send.c. */ if (resp->nscount != nserv - && (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv)) - return false; + || (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv)) + { + if (fp != NULL) + fputs ("mismatch detected at nscount\n", fp); + return false; + } for (size_t i = 0; i < nserv; ++i) { if (resp->nsaddr_list[i].sin_family == 0) { if (resp->_u._ext.nsaddrs[i]->sin6_family != AF_INET6) - return false; + { + if (fp != NULL) + fprintf + (fp, "extended address family at %zu is not AF_INET6\n", + i); + return false; + } if (!same_address ((struct sockaddr *) resp->_u._ext.nsaddrs[i], conf->nameserver_list[i])) - return false; + { + if (fp != NULL) + fprintf (fp, "extended address %zu does not match\n", i); + return false; + } } else if (resp->nsaddr_list[i].sin_family != AF_INET) - return false; + { + if (fp != NULL) + fprintf + (fp, "basic address family at %zu is not AF_INET\n", i); + return false; + } else if (!same_address ((struct sockaddr *) &resp->nsaddr_list[i], conf->nameserver_list[i])) - return false; + { + if (fp != NULL) + fprintf (fp, "basic address %zu does not match\n", i); + return false; + } } } @@ -297,7 +322,11 @@ resolv_conf_matches (const struct __res_state *resp, { if (!(resp->dnsrch[0] == resp->defdname && resp->dnsrch[MAXDNSRCH] == NULL)) - return false; + { + if (fp != NULL) + fputs ("mismatch detected at dnsrch\n", fp); + return false; + } size_t search_list_size = 0; for (size_t i = 0; i < conf->search_list_size; ++i) { @@ -305,7 +334,11 @@ resolv_conf_matches (const struct __res_state *resp, { search_list_size += strlen (resp->dnsrch[i]) + 1; if (strcmp (resp->dnsrch[i], conf->search_list[i]) != 0) - return false; + { + if (fp != NULL) + fprintf (fp, "mismatch at search entry %zu\n", i); + return false; + } } else { @@ -316,6 +349,8 @@ resolv_conf_matches (const struct __res_state *resp, if (i == MAXDNSRCH || search_list_size > sizeof (resp->dnsrch)) break; /* Otherwise, a mismatch indicates a match failure. */ + if (fp != NULL) + fprintf (fp, "mismatch at search entry %zu (truncation)\n", i); return false; } } @@ -326,10 +361,20 @@ resolv_conf_matches (const struct __res_state *resp, size_t nsort = conf->sort_list_size; if (nsort > MAXRESOLVSORT) nsort = MAXRESOLVSORT; + if (resp->nsort != nsort) + { + if (fp != NULL) + fputs ("mismatch detected at nsort\n", fp); + return false; + } for (size_t i = 0; i < nsort; ++i) if (resp->sort_list[i].addr.s_addr != conf->sort_list[i].addr.s_addr || resp->sort_list[i].mask != conf->sort_list[i].mask) - return false; + { + if (fp != NULL) + fprintf (fp, "mismatch at sort list entry %zu\n", i); + return false; + } } return true; @@ -341,7 +386,7 @@ __resolv_conf_get (struct __res_state *resp) struct resolv_conf *conf = resolv_conf_get_1 (resp); if (conf == NULL) return NULL; - if (resolv_conf_matches (resp, conf)) + if (resolv_conf_matches (resp, conf, NULL)) return conf; __resolv_conf_put (conf); return NULL; @@ -462,8 +507,116 @@ __resolv_conf_allocate (const struct resolv_conf *init) return conf; } +static void +format_sockaddr (const void *ptr, FILE *fp) +{ + const struct sockaddr *sa = ptr; + char addr[50]; + uint16_t port; + switch (sa->sa_family) + { + case AF_INET: + { + const struct sockaddr_in *sin = ptr; + if (inet_ntop (AF_INET, &sin->sin_addr, addr, sizeof (addr)) == NULL) + { + fputs ("", fp); + return; + } + port = sin->sin_port; + break; + } + case AF_INET6: + { + const struct sockaddr_in6 *sin6 = ptr; + if (inet_ntop (AF_INET6, &sin6->sin6_addr, addr, sizeof (addr)) == NULL) + { + fputs ("", fp); + return; + } + port = sin6->sin6_port; + break; + } + default: + fprintf (fp, "", sa->sa_family); + return; + } + fprintf (fp, "[%s]:%u", addr, ntohs (port)); +} + +static void +format_ipv4 (uint32_t addr, FILE *fp) +{ + char buf[50]; + if (inet_ntop (AF_INET, &addr, buf, sizeof (buf)) == NULL) + fputs ("", fp); + else + fputs (buf, fp); +} + +static void +print_conf (const struct resolv_conf *conf, FILE *fp) +{ + fprintf (fp, "resolv_conf options: 0x%08x\n", conf->options); + for (size_t i = 0; i < conf->nameserver_list_size; ++i) + { + fprintf (fp, "resolv_conf nameserver %zu: ", i); + format_sockaddr (conf->nameserver_list[i], fp); + _IO_putc ('\n', fp); + } + for (size_t i = 0; i < conf->search_list_size; ++i) + fprintf (fp, "resolv_conf search list %zu: %s\n", i, conf->search_list[i]); + for (size_t i = 0; i < conf->sort_list_size; ++i) + { + fprintf (fp, "resolv_conf sortlist %zu: ", i); + format_ipv4 (conf->sort_list[i].addr.s_addr, fp); + _IO_putc ('/', fp); + format_ipv4 (conf->sort_list[i].mask, fp); + _IO_putc ('\n', fp); + } +} + +static void +print_resp (const struct __res_state *resp, FILE *fp) +{ + fprintf (fp, "_res options: 0x%08lx\n", resp->options); + fprintf (fp, "_res nscount: %d\n", resp->nscount); + for (size_t i = 0; i < resp->nscount; ++i) + { + fprintf (fp, "_res nameserver %zu: ", i); + format_sockaddr (&resp->nsaddr_list[i], fp); + _IO_putc ('\n', fp); + } + fprintf (fp, "_res _ext nscount: %d\n", resp->_u._ext.nscount); + for (size_t i = 0; i < resp->_u._ext.nscount; ++i) + { + fprintf (fp, "_res _ext nameserver %zu: ", i); + if (resp->_u._ext.nsaddrs[i] == NULL) + fputs ("(null)", fp); + else + format_sockaddr (resp->_u._ext.nsaddrs[i], fp); + _IO_putc ('\n', fp); + } + fprintf (fp, "_res default domain: %s\n", resp->defdname); + for (size_t i = 0; i < MAXDNSRCH; ++i) + if (resp->dnsrch[i] == NULL) + break; + else + fprintf (fp, "_res search list %zu: %s\n", i, resp->dnsrch[i]); + fprintf (fp, "_res nsort: %d\n", resp->nsort); + for (size_t i = 0; i < resp->nsort; ++i) + { + fprintf (fp, "_res sortlist %zu: ", i); + format_ipv4 (resp->sort_list[i].addr.s_addr, fp); + _IO_putc ('/', fp); + format_ipv4 (resp->sort_list[i].mask, fp); + _IO_putc ('\n', fp); + } +} + /* Update *RESP from the extended state. */ -static __attribute__ ((nonnull (1, 2), warn_unused_result)) bool +static __attribute__ ((nonnull (1, 2), warn_unused_result, + noinline, noclone)) bool update_from_conf (struct __res_state *resp, const struct resolv_conf *conf) { resp->defdname[0] = '\0'; @@ -549,7 +702,18 @@ update_from_conf (struct __res_state *resp, const struct resolv_conf *conf) /* The overlapping parts of both configurations should agree after initialization. */ - assert (resolv_conf_matches (resp, conf)); + if (!resolv_conf_matches (resp, conf, NULL)) + { + char *buffer = NULL; + size_t buffer_length = 0; + FILE *fp = __open_memstream (&buffer, &buffer_length); + fputs ("Fatal glibc error: resolv.conf mismatch after loading\n", fp); + print_conf (conf, fp); + print_resp (resp, fp); + resolv_conf_matches (resp, conf, fp); + fclose (fp); + __libc_fatal (buffer); + } return true; } -- 2.9.4