Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
glibc
gai-merge-continue-actions.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gai-merge-continue-actions.patch of Package glibc
From be9a9dca822ffd256aa9847292fe60f94a4b4ede Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar <siddhesh@sourceware.org> Date: Thu, 17 Mar 2022 11:44:34 +0530 Subject: [PATCH] Simplify allocations and fix merge and continue actions [BZ #28931] Allocations for address tuples is currently a bit confusing because of the pointer chasing through PAT, making it hard to observe the sequence in which allocations have been made. Narrow scope of the pointer chasing through PAT so that it is only used where necessary. This also tightens actions behaviour with the hosts database in getaddrinfo to comply with the manual text. The "continue" action discards previous results and the "merge" action results in an immedate lookup failure. Consequently, chaining of allocations across modules is no longer necessary, thus opening up cleanup opportunities. A test has been added that checks some combinations to ensure that they work correctly. Resolves: BZ #28931 Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> Reviewed-by: DJ Delorie <dj@redhat.com> (cherry picked from commit 1c37b8022e8763fedbb3f79c02e05c6acfe5a215) --- sysdeps/posix/getaddrinfo.c | 140 ++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 2c4b6d6793..266b73d874 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -473,11 +473,6 @@ gaih_inet (const char *name, const struct gaih_service *service, if (name != NULL) { - at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); - at->family = AF_UNSPEC; - at->scopeid = 0; - at->next = NULL; - #ifdef HAVE_LIBIDN if (req->ai_flags & AI_IDN) { @@ -508,13 +503,21 @@ gaih_inet (const char *name, const struct gaih_service *service, } #endif - if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) + uint32_t addr[4]; + if (__inet_aton_exact (name, (struct in_addr *) addr) != 0) { + at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); + at->scopeid = 0; + at->next = NULL; + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) - at->family = AF_INET; + { + memcpy (at->addr, addr, sizeof (at->addr)); + at->family = AF_INET; + } else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED)) { - at->addr[3] = at->addr[0]; + at->addr[3] = addr[0]; at->addr[2] = htonl (0xffff); at->addr[1] = 0; at->addr[0] = 0; @@ -528,49 +531,59 @@ gaih_inet (const char *name, const struct gaih_service *service, if (req->ai_flags & AI_CANONNAME) canon = name; + + goto process_list; } - else if (at->family == AF_UNSPEC) + + char *scope_delim = strchr (name, SCOPE_DELIMITER); + int e; + + if (scope_delim == NULL) + e = inet_pton (AF_INET6, name, addr); + else + e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr); + + if (e > 0) { - char *scope_delim = strchr (name, SCOPE_DELIMITER); - int e; - if (scope_delim == NULL) - e = inet_pton (AF_INET6, name, at->addr); + at = alloca_account (sizeof (struct gaih_addrtuple), + alloca_used); + at->scopeid = 0; + at->next = NULL; + + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + { + memcpy (at->addr, addr, sizeof (at->addr)); + at->family = AF_INET6; + } + else if (req->ai_family == AF_INET + && IN6_IS_ADDR_V4MAPPED (addr)) + { + at->addr[0] = addr[3]; + at->family = AF_INET; + } else - e = __inet_pton_length (AF_INET6, name, scope_delim - name, - at->addr); - if (e > 0) { - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) - at->family = AF_INET6; - else if (req->ai_family == AF_INET - && IN6_IS_ADDR_V4MAPPED (at->addr)) - { - at->addr[0] = at->addr[3]; - at->family = AF_INET; - } - else - { - result = -EAI_ADDRFAMILY; - goto free_and_return; - } - - if (scope_delim != NULL - && __inet6_scopeid_pton ((struct in6_addr *) at->addr, - scope_delim + 1, - &at->scopeid) != 0) - { - result = -EAI_NONAME; - goto free_and_return; - } + result = -EAI_ADDRFAMILY; + goto free_and_return; + } - if (req->ai_flags & AI_CANONNAME) - canon = name; + if (scope_delim != NULL + && __inet6_scopeid_pton ((struct in6_addr *) at->addr, + scope_delim + 1, + &at->scopeid) != 0) + { + result = -EAI_NONAME; + goto free_and_return; } + + if (req->ai_flags & AI_CANONNAME) + canon = name; + + goto process_list; } - if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) + if ((req->ai_flags & AI_NUMERICHOST) == 0) { - struct gaih_addrtuple **pat = &at; int no_data = 0; int no_inet6_data = 0; service_user *nip; @@ -579,6 +592,7 @@ gaih_inet (const char *name, const struct gaih_service *service, int no_more; struct resolv_context *res_ctx = NULL; bool res_enable_inet6 = false; + bool do_merge = false; /* If we do not have to look for IPv6 addresses or the canonical name, use the simple, old functions, which do not support @@ -615,7 +629,7 @@ gaih_inet (const char *name, const struct gaih_service *service, result = -EAI_MEMORY; goto free_and_return; } - *pat = addrmem; + at = addrmem; } else { @@ -668,6 +682,8 @@ gaih_inet (const char *name, const struct gaih_service *service, } struct gaih_addrtuple *addrfree = addrmem; + struct gaih_addrtuple **pat = &at; + for (int i = 0; i < air->naddrs; ++i) { socklen_t size = (air->family[i] == AF_INET @@ -731,12 +747,6 @@ gaih_inet (const char *name, const struct gaih_service *service, free (air); - if (at->family == AF_UNSPEC) - { - result = -EAI_NONAME; - goto free_and_return; - } - goto process_list; } else if (err == 0) @@ -775,6 +785,22 @@ gaih_inet (const char *name, const struct gaih_service *service, while (!no_more) { + /* Always start afresh; continue should discard previous results + and the hosts database does not support merge. */ + at = NULL; + free (canonbuf); + free (addrmem); + canon = canonbuf = NULL; + addrmem = NULL; + got_ipv6 = false; + + if (do_merge) + { + __set_h_errno (NETDB_INTERNAL); + __set_errno (EBUSY); + break; + } + no_data = 0; nss_gethostbyname4_r fct4 = NULL; @@ -787,12 +813,14 @@ gaih_inet (const char *name, const struct gaih_service *service, { while (1) { - status = DL_CALL_FCT (fct4, (name, pat, + status = DL_CALL_FCT (fct4, (name, &at, tmpbuf->data, tmpbuf->length, &errno, &h_errno, NULL)); if (status == NSS_STATUS_SUCCESS) break; + /* gethostbyname4_r may write into AT, so reset it. */ + at = NULL; if (status != NSS_STATUS_TRYAGAIN || errno != ERANGE || h_errno != NETDB_INTERNAL) { @@ -819,7 +847,9 @@ gaih_inet (const char *name, const struct gaih_service *service, no_data = 1; if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) - canon = (*pat)->name; + canon = at->name; + + struct gaih_addrtuple **pat = &at; while (*pat != NULL) { @@ -871,6 +901,8 @@ gaih_inet (const char *name, const struct gaih_service *service, if (fct != NULL) { + struct gaih_addrtuple **pat = &at; + if (req->ai_family == AF_INET6 || req->ai_family == AF_UNSPEC) { @@ -946,6 +978,10 @@ gaih_inet (const char *name, const struct gaih_service *service, if (nss_next_action (nip, status) == NSS_ACTION_RETURN) break; + /* The hosts database does not support MERGE. */ + if (nss_next_action (nip, status) == NSS_ACTION_MERGE) + do_merge = true; + if (nip->next == NULL) no_more = -1; else @@ -979,7 +1015,7 @@ gaih_inet (const char *name, const struct gaih_service *service, } process_list: - if (at->family == AF_UNSPEC) + if (at == NULL) { result = -EAI_NONAME; goto free_and_return; -- 2.42.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor