diff --git a/SOURCES/glibc-RHEL-21007-1.patch b/SOURCES/glibc-RHEL-21007-1.patch new file mode 100644 index 0000000..d8d33c3 --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21007-2.patch b/SOURCES/glibc-RHEL-21007-2.patch new file mode 100644 index 0000000..ed0a98c --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21007-3.patch b/SOURCES/glibc-RHEL-21007-3.patch new file mode 100644 index 0000000..c9f092a --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21007-4.patch b/SOURCES/glibc-RHEL-21007-4.patch new file mode 100644 index 0000000..53429e7 --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21007-5.patch b/SOURCES/glibc-RHEL-21007-5.patch new file mode 100644 index 0000000..8b16670 --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21007-6.patch b/SOURCES/glibc-RHEL-21007-6.patch new file mode 100644 index 0000000..dd72b79 --- /dev/null +++ b/SOURCES/glibc-RHEL-21007-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/SOURCES/glibc-RHEL-21240.patch b/SOURCES/glibc-RHEL-21240.patch new file mode 100644 index 0000000..2c03560 --- /dev/null +++ b/SOURCES/glibc-RHEL-21240.patch @@ -0,0 +1,29 @@ +commit 5eabdb6a6ac1599d23dd5966a37417215950245f +Author: Andreas Schwab +Date: Wed Dec 6 14:48:22 2023 +0100 + + getaddrinfo: translate ENOMEM to EAI_MEMORY (bug 31163) + + When __resolv_context_get returns NULL due to out of memory, translate it + to a return value of EAI_MEMORY. + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 321a6679d46494a3..8fe879c5420337a4 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -615,7 +615,14 @@ get_nss_addresses (const char *name, const struct addrinfo *req, + function variant. */ + res_ctx = __resolv_context_get (); + if (res_ctx == NULL) +- no_more = 1; ++ { ++ if (errno == ENOMEM) ++ { ++ result = -EAI_MEMORY; ++ goto out; ++ } ++ no_more = 1; ++ } + + while (!no_more) + { diff --git a/SOURCES/glibc-RHEL-21518.patch b/SOURCES/glibc-RHEL-21518.patch new file mode 100644 index 0000000..b6a39b9 --- /dev/null +++ b/SOURCES/glibc-RHEL-21518.patch @@ -0,0 +1,112 @@ +commit 849274d48fc59bfa6db3c713c8ced8026b20f3b7 +Author: Florian Weimer +Date: Thu Nov 16 19:55:35 2023 +0100 + + elf: Fix force_first handling in dlclose (bug 30981) + + The force_first parameter was ineffective because the dlclose'd + object was not necessarily the first in the maps array. Also + enable force_first handling unconditionally, regardless of namespace. + The initial object in a namespace should be destructed first, too. + + The _dl_sort_maps_dfs function had early returns for relocation + dependency processing which broke force_first handling, too, and + this is fixed in this change as well. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 985cd4e2821436af..1aedd89bc48d4827 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -182,6 +182,16 @@ _dl_close_worker (struct link_map *map, bool force) + } + assert (idx == nloaded); + ++ /* Put the dlclose'd map first, so that its destructor runs first. ++ The map variable is NULL after a retry. */ ++ if (map != NULL) ++ { ++ maps[map->l_idx] = maps[0]; ++ maps[map->l_idx]->l_idx = map->l_idx; ++ maps[0] = map; ++ maps[0]->l_idx = 0; ++ } ++ + /* Keep track of the lowest index link map we have covered already. */ + int done_index = -1; + while (++done_index < nloaded) +@@ -255,9 +265,10 @@ _dl_close_worker (struct link_map *map, bool force) + } + } + +- /* Sort the entries. We can skip looking for the binary itself which is +- at the front of the search list for the main namespace. */ +- _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true); ++ /* Sort the entries. Unless retrying, the maps[0] object (the ++ original argument to dlclose) needs to remain first, so that its ++ destructor runs first. */ ++ _dl_sort_maps (maps, nloaded, /* force_first */ map != NULL, true); + + /* Call all termination functions at once. */ + bool unload_any = false; +@@ -768,7 +779,11 @@ _dl_close_worker (struct link_map *map, bool force) + /* Recheck if we need to retry, release the lock. */ + out: + if (dl_close_state == rerun) +- goto retry; ++ { ++ /* The map may have been deallocated. */ ++ map = NULL; ++ goto retry; ++ } + + dl_close_state = not_pending; + } +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index e8ef5e8b3588ab53..937feb6e7008bc62 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -260,13 +260,12 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, + The below memcpy is not needed in the do_reldeps case here, + since we wrote back to maps[] during DFS traversal. */ + if (maps_head == maps) +- return; ++ break; + } + assert (maps_head == maps); +- return; + } +- +- memcpy (maps, rpo, sizeof (struct link_map *) * nmaps); ++ else ++ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps); + + /* Skipping the first object at maps[0] is not valid in general, + since traversing along object dependency-links may "find" that +diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def +index 4bf9052db16fb352..cf6453e9eb85ac65 100644 +--- a/elf/dso-sort-tests-1.def ++++ b/elf/dso-sort-tests-1.def +@@ -56,14 +56,16 @@ output: b>a>{}b->c->d order). +-# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based +-# dynamic_sort=2 algorithm does, although it is still arguable whether going +-# beyond spec to do this is the right thing to do. ++# The older dynamic_sort=1 algorithm originally did not achieve this, ++# but this was a bug in the way _dl_sort_maps was called from _dl_close_worker, ++# effectively disabling proper force_first handling. ++# The new dynamic_sort=2 algorithm shows the effect of the simpler force_first ++# handling: the a object is simply moved to the front. + # The below expected outputs are what the two algorithms currently produce + # respectively, for regression testing purposes. + tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c +-output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[ +Date: Mon Nov 27 11:28:07 2023 +0100 + + elf: In _dl_relocate_object, skip processing if object is relocated + + This is just a minor optimization. It also makes it more obvious that + _dl_relocate_object can be called multiple times. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index 5b69321bda1f2b27..bbc5c15170a0856b 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -192,6 +192,9 @@ void + _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + int reloc_mode, int consider_profiling) + { ++ if (l->l_relocated) ++ return; ++ + struct textrels + { + caddr_t start; +@@ -229,9 +232,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + # define consider_symbind 0 + #endif + +- if (l->l_relocated) +- return; +- + /* If DT_BIND_NOW is set relocate all references in this object. We + do not do this if we are profiling, of course. */ + // XXX Correct for auditing? diff --git a/SOURCES/glibc-RHEL-21521-2.patch b/SOURCES/glibc-RHEL-21521-2.patch new file mode 100644 index 0000000..dc221ce --- /dev/null +++ b/SOURCES/glibc-RHEL-21521-2.patch @@ -0,0 +1,121 @@ +commit a74c2e1cbc8673dd7e97aae2f2705392e2ccc3f6 +Author: Florian Weimer +Date: Mon Nov 27 11:28:10 2023 +0100 + + elf: Introduce the _dl_open_relocate_one_object function + + It is extracted from dl_open_worker_begin. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 633b047ad2497296..bc4d38d6a6b1b5a0 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -467,6 +467,50 @@ activate_nodelete (struct link_map *new) + } + } + ++/* Relocate the object L. *RELOCATION_IN_PROGRESS controls whether ++ the debugger is notified of the start of relocation processing. */ ++static void ++_dl_open_relocate_one_object (struct dl_open_args *args, struct r_debug *r, ++ struct link_map *l, int reloc_mode, ++ bool *relocation_in_progress) ++{ ++ if (l->l_real->l_relocated) ++ return; ++ ++ if (!*relocation_in_progress) ++ { ++ /* Notify the debugger that relocations are about to happen. */ ++ LIBC_PROBE (reloc_start, 2, args->nsid, r); ++ *relocation_in_progress = true; ++ } ++ ++#ifdef SHARED ++ if (__glibc_unlikely (GLRO(dl_profile) != NULL)) ++ { ++ /* If this here is the shared object which we want to profile ++ make sure the profile is started. We can find out whether ++ this is necessary or not by observing the `_dl_profile_map' ++ variable. If it was NULL but is not NULL afterwards we must ++ start the profiling. */ ++ struct link_map *old_profile_map = GL(dl_profile_map); ++ ++ _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); ++ ++ if (old_profile_map == NULL && GL(dl_profile_map) != NULL) ++ { ++ /* We must prepare the profiling. */ ++ _dl_start_profile (); ++ ++ /* Prevent unloading the object. */ ++ GL(dl_profile_map)->l_nodelete_active = true; ++ } ++ } ++ else ++#endif ++ _dl_relocate_object (l, l->l_scope, reloc_mode, 0); ++} ++ ++ + /* struct dl_init_args and call_dl_init are used to call _dl_init with + exception handling disabled. */ + struct dl_init_args +@@ -651,7 +695,7 @@ dl_open_worker_begin (void *a) + } + while (l != NULL); + +- int relocation_in_progress = 0; ++ bool relocation_in_progress = false; + + /* Perform relocation. This can trigger lazy binding in IFUNC + resolvers. For NODELETE mappings, these dependencies are not +@@ -662,44 +706,8 @@ dl_open_worker_begin (void *a) + are undefined anyway, so this is not a problem. */ + + for (unsigned int i = last; i-- > first; ) +- { +- l = new->l_initfini[i]; +- +- if (l->l_real->l_relocated) +- continue; +- +- if (! relocation_in_progress) +- { +- /* Notify the debugger that relocations are about to happen. */ +- LIBC_PROBE (reloc_start, 2, args->nsid, r); +- relocation_in_progress = 1; +- } +- +-#ifdef SHARED +- if (__glibc_unlikely (GLRO(dl_profile) != NULL)) +- { +- /* If this here is the shared object which we want to profile +- make sure the profile is started. We can find out whether +- this is necessary or not by observing the `_dl_profile_map' +- variable. If it was NULL but is not NULL afterwards we must +- start the profiling. */ +- struct link_map *old_profile_map = GL(dl_profile_map); +- +- _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); +- +- if (old_profile_map == NULL && GL(dl_profile_map) != NULL) +- { +- /* We must prepare the profiling. */ +- _dl_start_profile (); +- +- /* Prevent unloading the object. */ +- GL(dl_profile_map)->l_nodelete_active = true; +- } +- } +- else +-#endif +- _dl_relocate_object (l, l->l_scope, reloc_mode, 0); +- } ++ _dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode, ++ &relocation_in_progress); + + /* This only performs the memory allocations. The actual update of + the scopes happens below, after failure is impossible. */ diff --git a/SOURCES/glibc-RHEL-21521-3.patch b/SOURCES/glibc-RHEL-21521-3.patch new file mode 100644 index 0000000..d177e19 --- /dev/null +++ b/SOURCES/glibc-RHEL-21521-3.patch @@ -0,0 +1,224 @@ +commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec +Author: Florian Weimer +Date: Mon Nov 27 11:28:13 2023 +0100 + + elf: Relocate libc.so early during startup and dlmopen (bug 31083) + + This makes it more likely that objects without dependencies can + use IFUNC resolvers in libc.so. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/Makefile + (test backport differences) + elf/rtld.c + (prelink support was removed upstream) + +diff --git a/elf/Makefile b/elf/Makefile +index 8e1f91bcd917fd4e..7b7c6c171ce23247 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -419,6 +419,8 @@ tests += \ + tst-nodelete2 \ + tst-nodelete-dlclose \ + tst-nodelete-opened \ ++ tst-nodeps1 \ ++ tst-nodeps2 \ + tst-noload \ + tst-null-argv \ + tst-relsort1 \ +@@ -777,6 +779,8 @@ modules-names = \ + tst-nodelete-dlclose-dso \ + tst-nodelete-dlclose-plugin \ + tst-nodelete-opened-lib \ ++ tst-nodeps1-mod \ ++ tst-nodeps2-mod \ + tst-null-argv-lib \ + tst-relsort1mod1 \ + tst-relsort1mod2 \ +@@ -931,8 +935,15 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) + + # filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special + # rules. +-modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod \ +- tst-audit24bmod1 tst-audit24bmod2 ++modules-names-nobuild += \ ++ filtmod1 \ ++ tst-audit24bmod1 \ ++ tst-audit24bmod2 \ ++ tst-big-note-lib \ ++ tst-nodeps1-mod \ ++ tst-nodeps2-mod \ ++ tst-ro-dynamic-mod \ ++ # modules-names-nobuild + + tests += $(tests-static) + +@@ -2684,3 +2695,18 @@ LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed + $(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so + $(objpfx)tst-dlclose-lazy.out: \ + $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so ++ ++# The object tst-nodeps1-mod.so has no explicit dependencies on libc.so. ++$(objpfx)tst-nodeps1-mod.so: $(objpfx)tst-nodeps1-mod.os ++ $(LINK.o) -nostartfiles -nostdlib -shared -o $@ $^ ++tst-nodeps1.so-no-z-defs = yes ++# Link libc.so before the test module with the IFUNC resolver reference. ++LDFLAGS-tst-nodeps1 = $(common-objpfx)libc.so $(objpfx)tst-nodeps1-mod.so ++$(objpfx)tst-nodeps1: $(objpfx)tst-nodeps1-mod.so ++# Reuse the tst-nodeps1 module. Link libc.so before the test module ++# with the IFUNC resolver reference. ++$(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \ ++ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.os ++ $(LINK.o) -Wl,--no-as-needed -nostartfiles -nostdlib -shared -o $@ $^ ++$(objpfx)tst-nodeps2.out: \ ++ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index bc4d38d6a6b1b5a0..3d81187ede4b09af 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -705,6 +705,17 @@ dl_open_worker_begin (void *a) + them. However, such relocation dependencies in IFUNC resolvers + are undefined anyway, so this is not a problem. */ + ++ /* Ensure that libc is relocated first. This helps with the ++ execution of IFUNC resolvers in libc, and matters only to newly ++ created dlmopen namespaces. Do not do this for static dlopen ++ because libc has relocations against ld.so, which may not have ++ been relocated at this point. */ ++#ifdef SHARED ++ if (GL(dl_ns)[args->nsid].libc_map != NULL) ++ _dl_open_relocate_one_object (args, r, GL(dl_ns)[args->nsid].libc_map, ++ reloc_mode, &relocation_in_progress); ++#endif ++ + for (unsigned int i = last; i-- > first; ) + _dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode, + &relocation_in_progress); +diff --git a/elf/rtld.c b/elf/rtld.c +index 9de53ccaed420a57..a638d14e77745baa 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2421,11 +2421,17 @@ dl_main (const ElfW(Phdr) *phdr, + objects. We do not re-relocate the dynamic linker itself in this + loop because that could result in the GOT entries for functions we + call being changed, and that would break us. It is safe to relocate +- the dynamic linker out of order because it has no copy relocs (we +- know that because it is self-contained). */ ++ the dynamic linker out of order because it has no copy relocations. ++ Likewise for libc, which is relocated early to ensure that IFUNC ++ resolvers in libc work. */ + + int consider_profiling = GLRO(dl_profile) != NULL; + ++ if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) ++ _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map, ++ GL(dl_ns)[LM_ID_BASE].libc_map->l_scope, ++ GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); ++ + /* If we are profiling we also must do lazy reloaction. */ + GLRO(dl_lazy) |= consider_profiling; + +diff --git a/elf/tst-nodeps1-mod.c b/elf/tst-nodeps1-mod.c +new file mode 100644 +index 0000000000000000..45c8e3c631251a89 +--- /dev/null ++++ b/elf/tst-nodeps1-mod.c +@@ -0,0 +1,25 @@ ++/* Test module with no libc.so dependency and string function references. ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++/* Some references to libc symbols which are likely to have IFUNC ++ resolvers. If they do not, this module does not exercise bug 31083. */ ++void *memcpy_pointer = memcpy; ++void *memmove_pointer = memmove; ++void *memset_pointer = memset; +diff --git a/elf/tst-nodeps1.c b/elf/tst-nodeps1.c +new file mode 100644 +index 0000000000000000..1a8bde36cdb71446 +--- /dev/null ++++ b/elf/tst-nodeps1.c +@@ -0,0 +1,23 @@ ++/* Test initially loaded module with implicit libc.so dependency (bug 31083). ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* Testing happens before main. */ ++int ++main (void) ++{ ++} +diff --git a/elf/tst-nodeps2-mod.c b/elf/tst-nodeps2-mod.c +new file mode 100644 +index 0000000000000000..4913feee9b56e0e1 +--- /dev/null ++++ b/elf/tst-nodeps2-mod.c +@@ -0,0 +1 @@ ++/* Empty test module which depends on tst-nodeps1-mod.so. */ +diff --git a/elf/tst-nodeps2.c b/elf/tst-nodeps2.c +new file mode 100644 +index 0000000000000000..0bdc8eeb8cba3a99 +--- /dev/null ++++ b/elf/tst-nodeps2.c +@@ -0,0 +1,29 @@ ++/* Test dlmopen with implicit libc.so dependency (bug 31083). ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-nodeps2-mod.so", RTLD_NOW); ++ xdlclose (handle); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-RHEL-21521-4.patch b/SOURCES/glibc-RHEL-21521-4.patch new file mode 100644 index 0000000..2c34cf6 --- /dev/null +++ b/SOURCES/glibc-RHEL-21521-4.patch @@ -0,0 +1,41 @@ +commit b3bee76c5f59498b9c189608f0a3132e2013fa1a +Author: Florian Weimer +Date: Fri Dec 8 09:51:34 2023 +0100 + + elf: Initialize GLRO(dl_lazy) before relocating libc in dynamic startup + + GLRO(dl_lazy) is used to set the parameters for the early + _dl_relocate_object call, so the consider_profiling setting has to + be applied before the call. + + Fixes commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec ("elf: Relocate + libc.so early during startup and dlmopen (bug 31083)"). + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/rtld.c + (prelink was removed upstream) + +diff --git a/elf/rtld.c b/elf/rtld.c +index a638d14e77745baa..d973c385b312ea16 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2427,14 +2427,14 @@ dl_main (const ElfW(Phdr) *phdr, + + int consider_profiling = GLRO(dl_profile) != NULL; + ++ /* If we are profiling we also must do lazy reloaction. */ ++ GLRO(dl_lazy) |= consider_profiling; ++ + if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) + _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map, + GL(dl_ns)[LM_ID_BASE].libc_map->l_scope, + GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); + +- /* If we are profiling we also must do lazy reloaction. */ +- GLRO(dl_lazy) |= consider_profiling; +- + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); + unsigned i = main_map->l_searchlist.r_nlist; diff --git a/SOURCES/glibc-RHEL-21527.patch b/SOURCES/glibc-RHEL-21527.patch new file mode 100644 index 0000000..5ea1f99 --- /dev/null +++ b/SOURCES/glibc-RHEL-21527.patch @@ -0,0 +1,95 @@ +commit 472894d2cfee5751b44c0aaa71ed87df81c8e62e +Author: Adhemerval Zanella +Date: Wed Oct 11 13:43:56 2023 -0300 + + malloc: Use __get_nprocs on arena_get2 (BZ 30945) + + This restore the 2.33 semantic for arena_get2. It was changed by + 11a02b035b46 to avoid arena_get2 call malloc (back when __get_nproc + was refactored to use an scratch_buffer - 903bc7dcc2acafc). The + __get_nproc was refactored over then and now it also avoid to call + malloc. + + The 11a02b035b46 did not take in consideration any performance + implication, which should have been discussed properly. The + __get_nprocs_sched is still used as a fallback mechanism if procfs + and sysfs is not acessible. + + Checked on x86_64-linux-gnu. + Reviewed-by: DJ Delorie + +diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h +index c490561581..65742b1036 100644 +--- a/include/sys/sysinfo.h ++++ b/include/sys/sysinfo.h +@@ -14,10 +14,6 @@ libc_hidden_proto (__get_nprocs_conf) + extern int __get_nprocs (void); + libc_hidden_proto (__get_nprocs) + +-/* Return the number of available processors which the process can +- be scheduled. */ +-extern int __get_nprocs_sched (void) attribute_hidden; +- + /* Return number of physical pages of memory in the system. */ + extern long int __get_phys_pages (void); + libc_hidden_proto (__get_phys_pages) +diff --git a/malloc/arena.c b/malloc/arena.c +index d1e214ac2e..a1a75e5a2b 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -824,7 +824,7 @@ arena_get2 (size_t size, mstate avoid_arena) + narenas_limit = mp_.arena_max; + else if (narenas > mp_.arena_test) + { +- int n = __get_nprocs_sched (); ++ int n = __get_nprocs (); + + if (n >= 1) + narenas_limit = NARENAS_FROM_NCORES (n); +diff --git a/misc/getsysstats.c b/misc/getsysstats.c +index 5f36adc0e8..23cc112074 100644 +--- a/misc/getsysstats.c ++++ b/misc/getsysstats.c +@@ -44,12 +44,6 @@ weak_alias (__get_nprocs, get_nprocs) + link_warning (get_nprocs, "warning: get_nprocs will always return 1") + + +-int +-__get_nprocs_sched (void) +-{ +- return 1; +-} +- + long int + __get_phys_pages (void) + { +diff --git a/sysdeps/mach/getsysstats.c b/sysdeps/mach/getsysstats.c +index 5184e5eee1..d3834f3b69 100644 +--- a/sysdeps/mach/getsysstats.c ++++ b/sysdeps/mach/getsysstats.c +@@ -62,12 +62,6 @@ __get_nprocs (void) + libc_hidden_def (__get_nprocs) + weak_alias (__get_nprocs, get_nprocs) + +-int +-__get_nprocs_sched (void) +-{ +- return __get_nprocs (); +-} +- + /* Return the number of physical pages on the system. */ + long int + __get_phys_pages (void) +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index b0b6c154ac..1ea7f1f01f 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -29,7 +29,7 @@ + #include + #include + +-int ++static int + __get_nprocs_sched (void) + { + enum diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec index 15f0b37..5d55528 100644 --- a/SPECS/glibc.spec +++ b/SPECS/glibc.spec @@ -155,7 +155,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 83%{?dist}.7 +Release: 83%{?dist}.12 # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -770,6 +770,19 @@ Patch533: glibc-RHEL-2426-13.patch Patch534: glibc-RHEL-3000.patch Patch535: glibc-RHEL-2426-14.patch Patch536: glibc-RHEL-2426-15.patch +Patch537: glibc-RHEL-21527.patch +Patch538: glibc-RHEL-21518.patch +Patch539: glibc-RHEL-21521-1.patch +Patch540: glibc-RHEL-21521-2.patch +Patch541: glibc-RHEL-21521-3.patch +Patch542: glibc-RHEL-21521-4.patch +Patch543: glibc-RHEL-21007-1.patch +Patch544: glibc-RHEL-21007-2.patch +Patch545: glibc-RHEL-21007-3.patch +Patch546: glibc-RHEL-21007-4.patch +Patch547: glibc-RHEL-21007-5.patch +Patch548: glibc-RHEL-21007-6.patch +Patch549: glibc-RHEL-21240.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2927,6 +2940,21 @@ update_gconv_modules_cache () %endif %changelog +* Wed Feb 07 2024 Carlos O'Donell - 2.34-83.12 +- getaddrinfo: Return correct error EAI_MEMORY when out-of-memory (RHEL-21240) + +* Wed Feb 07 2024 Carlos O'Donell - 2.34-83.11 +- getaddrinfo: Fix occasionally empty result due to nscd cache order (RHEL-21007) + +* Wed Feb 07 2024 Carlos O'Donell - 2.34-83.10 +- Improve compatibility between underlinking and IFUNC resolvers (RHEL-21521) + +* Wed Feb 07 2024 Carlos O'Donell - 2.34-83.9 +- Fix force-first handling in dlclose (RHEL-21518) + +* Mon Jan 29 2024 DJ Delorie - 2.34-83.8 +- malloc: Use __get_nprocs on arena_get2. (RHEL-21527) + * Mon Sep 25 2023 Florian Weimer - 2.34-83.7 - Fix memory leak regression in getaddrinfo (RHEL-2426)