public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/siddhesh/gai-cleanup2] inet: Fix getnameinfo (NI_NOFQDN) race condition (BZ#28566)
@ 2022-03-14 14:15 Siddhesh Poyarekar
0 siblings, 0 replies; only message in thread
From: Siddhesh Poyarekar @ 2022-03-14 14:15 UTC (permalink / raw)
To: glibc-cvs
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c54d689269c7f10e7f7d28b1cb5b3a6a0dd5a889
commit c54d689269c7f10e7f7d28b1cb5b3a6a0dd5a889
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Nov 10 14:40:30 2021 -0300
inet: Fix getnameinfo (NI_NOFQDN) race condition (BZ#28566)
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.
Reviewed-by: DJ Delorie <dj@redhat.com>
Diff:
---
inet/getnameinfo.c | 148 ++++++++++++++++++++++++++++-------------------------
1 file changed, 78 insertions(+), 70 deletions(-)
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index e7031d3741..5965912c9e 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;
};
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-03-14 14:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-14 14:15 [glibc/siddhesh/gai-cleanup2] inet: Fix getnameinfo (NI_NOFQDN) race condition (BZ#28566) Siddhesh Poyarekar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).