mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 14:20:07 +00:00
Fix incorrect double-checked locking related to _res_hconf.initialized.
_res_hconf.initialized was not suitable for use in a multi-threaded environment due to the lack of atomics and memory barriers. Use of it was also unnecessary because _res_hconf_init did the right thing by using __libc_once. This patch fixes the glibc-internal uses by just calling _res_hconf_init unconditionally, and switches to a release MO atomic store for _res_hconf.initialized to fix the glibc side of the synchronization problem (which will maintain backward compatibility, but cannot fix the lack of acquire MO on any glibc-external loads). [BZ #20477] * resolv/res_hconf.c (do_init): Use atomic access. * resolv/res_hconf.h: Add comments. * nscd/aicache.c (addhstaiX): Call _res_hconf_init unconditionally. * nss/getXXbyYY_r.c (REENTRANT_NAME): Likewise. * sysdeps/posix/getaddrinfo.c (gaih_inet): Likewise.
This commit is contained in:
parent
b65f0b7b2e
commit
6f9d4f595e
@ -1,3 +1,12 @@
|
||||
2016-08-18 Torvald Riegel <triegel@redhat.com>
|
||||
|
||||
[BZ #20477]
|
||||
* resolv/res_hconf.c (do_init): Use atomic access.
|
||||
* resolv/res_hconf.h: Add comments.
|
||||
* nscd/aicache.c (addhstaiX): Call _res_hconf_init unconditionally.
|
||||
* nss/getXXbyYY_r.c (REENTRANT_NAME): Likewise.
|
||||
* sysdeps/posix/getaddrinfo.c (gaih_inet): Likewise.
|
||||
|
||||
2016-08-18 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/ieee754/dbl-64/k_rem_pio2.c (__kernel_rem_pio2):
|
||||
|
@ -101,7 +101,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
nip = hosts_database;
|
||||
|
||||
/* Initialize configurations. */
|
||||
if (__glibc_unlikely (!_res_hconf.initialized))
|
||||
_res_hconf_init ();
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
no_more = 1;
|
||||
|
@ -274,7 +274,6 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
}
|
||||
#endif /* need _res */
|
||||
#ifdef NEED__RES_HCONF
|
||||
if (!_res_hconf.initialized)
|
||||
_res_hconf_init ();
|
||||
#endif /* need _res_hconf */
|
||||
|
||||
|
@ -348,7 +348,8 @@ do_init (void)
|
||||
arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval);
|
||||
}
|
||||
|
||||
_res_hconf.initialized = 1;
|
||||
/* See comments on the declaration of _res_hconf. */
|
||||
atomic_store_release (&_res_hconf.initialized, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,6 +25,15 @@
|
||||
|
||||
struct hconf
|
||||
{
|
||||
/* We keep the INITIALIZED member only for backwards compatibility. New
|
||||
code should just call _res_hconf_init unconditionally. For this field
|
||||
to be used safely, users must ensure that either (1) a call to
|
||||
_res_hconf_init happens-before any load from INITIALIZED, or (2) an
|
||||
assignment of zero to INITIALIZED happens-before any load from it, and
|
||||
these loads use acquire MO if the intent is to skip calling
|
||||
_res_hconf_init if the load returns a nonzero value. Such acquire MO
|
||||
loads will then synchronize with the release MO store to INITIALIZED
|
||||
in do_init in res_hconf.c; see pthread_once for more detail. */
|
||||
int initialized;
|
||||
int unused1;
|
||||
int unused2[4];
|
||||
|
@ -816,7 +816,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
nip = __nss_hosts_database;
|
||||
|
||||
/* Initialize configurations. */
|
||||
if (__glibc_unlikely (!_res_hconf.initialized))
|
||||
_res_hconf_init ();
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
no_more = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user