diff --git a/glibc-RHEL-16643-1.patch b/glibc-RHEL-16643-1.patch new file mode 100644 index 0000000..d8d33c3 --- /dev/null +++ b/glibc-RHEL-16643-1.patch @@ -0,0 +1,211 @@ +commit 06890c7ba553e82393413c59bb3131db5815a337 +Author: Siddhesh Poyarekar +Date: Tue Jul 27 22:49:53 2021 +0530 + + gaiconf_init: Refactor some bits for readability + + Split out line processing for `label`, `precedence` and `scopev4` into + separate functions instead of the gotos. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: DJ Delorie + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index d6046a707f1d742a..3bf9a8bae16a5b02 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -1858,6 +1858,66 @@ scopecmp (const void *p1, const void *p2) + return 1; + } + ++static bool ++add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp, ++ char *val1, char *val2, char **pos) ++{ ++ struct in6_addr prefix; ++ unsigned long int bits; ++ unsigned long int val; ++ char *endp; ++ ++ bits = 128; ++ __set_errno (0); ++ char *cp = strchr (val1, '/'); ++ if (cp != NULL) ++ *cp++ = '\0'; ++ *pos = cp; ++ if (inet_pton (AF_INET6, val1, &prefix) ++ && (cp == NULL ++ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && bits <= 128 ++ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && val <= INT_MAX) ++ { ++ struct prefixlist *newp = malloc (sizeof (*newp)); ++ if (newp == NULL) ++ return false; ++ ++ memcpy (&newp->entry.prefix, &prefix, sizeof (prefix)); ++ newp->entry.bits = bits; ++ newp->entry.val = val; ++ newp->next = *listp; ++ *listp = newp; ++ ++*lenp; ++ *nullbitsp |= bits == 0; ++ } ++ return true; ++} ++ ++static bool ++add_scopelist (struct scopelist **listp, size_t *lenp, bool *nullbitsp, ++ const struct in6_addr *prefixp, unsigned long int bits, ++ unsigned long int val) ++{ ++ struct scopelist *newp = malloc (sizeof (*newp)); ++ if (newp == NULL) ++ return false; ++ ++ newp->entry.netmask = htonl (bits != 96 ? (0xffffffff << (128 - bits)) : 0); ++ newp->entry.addr32 = (prefixp->s6_addr32[3] & newp->entry.netmask); ++ newp->entry.scope = val; ++ newp->next = *listp; ++ *listp = newp; ++ ++*lenp; ++ *nullbitsp |= bits == 96; ++ ++ return true; ++} + + static void + gaiconf_init (void) +@@ -1933,55 +1993,17 @@ gaiconf_init (void) + /* Ignore the rest of the line. */ + *cp = '\0'; + +- struct prefixlist **listp; +- size_t *lenp; +- bool *nullbitsp; + switch (cmdlen) + { + case 5: + if (strcmp (cmd, "label") == 0) + { +- struct in6_addr prefix; +- unsigned long int bits; +- unsigned long int val; +- char *endp; +- +- listp = &labellist; +- lenp = &nlabellist; +- nullbitsp = &labellist_nullbits; +- +- new_elem: +- bits = 128; +- __set_errno (0); +- cp = strchr (val1, '/'); +- if (cp != NULL) +- *cp++ = '\0'; +- if (inet_pton (AF_INET6, val1, &prefix) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && bits <= 128 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && val <= INT_MAX) ++ if (!add_prefixlist (&labellist, &nlabellist, ++ &labellist_nullbits, val1, val2, &cp)) + { +- struct prefixlist *newp = malloc (sizeof (*newp)); +- if (newp == NULL) +- { +- free (line); +- fclose (fp); +- goto no_file; +- } +- +- memcpy (&newp->entry.prefix, &prefix, sizeof (prefix)); +- newp->entry.bits = bits; +- newp->entry.val = val; +- newp->next = *listp; +- *listp = newp; +- ++*lenp; +- *nullbitsp |= bits == 0; ++ free (line); ++ fclose (fp); ++ goto no_file; + } + } + break; +@@ -2023,27 +2045,14 @@ gaiconf_init (void) + && *endp == '\0' + && val <= INT_MAX) + { +- struct scopelist *newp; +- new_scope: +- newp = malloc (sizeof (*newp)); +- if (newp == NULL) ++ if (!add_scopelist (&scopelist, &nscopelist, ++ &scopelist_nullbits, &prefix, ++ bits, val)) + { + free (line); + fclose (fp); + goto no_file; + } +- +- newp->entry.netmask = htonl (bits != 96 +- ? (0xffffffff +- << (128 - bits)) +- : 0); +- newp->entry.addr32 = (prefix.s6_addr32[3] +- & newp->entry.netmask); +- newp->entry.scope = val; +- newp->next = scopelist; +- scopelist = newp; +- ++nscopelist; +- scopelist_nullbits |= bits == 96; + } + } + else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3]) +@@ -2057,8 +2066,14 @@ gaiconf_init (void) + && *endp == '\0' + && val <= INT_MAX) + { +- bits += 96; +- goto new_scope; ++ if (!add_scopelist (&scopelist, &nscopelist, ++ &scopelist_nullbits, &prefix, ++ bits + 96, val)) ++ { ++ free (line); ++ fclose (fp); ++ goto no_file; ++ } + } + } + break; +@@ -2066,10 +2081,14 @@ gaiconf_init (void) + case 10: + if (strcmp (cmd, "precedence") == 0) + { +- listp = &precedencelist; +- lenp = &nprecedencelist; +- nullbitsp = &precedencelist_nullbits; +- goto new_elem; ++ if (!add_prefixlist (&precedencelist, &nprecedencelist, ++ &precedencelist_nullbits, val1, val2, ++ &cp)) ++ { ++ free (line); ++ fclose (fp); ++ goto no_file; ++ } + } + break; + } diff --git a/glibc-RHEL-16643-2.patch b/glibc-RHEL-16643-2.patch new file mode 100644 index 0000000..ed0a98c --- /dev/null +++ b/glibc-RHEL-16643-2.patch @@ -0,0 +1,584 @@ +commit bc0d18d873abf2cda6842ad8bb4df2a31dc0fbac +Author: Siddhesh Poyarekar +Date: Tue Aug 3 21:29:23 2021 +0530 + + gai_init: Avoid jumping from if condition to its else counterpart + + Clean up another antipattern where code flows from an if condition to + its else counterpart with a goto. + + Most of the change in this patch is whitespace-only; a `git diff -b` + ought to show the actual logic changes. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: DJ Delorie + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 3bf9a8bae16a5b02..1635a09837351068 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -1933,142 +1933,122 @@ gaiconf_init (void) + bool scopelist_nullbits = false; + + FILE *fp = fopen (GAICONF_FNAME, "rce"); +- if (fp != NULL) ++ if (fp == NULL) ++ goto no_file; ++ ++ struct __stat64_t64 st; ++ if (__fstat64_time64 (fileno (fp), &st) != 0) + { +- struct __stat64_t64 st; +- if (__fstat64_time64 (fileno (fp), &st) != 0) +- { +- fclose (fp); +- goto no_file; +- } ++ fclose (fp); ++ goto no_file; ++ } + +- char *line = NULL; +- size_t linelen = 0; ++ char *line = NULL; ++ size_t linelen = 0; + +- __fsetlocking (fp, FSETLOCKING_BYCALLER); ++ __fsetlocking (fp, FSETLOCKING_BYCALLER); + +- while (!feof_unlocked (fp)) +- { +- ssize_t n = __getline (&line, &linelen, fp); +- if (n <= 0) +- break; ++ while (!feof_unlocked (fp)) ++ { ++ ssize_t n = __getline (&line, &linelen, fp); ++ if (n <= 0) ++ break; + +- /* Handle comments. No escaping possible so this is easy. */ +- char *cp = strchr (line, '#'); +- if (cp != NULL) +- *cp = '\0'; ++ /* Handle comments. No escaping possible so this is easy. */ ++ char *cp = strchr (line, '#'); ++ if (cp != NULL) ++ *cp = '\0'; + +- cp = line; +- while (isspace (*cp)) +- ++cp; ++ cp = line; ++ while (isspace (*cp)) ++ ++cp; + +- char *cmd = cp; +- while (*cp != '\0' && !isspace (*cp)) +- ++cp; +- size_t cmdlen = cp - cmd; ++ char *cmd = cp; ++ while (*cp != '\0' && !isspace (*cp)) ++ ++cp; ++ size_t cmdlen = cp - cmd; + +- if (*cp != '\0') +- *cp++ = '\0'; +- while (isspace (*cp)) +- ++cp; ++ if (*cp != '\0') ++ *cp++ = '\0'; ++ while (isspace (*cp)) ++ ++cp; + +- char *val1 = cp; +- while (*cp != '\0' && !isspace (*cp)) +- ++cp; +- size_t val1len = cp - cmd; ++ char *val1 = cp; ++ while (*cp != '\0' && !isspace (*cp)) ++ ++cp; ++ size_t val1len = cp - cmd; + +- /* We always need at least two values. */ +- if (val1len == 0) +- continue; ++ /* We always need at least two values. */ ++ if (val1len == 0) ++ continue; + +- if (*cp != '\0') +- *cp++ = '\0'; +- while (isspace (*cp)) +- ++cp; ++ if (*cp != '\0') ++ *cp++ = '\0'; ++ while (isspace (*cp)) ++ ++cp; + +- char *val2 = cp; +- while (*cp != '\0' && !isspace (*cp)) +- ++cp; ++ char *val2 = cp; ++ while (*cp != '\0' && !isspace (*cp)) ++ ++cp; + +- /* Ignore the rest of the line. */ +- *cp = '\0'; ++ /* Ignore the rest of the line. */ ++ *cp = '\0'; + +- switch (cmdlen) ++ switch (cmdlen) ++ { ++ case 5: ++ if (strcmp (cmd, "label") == 0) + { +- case 5: +- if (strcmp (cmd, "label") == 0) ++ if (!add_prefixlist (&labellist, &nlabellist, ++ &labellist_nullbits, val1, val2, &cp)) + { +- if (!add_prefixlist (&labellist, &nlabellist, +- &labellist_nullbits, val1, val2, &cp)) +- { +- free (line); +- fclose (fp); +- goto no_file; +- } ++ free (line); ++ fclose (fp); ++ goto no_file; + } +- break; ++ } ++ break; + +- case 6: +- if (strcmp (cmd, "reload") == 0) +- { +- gaiconf_reload_flag = strcmp (val1, "yes") == 0; +- if (gaiconf_reload_flag) +- gaiconf_reload_flag_ever_set = 1; +- } +- break; ++ case 6: ++ if (strcmp (cmd, "reload") == 0) ++ { ++ gaiconf_reload_flag = strcmp (val1, "yes") == 0; ++ if (gaiconf_reload_flag) ++ gaiconf_reload_flag_ever_set = 1; ++ } ++ break; + +- case 7: +- if (strcmp (cmd, "scopev4") == 0) ++ case 7: ++ if (strcmp (cmd, "scopev4") == 0) ++ { ++ struct in6_addr prefix; ++ unsigned long int bits; ++ unsigned long int val; ++ char *endp; ++ ++ bits = 32; ++ __set_errno (0); ++ cp = strchr (val1, '/'); ++ if (cp != NULL) ++ *cp++ = '\0'; ++ if (inet_pton (AF_INET6, val1, &prefix)) + { +- struct in6_addr prefix; +- unsigned long int bits; +- unsigned long int val; +- char *endp; +- +- bits = 32; +- __set_errno (0); +- cp = strchr (val1, '/'); +- if (cp != NULL) +- *cp++ = '\0'; +- if (inet_pton (AF_INET6, val1, &prefix)) +- { +- bits = 128; +- if (IN6_IS_ADDR_V4MAPPED (&prefix) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && bits >= 96 +- && bits <= 128 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && val <= INT_MAX) +- { +- if (!add_scopelist (&scopelist, &nscopelist, +- &scopelist_nullbits, &prefix, +- bits, val)) +- { +- free (line); +- fclose (fp); +- goto no_file; +- } +- } +- } +- else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3]) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && bits <= 32 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' +- && val <= INT_MAX) ++ bits = 128; ++ if (IN6_IS_ADDR_V4MAPPED (&prefix) ++ && (cp == NULL ++ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && bits >= 96 ++ && bits <= 128 ++ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && val <= INT_MAX) + { + if (!add_scopelist (&scopelist, &nscopelist, + &scopelist_nullbits, &prefix, +- bits + 96, val)) ++ bits, val)) + { + free (line); + fclose (fp); +@@ -2076,173 +2056,191 @@ gaiconf_init (void) + } + } + } +- break; +- +- case 10: +- if (strcmp (cmd, "precedence") == 0) ++ else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3]) ++ && (cp == NULL ++ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && bits <= 32 ++ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX ++ || errno != ERANGE) ++ && *endp == '\0' ++ && val <= INT_MAX) + { +- if (!add_prefixlist (&precedencelist, &nprecedencelist, +- &precedencelist_nullbits, val1, val2, +- &cp)) ++ if (!add_scopelist (&scopelist, &nscopelist, ++ &scopelist_nullbits, &prefix, ++ bits + 96, val)) + { + free (line); + fclose (fp); + goto no_file; + } + } +- break; +- } +- } +- +- free (line); +- +- fclose (fp); +- +- /* Create the array for the labels. */ +- struct prefixentry *new_labels; +- if (nlabellist > 0) +- { +- if (!labellist_nullbits) +- ++nlabellist; +- new_labels = malloc (nlabellist * sizeof (*new_labels)); +- if (new_labels == NULL) +- goto no_file; +- +- int i = nlabellist; +- if (!labellist_nullbits) +- { +- --i; +- memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr)); +- new_labels[i].bits = 0; +- new_labels[i].val = 1; + } ++ break; + +- struct prefixlist *l = labellist; +- while (i-- > 0) ++ case 10: ++ if (strcmp (cmd, "precedence") == 0) + { +- new_labels[i] = l->entry; +- l = l->next; ++ if (!add_prefixlist (&precedencelist, &nprecedencelist, ++ &precedencelist_nullbits, val1, val2, ++ &cp)) ++ { ++ free (line); ++ fclose (fp); ++ goto no_file; ++ } + } +- free_prefixlist (labellist); +- labellist = NULL; +- +- /* Sort the entries so that the most specific ones are at +- the beginning. */ +- qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp); ++ break; + } +- else +- new_labels = (struct prefixentry *) default_labels; +- +- struct prefixentry *new_precedence; +- if (nprecedencelist > 0) +- { +- if (!precedencelist_nullbits) +- ++nprecedencelist; +- new_precedence = malloc (nprecedencelist * sizeof (*new_precedence)); +- if (new_precedence == NULL) +- { +- if (new_labels != default_labels) +- free (new_labels); +- goto no_file; +- } ++ } + +- int i = nprecedencelist; +- if (!precedencelist_nullbits) +- { +- --i; +- memset (&new_precedence[i].prefix, '\0', +- sizeof (struct in6_addr)); +- new_precedence[i].bits = 0; +- new_precedence[i].val = 40; +- } ++ free (line); + +- struct prefixlist *l = precedencelist; +- while (i-- > 0) +- { +- new_precedence[i] = l->entry; +- l = l->next; +- } +- free_prefixlist (precedencelist); +- precedencelist = NULL; ++ fclose (fp); + +- /* Sort the entries so that the most specific ones are at +- the beginning. */ +- qsort (new_precedence, nprecedencelist, sizeof (*new_precedence), +- prefixcmp); ++ /* Create the array for the labels. */ ++ struct prefixentry *new_labels; ++ if (nlabellist > 0) ++ { ++ if (!labellist_nullbits) ++ ++nlabellist; ++ new_labels = malloc (nlabellist * sizeof (*new_labels)); ++ if (new_labels == NULL) ++ goto no_file; ++ ++ int i = nlabellist; ++ if (!labellist_nullbits) ++ { ++ --i; ++ memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr)); ++ new_labels[i].bits = 0; ++ new_labels[i].val = 1; + } +- else +- new_precedence = (struct prefixentry *) default_precedence; + +- struct scopeentry *new_scopes; +- if (nscopelist > 0) ++ struct prefixlist *l = labellist; ++ while (i-- > 0) + { +- if (!scopelist_nullbits) +- ++nscopelist; +- new_scopes = malloc (nscopelist * sizeof (*new_scopes)); +- if (new_scopes == NULL) +- { +- if (new_labels != default_labels) +- free (new_labels); +- if (new_precedence != default_precedence) +- free (new_precedence); +- goto no_file; +- } +- +- int i = nscopelist; +- if (!scopelist_nullbits) +- { +- --i; +- new_scopes[i].addr32 = 0; +- new_scopes[i].netmask = 0; +- new_scopes[i].scope = 14; +- } ++ new_labels[i] = l->entry; ++ l = l->next; ++ } ++ free_prefixlist (labellist); ++ labellist = NULL; + +- struct scopelist *l = scopelist; +- while (i-- > 0) +- { +- new_scopes[i] = l->entry; +- l = l->next; +- } +- free_scopelist (scopelist); ++ /* Sort the entries so that the most specific ones are at ++ the beginning. */ ++ qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp); ++ } ++ else ++ new_labels = (struct prefixentry *) default_labels; + +- /* Sort the entries so that the most specific ones are at +- the beginning. */ +- qsort (new_scopes, nscopelist, sizeof (*new_scopes), +- scopecmp); ++ struct prefixentry *new_precedence; ++ if (nprecedencelist > 0) ++ { ++ if (!precedencelist_nullbits) ++ ++nprecedencelist; ++ new_precedence = malloc (nprecedencelist * sizeof (*new_precedence)); ++ if (new_precedence == NULL) ++ { ++ if (new_labels != default_labels) ++ free (new_labels); ++ goto no_file; + } +- else +- new_scopes = (struct scopeentry *) default_scopes; +- +- /* Now we are ready to replace the values. */ +- const struct prefixentry *old = labels; +- labels = new_labels; +- if (old != default_labels) +- free ((void *) old); + +- old = precedence; +- precedence = new_precedence; +- if (old != default_precedence) +- free ((void *) old); ++ int i = nprecedencelist; ++ if (!precedencelist_nullbits) ++ { ++ --i; ++ memset (&new_precedence[i].prefix, '\0', ++ sizeof (struct in6_addr)); ++ new_precedence[i].bits = 0; ++ new_precedence[i].val = 40; ++ } + +- const struct scopeentry *oldscope = scopes; +- scopes = new_scopes; +- if (oldscope != default_scopes) +- free ((void *) oldscope); ++ struct prefixlist *l = precedencelist; ++ while (i-- > 0) ++ { ++ new_precedence[i] = l->entry; ++ l = l->next; ++ } ++ free_prefixlist (precedencelist); ++ precedencelist = NULL; + +- save_gaiconf_mtime (&st); ++ /* Sort the entries so that the most specific ones are at ++ the beginning. */ ++ qsort (new_precedence, nprecedencelist, sizeof (*new_precedence), ++ prefixcmp); + } + else ++ new_precedence = (struct prefixentry *) default_precedence; ++ ++ struct scopeentry *new_scopes; ++ if (nscopelist > 0) + { +- no_file: +- free_prefixlist (labellist); +- free_prefixlist (precedencelist); ++ if (!scopelist_nullbits) ++ ++nscopelist; ++ new_scopes = malloc (nscopelist * sizeof (*new_scopes)); ++ if (new_scopes == NULL) ++ { ++ if (new_labels != default_labels) ++ free (new_labels); ++ if (new_precedence != default_precedence) ++ free (new_precedence); ++ goto no_file; ++ } ++ ++ int i = nscopelist; ++ if (!scopelist_nullbits) ++ { ++ --i; ++ new_scopes[i].addr32 = 0; ++ new_scopes[i].netmask = 0; ++ new_scopes[i].scope = 14; ++ } ++ ++ struct scopelist *l = scopelist; ++ while (i-- > 0) ++ { ++ new_scopes[i] = l->entry; ++ l = l->next; ++ } + free_scopelist (scopelist); + +- /* If we previously read the file but it is gone now, free the +- old data and use the builtin one. Leave the reload flag +- alone. */ +- fini (); ++ /* Sort the entries so that the most specific ones are at ++ the beginning. */ ++ qsort (new_scopes, nscopelist, sizeof (*new_scopes), ++ scopecmp); + } ++ else ++ new_scopes = (struct scopeentry *) default_scopes; ++ ++ /* Now we are ready to replace the values. */ ++ const struct prefixentry *old = labels; ++ labels = new_labels; ++ if (old != default_labels) ++ free ((void *) old); ++ ++ old = precedence; ++ precedence = new_precedence; ++ if (old != default_precedence) ++ free ((void *) old); ++ ++ const struct scopeentry *oldscope = scopes; ++ scopes = new_scopes; ++ if (oldscope != default_scopes) ++ free ((void *) oldscope); ++ ++ save_gaiconf_mtime (&st); ++ return; ++ ++no_file: ++ free_prefixlist (labellist); ++ free_prefixlist (precedencelist); ++ free_scopelist (scopelist); ++ ++ /* If we previously read the file but it is gone now, free the old data and ++ use the builtin one. Leave the reload flag alone. */ ++ fini (); + } + + diff --git a/glibc-RHEL-16643-3.patch b/glibc-RHEL-16643-3.patch new file mode 100644 index 0000000..c9f092a --- /dev/null +++ b/glibc-RHEL-16643-3.patch @@ -0,0 +1,90 @@ +commit d3f2c2c8b57bdf9d963db8fa2372d6c1b86a337e +Author: Siddhesh Poyarekar +Date: Tue Mar 22 22:40:05 2022 +0530 + + getaddrinfo: Refactor code for readability + + The close_retry goto jump is confusing and clumsy to read, so refactor + the code a bit to make it easier to follow. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: DJ Delorie + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 1635a09837351068..5e9bd17eb949974c 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -2253,6 +2253,36 @@ gaiconf_reload (void) + gaiconf_init (); + } + ++static bool ++try_connect (int *fdp, int *afp, struct sockaddr_in6 *source_addrp, ++ const struct sockaddr *addr, socklen_t addrlen, int family) ++{ ++ int fd = *fdp; ++ int af = *afp; ++ socklen_t sl = sizeof (*source_addrp); ++ ++ while (true) ++ { ++ if (fd != -1 && __connect (fd, addr, addrlen) == 0 ++ && __getsockname (fd, (struct sockaddr *) source_addrp, &sl) == 0) ++ return true; ++ ++ if (errno == EAFNOSUPPORT && af == AF_INET6 && family == AF_INET) ++ { ++ /* This could mean IPv6 sockets are IPv6-only. */ ++ if (fd != -1) ++ __close_nocancel_nostatus (fd); ++ *afp = af = AF_INET; ++ *fdp = fd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, ++ IPPROTO_IP); ++ continue; ++ } ++ ++ return false; ++ } ++ ++ __builtin_unreachable (); ++} + + int + getaddrinfo (const char *name, const char *service, +@@ -2443,7 +2473,6 @@ getaddrinfo (const char *name, const char *service, + if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6)) + { + if (fd != -1) +- close_retry: + __close_nocancel_nostatus (fd); + af = q->ai_family; + fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP); +@@ -2455,14 +2484,10 @@ getaddrinfo (const char *name, const char *service, + __connect (fd, &sa, sizeof (sa)); + } + +- socklen_t sl = sizeof (results[i].source_addr); +- if (fd != -1 +- && __connect (fd, q->ai_addr, q->ai_addrlen) == 0 +- && __getsockname (fd, +- (struct sockaddr *) &results[i].source_addr, +- &sl) == 0) ++ if (try_connect (&fd, &af, &results[i].source_addr, q->ai_addr, ++ q->ai_addrlen, q->ai_family)) + { +- results[i].source_addr_len = sl; ++ results[i].source_addr_len = sizeof (results[i].source_addr); + results[i].got_source_addr = true; + + if (in6ai != NULL) +@@ -2527,10 +2552,6 @@ getaddrinfo (const char *name, const char *service, + results[i].source_addr_len = sizeof (struct sockaddr_in); + } + } +- else if (errno == EAFNOSUPPORT && af == AF_INET6 +- && q->ai_family == AF_INET) +- /* This could mean IPv6 sockets are IPv6-only. */ +- goto close_retry; + else + /* Just make sure that if we have to process the same + address again we do not copy any memory. */ diff --git a/glibc-RHEL-16643-4.patch b/glibc-RHEL-16643-4.patch new file mode 100644 index 0000000..53429e7 --- /dev/null +++ b/glibc-RHEL-16643-4.patch @@ -0,0 +1,32 @@ +commit c9226c03da0276593a0918eaa9a14835183343e8 +Author: Jörg Sonnenberger +Date: Mon Sep 26 13:59:16 2022 -0400 + + get_nscd_addresses: Fix subscript typos [BZ #29605] + + Fix the subscript on air->family, which was accidentally set to COUNT + when it should have remained as I. + + Resolves: BZ #29605 + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 5e9bd17eb949974c..40a32a3de30cb294 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -549,11 +549,11 @@ get_nscd_addresses (const char *name, const struct addrinfo *req, + at[count].addr[2] = htonl (0xffff); + } + else if (req->ai_family == AF_UNSPEC +- || air->family[count] == req->ai_family) ++ || air->family[i] == req->ai_family) + { +- at[count].family = air->family[count]; ++ at[count].family = air->family[i]; + memcpy (at[count].addr, addrs, size); +- if (air->family[count] == AF_INET6) ++ if (air->family[i] == AF_INET6) + res->got_ipv6 = true; + } + at[count].next = at + count + 1; diff --git a/glibc-RHEL-16643-5.patch b/glibc-RHEL-16643-5.patch new file mode 100644 index 0000000..8b16670 --- /dev/null +++ b/glibc-RHEL-16643-5.patch @@ -0,0 +1,25 @@ +commit 3bf7bab88b0da01d4f5ef20afbbb45203185501e +Author: Siddhesh Poyarekar +Date: Tue Sep 5 17:04:05 2023 -0400 + + getcanonname: Fix a typo + + This code is generally unused in practice since there don't seem to be + any NSS modules that only implement _nss_MOD_gethostbyname2_r and not + _nss_MOD_gethostbyname3_r. + + Signed-off-by: Siddhesh Poyarekar + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 40a32a3de30cb294..e9f47aea358a3351 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -346,7 +346,7 @@ getcanonname (nss_action_list nip, const char *hname, const char *name) + string. */ + s = (char *) name; + } +- return __strdup (name); ++ return __strdup (s); + } + + /* Process looked up canonical name and if necessary, decode to IDNA. Result diff --git a/glibc-RHEL-16643-6.patch b/glibc-RHEL-16643-6.patch new file mode 100644 index 0000000..dd72b79 --- /dev/null +++ b/glibc-RHEL-16643-6.patch @@ -0,0 +1,23 @@ +commit 61bac1a9d2ab80ebcbc51484722e6ea43414bec7 +Author: Florian Weimer +Date: Wed Dec 20 16:14:33 2023 +0100 + + nss: Remove unused allocation from get_nscd_addresses in getaddrinfo + + No bug because this is not visible if glibc is built with + optimization. Otherwise this would be a critical resource leak. + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index e9f47aea358a3351..321a6679d46494a3 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -514,7 +514,6 @@ get_nscd_addresses (const char *name, const struct addrinfo *req, + int result = 0; + char *addrs = air->addrs; + +- struct gaih_addrtuple *addrfree = calloc (air->naddrs, sizeof (*addrfree)); + struct gaih_addrtuple *at = calloc (air->naddrs, sizeof (*at)); + if (at == NULL) + { diff --git a/glibc.spec b/glibc.spec index 083d8e5..64c4a9f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -155,7 +155,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 97%{?dist} +Release: 98%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -800,6 +800,12 @@ Patch563: glibc-RHEL-17319-4.patch Patch564: glibc-RHEL-17465-1.patch Patch565: glibc-RHEL-17465-2.patch Patch566: glibc-RHEL-19862.patch +Patch567: glibc-RHEL-16643-1.patch +Patch568: glibc-RHEL-16643-2.patch +Patch569: glibc-RHEL-16643-3.patch +Patch570: glibc-RHEL-16643-4.patch +Patch571: glibc-RHEL-16643-5.patch +Patch572: glibc-RHEL-16643-6.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2958,6 +2964,9 @@ update_gconv_modules_cache () %endif %changelog +* Mon Jan 8 2024 Arjun Shankar - 2.34-98 +- getaddrinfo: Fix occasionally empty result due to nscd cache order (RHEL-16643) + * Tue Jan 2 2024 Florian Weimer - 2.34-97 - Re-enable output buffering for wide stdio streams (RHEL-19862)