[PATCH 1/3] inet: Fix getnameinfo (NI_NOFQDN) race condition (BZ#28566)
Adhemerval Zanella
adhemerval.zanella@linaro.org
Wed Nov 10 18:58:30 GMT 2021
The 'not_first' is accessed on nrl_domainname() in a non atomically
way, although it is only updated after the lock is taken.
Instead of being too clever, just always take the lock (another
option might to use an atomic load and only take the lock if lock
might be taken, but I think it would be better to have this optimization
on generic lll_lock instead of ad-hoc solution).
Checked on x86_64-linux-gnu.
---
inet/getnameinfo.c | 120 ++++++++++++++++++++++-----------------------
1 file changed, 59 insertions(+), 61 deletions(-)
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index 8380d85783..58ebbb1154 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -86,55 +86,75 @@ libc_freeres_ptr (static char *domain);
static char *
nrl_domainname (void)
{
- static int not_first;
+ __libc_lock_define_initialized (static, lock);
+ __libc_lock_lock (lock);
+ static bool not_first = false;
if (! not_first)
{
- __libc_lock_define_initialized (static, lock);
- __libc_lock_lock (lock);
-
- if (! not_first)
- {
- char *c;
- struct hostent *h, th;
- int herror;
- struct scratch_buffer tmpbuf;
+ char *c;
+ struct hostent *h, th;
+ int herror;
+ struct scratch_buffer tmpbuf;
- scratch_buffer_init (&tmpbuf);
- not_first = 1;
+ scratch_buffer_init (&tmpbuf);
- while (__gethostbyname_r ("localhost", &th,
- tmpbuf.data, tmpbuf.length,
- &h, &herror))
+ while (__gethostbyname_r ("localhost", &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))
+ goto done;
}
+ else
+ break;
+ }
- if (h && (c = strchr (h->h_name, '.')))
+ if (h && (c = strchr (h->h_name, '.')))
+ 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;
+
+ if ((c = strchr (tmpbuf.data, '.')))
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;
+ /* 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_preserve (&tmpbuf))
+ goto done;
+ }
+ else
+ break;
+ }
- if ((c = strchr (tmpbuf.data, '.')))
+ if (h && (c = strchr(h->h_name, '.')))
domain = __strdup (++c);
else
{
- /* We need to preserve the hostname. */
- const char *hstname = strdupa (tmpbuf.data);
+ struct in_addr in_addr;
+
+ in_addr.s_addr = htonl (INADDR_LOOPBACK);
- while (__gethostbyname_r (hstname, &th,
- tmpbuf.data, tmpbuf.length,
+ 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)
@@ -146,41 +166,19 @@ nrl_domainname (void)
break;
}
- if (h && (c = strchr(h->h_name, '.')))
+ 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);
- }
}
}
- done:
- scratch_buffer_free (&tmpbuf);
}
- __libc_lock_unlock (lock);
+ done:
+ scratch_buffer_free (&tmpbuf);
+ not_first = true;
}
+ __libc_lock_unlock (lock);
+
return domain;
};
--
2.32.0
More information about the Libc-alpha
mailing list