From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-vk1-xa2a.google.com (mail-vk1-xa2a.google.com [IPv6:2607:f8b0:4864:20::a2a]) by sourceware.org (Postfix) with ESMTPS id EA77C3858C78 for ; Thu, 3 Feb 2022 20:52:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EA77C3858C78 Received: by mail-vk1-xa2a.google.com with SMTP id o15so2537844vki.2 for ; Thu, 03 Feb 2022 12:52:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:from:to:references:in-reply-to :content-transfer-encoding; bh=E7KdD0mc1v/N46LUhima/Reg5DITHGG0fKs4N6k44k0=; b=eB+IMcsWZ1Ta4GHWnwd56ZHXLlCRfWixA52sqpN18b8Z6MwTf6WTVmU41hOsZEZOAZ i2KkRu0uD5aOcxklx2tFy92Y7F/RIkGviY+LqOqsw+T5oRPqM10yBHdwiA3eyeHAWNYp 1wnLUy+SzOABoty55rQiNnPFT/+AVj4OUG17ryHBRjSLQkHngbjisH6sjebft7nrrbcr 47W9OyU0ey39c9HXt6qINfBce38UKDILVrJucRBQu/xzbnynJlaTLTcU6+Wfjgr3Qyaz Hb5JZJRTdwKHJ7NoKjPbUqz1yR26UuRtnpF5idwsh3+ei74OTNeFazloTvWhcrf3tiux boAw== X-Gm-Message-State: AOAM531nYRRnSzwnL6zyjqc+v1NZIRzz10WgT2RujYzo/mzmNXqpc0PB ytYt/Wmce2NPgMeR97HsikOmylIzSROJJg== X-Google-Smtp-Source: ABdhPJxsKmWalfJUZJz1eaTeWkoDH8bdoDO1th1+ZyRyegdGpSwWFiOSd0hploca4QQJnWo4yaxKcA== X-Received: by 2002:a05:6122:984:: with SMTP id g4mr14636375vkd.11.1643921574241; Thu, 03 Feb 2022 12:52:54 -0800 (PST) Received: from ?IPV6:2804:431:c7ca:709a:22aa:9542:591f:6eb9? ([2804:431:c7ca:709a:22aa:9542:591f:6eb9]) by smtp.gmail.com with ESMTPSA id e1sm5602945vsh.19.2022.02.03.12.52.53 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 03 Feb 2022 12:52:53 -0800 (PST) Message-ID: <0d6fcc40-d647-2574-6da9-cc3b75f7632c@linaro.org> Date: Thu, 3 Feb 2022 17:52:52 -0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.1 Subject: Re: [PATCH v2 1/3] inet: Fix getnameinfo (NI_NOFQDN) race condition (BZ#28566) Content-Language: en-US From: Adhemerval Zanella To: libc-alpha@sourceware.org References: <20211210110733.1499984-1-adhemerval.zanella@linaro.org> <20211210110733.1499984-2-adhemerval.zanella@linaro.org> In-Reply-To: <20211210110733.1499984-2-adhemerval.zanella@linaro.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Feb 2022 20:52:57 -0000 Ping. On 10/12/2021 08:07, Adhemerval Zanella wrote: > The 'not_first' is accessed on nrl_domainname() in a non atomically > way, although it is only updated after the lock is taken. > > This patch fix the double-checked locking by using acquire-release > atomic operation instead of plain load and by moving the 'not_first' > store only after 'domain' is actually set. > > Checked on x86_64-linux-gnu. > --- > inet/getnameinfo.c | 148 ++++++++++++++++++++++++--------------------- > 1 file changed, 78 insertions(+), 70 deletions(-) > > diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c > index 8380d85783..5eee354200 100644 > --- a/inet/getnameinfo.c > +++ b/inet/getnameinfo.c > @@ -83,104 +83,112 @@ libc_freeres_ptr (static char *domain); > now ignored. */ > #define DEPRECATED_NI_IDN 192 > > -static char * > -nrl_domainname (void) > +static void > +nrl_domainname_core (struct scratch_buffer *tmpbuf) > { > - static int not_first; > + char *c; > + struct hostent *h, th; > + int herror; > > - if (! not_first) > + while (__gethostbyname_r ("localhost", &th, > + tmpbuf->data, tmpbuf->length, > + &h, &herror)) > { > - __libc_lock_define_initialized (static, lock); > - __libc_lock_lock (lock); > - > - if (! not_first) > + if (herror == NETDB_INTERNAL && errno == ERANGE) > { > - char *c; > - struct hostent *h, th; > - int herror; > - struct scratch_buffer tmpbuf; > - > - scratch_buffer_init (&tmpbuf); > - not_first = 1; > + if (!scratch_buffer_grow (tmpbuf)) > + return; > + } > + else > + break; > + } > > - while (__gethostbyname_r ("localhost", &th, > - tmpbuf.data, tmpbuf.length, > + if (h != NULL && (c = strchr (h->h_name, '.')) != NULL) > + domain = __strdup (++c); > + else > + { > + /* The name contains no domain information. Use the name > + now to get more information. */ > + while (__gethostname (tmpbuf->data, tmpbuf->length)) > + if (!scratch_buffer_grow (tmpbuf)) > + return; > + > + if ((c = strchr (tmpbuf->data, '.')) != NULL) > + domain = __strdup (++c); > + else > + { > + /* We need to preserve the hostname. */ > + const char *hstname = strdupa (tmpbuf->data); > + while (__gethostbyname_r (hstname, &th, > + tmpbuf->data, > + tmpbuf->length, > &h, &herror)) > { > if (herror == NETDB_INTERNAL && errno == ERANGE) > { > - if (!scratch_buffer_grow (&tmpbuf)) > - goto done; > + if (!scratch_buffer_grow (tmpbuf)) > + return; > } > else > break; > } > > - if (h && (c = strchr (h->h_name, '.'))) > + if (h != NULL && (c = strchr(h->h_name, '.')) != NULL) > domain = __strdup (++c); > else > { > - /* The name contains no domain information. Use the name > - now to get more information. */ > - while (__gethostname (tmpbuf.data, tmpbuf.length)) > - if (!scratch_buffer_grow (&tmpbuf)) > - goto done; > + struct in_addr in_addr; > > - if ((c = strchr (tmpbuf.data, '.'))) > - domain = __strdup (++c); > - else > - { > - /* We need to preserve the hostname. */ > - const char *hstname = strdupa (tmpbuf.data); > + in_addr.s_addr = htonl (INADDR_LOOPBACK); > > - while (__gethostbyname_r (hstname, &th, > - tmpbuf.data, tmpbuf.length, > - &h, &herror)) > + while (__gethostbyaddr_r ((const char *) &in_addr, > + sizeof (struct in_addr), > + AF_INET, &th, > + tmpbuf->data, > + tmpbuf->length, > + &h, &herror)) > + { > + if (herror == NETDB_INTERNAL && errno == ERANGE) > { > - if (herror == NETDB_INTERNAL && errno == ERANGE) > - { > - if (!scratch_buffer_grow (&tmpbuf)) > - goto done; > - } > - else > - break; > + if (!scratch_buffer_grow (tmpbuf)) > + return; > } > - > - if (h && (c = strchr(h->h_name, '.'))) > - domain = __strdup (++c); > else > - { > - struct in_addr in_addr; > - > - in_addr.s_addr = htonl (INADDR_LOOPBACK); > - > - while (__gethostbyaddr_r ((const char *) &in_addr, > - sizeof (struct in_addr), > - AF_INET, &th, > - tmpbuf.data, tmpbuf.length, > - &h, &herror)) > - { > - if (herror == NETDB_INTERNAL && errno == ERANGE) > - { > - if (!scratch_buffer_grow (&tmpbuf)) > - goto done; > - } > - else > - break; > - } > - > - if (h && (c = strchr (h->h_name, '.'))) > - domain = __strdup (++c); > - } > + break; > } > + > + if (h != NULL && (c = strchr (h->h_name, '.')) != NULL) > + domain = __strdup (++c); > } > - done: > - scratch_buffer_free (&tmpbuf); > } > + } > +} > > - __libc_lock_unlock (lock); > +static char * > +nrl_domainname (void) > +{ > + static int not_first; > + > + if (__glibc_likely (atomic_load_acquire (¬_first) != 0)) > + return domain; > + > + __libc_lock_define_initialized (static, lock); > + __libc_lock_lock (lock); > + > + if (atomic_load_relaxed (¬_first) == 0) > + { > + struct scratch_buffer tmpbuf; > + scratch_buffer_init (&tmpbuf); > + > + nrl_domainname_core (&tmpbuf); > + > + scratch_buffer_free (&tmpbuf); > + > + atomic_store_release (¬_first, 1); > } > > + __libc_lock_unlock (lock); > + > return domain; > }; >