Hello community, here is the log from the commit of package glibc for openSUSE:Leap:15.2 checked in at 2020-03-24 19:05:12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/glibc (Old) and /work/SRC/openSUSE:Leap:15.2/.glibc.new.3160 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "glibc" Tue Mar 24 19:05:12 2020 rev:72 rq:786665 version:2.26 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/glibc/glibc.changes 2020-03-20 05:52:54.200063360 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.glibc.new.3160/glibc.changes 2020-03-24 19:05:13.413438067 +0100 @@ -1,0 +2,6 @@ +Tue Mar 10 10:30:36 UTC 2020 - Andreas Schwab <[email protected]> + +- dl-sort-maps.patch, dlopen-filter-object.patch: Allow dlopen of filter + object to work (bsc#1166106, BZ #16272) + +------------------------------------------------------------------- New: ---- dl-sort-maps.patch dlopen-filter-object.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ glibc.spec ++++++ --- /var/tmp/diff_new_pack.qJq9Jc/_old 2020-03-24 19:05:16.129439893 +0100 +++ /var/tmp/diff_new_pack.qJq9Jc/_new 2020-03-24 19:05:16.129439893 +0100 @@ -425,6 +425,9 @@ Patch1077: manual-memory-protection.patch # PATCH-FIX-UPSTREAM Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (CVE-2020-10029, BZ #25487) Patch1078: ldbl-96-rem-pio2l.patch +# PATCH-FIX-UPSTREAM elf: Allow dlopen of filter object to work (BZ #16272) +Patch1079: dl-sort-maps.patch +Patch1080: dlopen-filter-object.patch ### # Patches awaiting upstream approval @@ -738,6 +741,8 @@ %patch1076 -p1 %patch1077 -p1 %patch1078 -p1 +%patch1079 -p1 +%patch1080 -p1 %patch2000 -p1 %patch2001 -p1 ++++++ dl-sort-maps.patch ++++++ 2017-11-27 Andreas Schwab <[email protected]> * elf/Makefile (dl-routines): Add dl-sort-maps. * elf/dl-sort-maps.c: New file. * sysdeps/generic/ldsodefs.h (_dl_sort_fini): Don't declare. (_dl_sort_maps): Declare. * elf/dl-fini.c (_dl_sort_fini): Remove. (_dl_fini): Use _dl_sort_maps instead of _dl_sort_fini. * elf/dl-close.c (_dl_close_worker): Likewise. * elf/dl-deps.c (_dl_map_object_deps): Use _dl_sort_maps instead of open-coding it. * elf/dl-open.c (dl_open_worker): Likewise. Index: glibc-2.26/elf/Makefile =================================================================== --- glibc-2.26.orig/elf/Makefile +++ glibc-2.26/elf/Makefile @@ -31,7 +31,8 @@ routines = $(all-dl-routines) dl-support dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ runtime init fini debug misc \ version profile tls origin scope \ - execstack caller open close trampoline) + execstack caller open close trampoline \ + sort-maps) ifeq (yes,$(use-ldconfig)) dl-routines += dl-cache endif Index: glibc-2.26/elf/dl-close.c =================================================================== --- glibc-2.26.orig/elf/dl-close.c +++ glibc-2.26/elf/dl-close.c @@ -241,8 +241,10 @@ _dl_close_worker (struct link_map *map, } } - /* Sort the entries. */ - _dl_sort_fini (maps, nloaded, used, nsid); + /* 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 + (nsid == LM_ID_BASE), nloaded - (nsid == LM_ID_BASE), + used + (nsid == LM_ID_BASE), true); /* Call all termination functions at once. */ #ifdef SHARED Index: glibc-2.26/elf/dl-deps.c =================================================================== --- glibc-2.26.orig/elf/dl-deps.c +++ glibc-2.26/elf/dl-deps.c @@ -610,62 +610,9 @@ Filters not supported with LD_TRACE_PREL itself will always be initialize last. */ memcpy (l_initfini, map->l_searchlist.r_list, nlist * sizeof (struct link_map *)); - if (__glibc_likely (nlist > 1)) - { - /* We can skip looking for the binary itself which is at the front - of the search list. */ - i = 1; - uint16_t seen[nlist]; - memset (seen, 0, nlist * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = l_initfini[i]; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - unsigned int k = nlist - 1; - while (k > i) - { - struct link_map **runp = l_initfini[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&l_initfini[i], &l_initfini[i + 1], - (k - i) * sizeof (l_initfini[0])); - l_initfini[k] = thisp; - - if (seen[i + 1] > nlist - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], - (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - --k; - } - - if (++i == nlist) - break; - next_clear: - memset (&seen[i], 0, (nlist - i) * sizeof (seen[0])); - - next:; - } - } + /* We can skip looking for the binary itself which is at the front of + the search list. */ + _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); /* Terminate the list of dependencies. */ l_initfini[nlist] = NULL; Index: glibc-2.26/elf/dl-fini.c =================================================================== --- glibc-2.26.orig/elf/dl-fini.c +++ glibc-2.26/elf/dl-fini.c @@ -27,105 +27,6 @@ typedef void (*fini_t) (void); void internal_function -_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns) -{ - /* A list of one element need not be sorted. */ - if (nmaps == 1) - return; - - /* We can skip looking for the binary itself which is at the front - of the search list for the main namespace. */ - unsigned int i = ns == LM_ID_BASE; - uint16_t seen[nmaps]; - memset (seen, 0, nmaps * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = maps[i]; - - /* Do not handle ld.so in secondary namespaces and object which - are not removed. */ - if (thisp != thisp->l_real || thisp->l_idx == -1) - goto skip; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - unsigned int k = nmaps - 1; - while (k > i) - { - struct link_map **runp = maps[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - move: - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&maps[i], &maps[i + 1], - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - - if (used != NULL) - { - char here_used = used[i]; - memmove (&used[i], &used[i + 1], - (k - i) * sizeof (used[0])); - used[k] = here_used; - } - - if (seen[i + 1] > nmaps - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - if (__glibc_unlikely (maps[k]->l_reldeps != NULL)) - { - unsigned int m = maps[k]->l_reldeps->act; - struct link_map **relmaps = &maps[k]->l_reldeps->list[0]; - - /* Look through the relocation dependencies of the object. */ - while (m-- > 0) - if (__glibc_unlikely (relmaps[m] == thisp)) - { - /* If a cycle exists with a link time dependency, - preserve the latter. */ - struct link_map **runp = thisp->l_initfini; - if (runp != NULL) - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == maps[k])) - goto ignore; - goto move; - } - ignore:; - } - - --k; - } - - skip: - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - - next:; - } -} - - -void -internal_function _dl_fini (void) { /* Lots of fun ahead. We have to call the destructors for all still @@ -188,8 +89,11 @@ _dl_fini (void) assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1); unsigned int nmaps = i; - /* Now we have to do the sorting. */ - _dl_sort_fini (maps, nmaps, NULL, ns); + /* Now we have to do the sorting. 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 + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE), + NULL, true); /* We do not rely on the linked list of loaded object anymore from this point on. We have our own list here (maps). The Index: glibc-2.26/elf/dl-open.c =================================================================== --- glibc-2.26.orig/elf/dl-open.c +++ glibc-2.26/elf/dl-open.c @@ -313,7 +313,7 @@ dl_open_worker (void *a) /* Sort the objects by dependency for the relocation process. This allows IFUNC relocations to work and it also means copy relocation of dependencies are if necessary overwritten. */ - size_t nmaps = 0; + unsigned int nmaps = 0; struct link_map *l = new; do { @@ -332,62 +332,11 @@ dl_open_worker (void *a) l = l->l_next; } while (l != NULL); - if (nmaps > 1) - { - uint16_t seen[nmaps]; - memset (seen, '\0', sizeof (seen)); - size_t i = 0; - while (1) - { - ++seen[i]; - struct link_map *thisp = maps[i]; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - size_t k = nmaps - 1; - while (k > i) - { - struct link_map **runp = maps[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&maps[i], &maps[i + 1], - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - - if (seen[i + 1] > nmaps - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], - (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - --k; - } - - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - next:; - } - } + _dl_sort_maps (maps, nmaps, NULL, false); int relocation_in_progress = 0; - for (size_t i = nmaps; i-- > 0; ) + for (unsigned int i = nmaps; i-- > 0; ) { l = maps[i]; Index: glibc-2.26/elf/dl-sort-maps.c =================================================================== --- /dev/null +++ glibc-2.26/elf/dl-sort-maps.c @@ -0,0 +1,123 @@ +/* Sort array of link maps according to dependencies. + Copyright (C) 2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <ldsodefs.h> + + +/* Sort array MAPS according to dependencies of the contained objects. + Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is + called for finishing an object. */ +void +internal_function +_dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, + bool for_fini) +{ + /* A list of one element need not be sorted. */ + if (nmaps <= 1) + return; + + unsigned int i = 0; + uint16_t seen[nmaps]; + memset (seen, 0, nmaps * sizeof (seen[0])); + while (1) + { + /* Keep track of which object we looked at this round. */ + ++seen[i]; + struct link_map *thisp = maps[i]; + + if (__glibc_unlikely (for_fini)) + { + /* Do not handle ld.so in secondary namespaces and objects which + are not removed. */ + if (thisp != thisp->l_real || thisp->l_idx == -1) + goto skip; + } + + /* Find the last object in the list for which the current one is + a dependency and move the current object behind the object + with the dependency. */ + unsigned int k = nmaps - 1; + while (k > i) + { + struct link_map **runp = maps[k]->l_initfini; + if (runp != NULL) + /* Look through the dependencies of the object. */ + while (*runp != NULL) + if (__glibc_unlikely (*runp++ == thisp)) + { + move: + /* Move the current object to the back past the last + object with it as the dependency. */ + memmove (&maps[i], &maps[i + 1], + (k - i) * sizeof (maps[0])); + maps[k] = thisp; + + if (used != NULL) + { + char here_used = used[i]; + memmove (&used[i], &used[i + 1], + (k - i) * sizeof (used[0])); + used[k] = here_used; + } + + if (seen[i + 1] > nmaps - i) + { + ++i; + goto next_clear; + } + + uint16_t this_seen = seen[i]; + memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); + seen[k] = this_seen; + + goto next; + } + + if (__glibc_unlikely (for_fini && maps[k]->l_reldeps != NULL)) + { + unsigned int m = maps[k]->l_reldeps->act; + struct link_map **relmaps = &maps[k]->l_reldeps->list[0]; + + /* Look through the relocation dependencies of the object. */ + while (m-- > 0) + if (__glibc_unlikely (relmaps[m] == thisp)) + { + /* If a cycle exists with a link time dependency, + preserve the latter. */ + struct link_map **runp = thisp->l_initfini; + if (runp != NULL) + while (*runp != NULL) + if (__glibc_unlikely (*runp++ == maps[k])) + goto ignore; + goto move; + } + ignore:; + } + + --k; + } + + skip: + if (++i == nmaps) + break; + next_clear: + memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); + + next:; + } +} Index: glibc-2.26/sysdeps/generic/ldsodefs.h =================================================================== --- glibc-2.26.orig/sysdeps/generic/ldsodefs.h +++ glibc-2.26/sysdeps/generic/ldsodefs.h @@ -908,8 +908,8 @@ extern void _dl_init (struct link_map *m extern void _dl_fini (void) internal_function; /* Sort array MAPS according to dependencies of the contained objects. */ -extern void _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, - Lmid_t ns) +extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps, + char *used, bool for_fini) internal_function attribute_hidden; /* The dynamic linker calls this function before and having changing ++++++ dlopen-filter-object.patch ++++++ >From eb447b7b4bd6177f876ba9420ad9e048c27bae91 Mon Sep 17 00:00:00 2001 From: David Kilroy <[email protected]> Date: Wed, 12 Feb 2020 14:28:15 -0300 Subject: [PATCH] elf: Allow dlopen of filter object to work [BZ #16272] There are two fixes that are needed to be able to dlopen filter objects. First _dl_map_object_deps cannot assume that map will be at the beginning of l_searchlist.r_list[], as filtees are inserted before map. Secondly dl_open_worker needs to ensure that filtees get relocated. In _dl_map_object_deps: * avoiding removing relocation dependencies of map by setting l_reserved to 0 and otherwise processing the rest of the search list. * ensure that map remains at the beginning of l_initfini - the list of things that need initialisation (and destruction). Do this by splitting the copy up. This may not be required, but matches the initialization order without dlopen. Modify dl_open_worker to relocate the objects in new->l_inifini. new->l_initfini is constructed in _dl_map_object_deps, and lists the objects that need initialization and destruction. Originally the list of objects in new->l_next are relocated. All of these objects should also be included in new->l_initfini (both lists are populated with dependencies in _dl_map_object_deps). We can't use new->l_prev to pick up filtees, as during a recursive dlopen from an interposed malloc call, l->prev can contain objects that are not ready for relocation. Add tests to verify that symbols resolve to the filtee implementation when auxiliary and filter objects are used, both as a normal link and when dlopen'd. Tested by running the testsuite on x86_64. Index: glibc-2.26/elf/dl-deps.c =================================================================== --- glibc-2.26.orig/elf/dl-deps.c +++ glibc-2.26/elf/dl-deps.c @@ -506,14 +506,18 @@ _dl_map_object_deps (struct link_map *ma map->l_searchlist.r_list = &l_initfini[nlist + 1]; map->l_searchlist.r_nlist = nlist; + unsigned int map_index = UINT_MAX; for (nlist = 0, runp = known; runp; runp = runp->next) { if (__builtin_expect (trace_mode, 0) && runp->map->l_faked) /* This can happen when we trace the loading. */ --map->l_searchlist.r_nlist; - else + else { + if (runp->map == map) + map_index = nlist; map->l_searchlist.r_list[nlist++] = runp->map; + } /* Now clear all the mark bits we set in the objects on the search list to avoid duplicates, so the next call starts fresh. */ @@ -571,13 +575,14 @@ Filters not supported with LD_TRACE_PREL } /* Maybe we can remove some relocation dependencies now. */ - assert (map->l_searchlist.r_list[0] == map); struct link_map_reldeps *l_reldeps = NULL; if (map->l_reldeps != NULL) { - for (i = 1; i < nlist; ++i) + for (i = 0; i < nlist; ++i) map->l_searchlist.r_list[i]->l_reserved = 1; + /* Avoid removing relocation dependencies of the main binary. */ + map->l_reserved = 0; struct link_map **list = &map->l_reldeps->list[0]; for (i = 0; i < map->l_reldeps->act; ++i) if (list[i]->l_reserved) @@ -602,16 +607,30 @@ Filters not supported with LD_TRACE_PREL } } - for (i = 1; i < nlist; ++i) + for (i = 0; i < nlist; ++i) map->l_searchlist.r_list[i]->l_reserved = 0; } - /* Sort the initializer list to take dependencies into account. The binary - itself will always be initialize last. */ - memcpy (l_initfini, map->l_searchlist.r_list, - nlist * sizeof (struct link_map *)); - /* We can skip looking for the binary itself which is at the front of - the search list. */ + /* Sort the initializer list to take dependencies into account. Always + initialize the binary itself last. */ + assert (map_index < nlist); + if (map_index > 0) + { + /* Copy the binary into position 0. */ + l_initfini[0] = map->l_searchlist.r_list[map_index]; + + /* Copy the filtees. */ + for (i = 0; i < map_index; ++i) + l_initfini[i+1] = map->l_searchlist.r_list[i]; + + /* Copy the remainder. */ + for (i = map_index + 1; i < nlist; ++i) + l_initfini[i] = map->l_searchlist.r_list[i]; + } + else + memcpy (l_initfini, map->l_searchlist.r_list, + nlist * sizeof (struct link_map *)); + _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); /* Terminate the list of dependencies. */ Index: glibc-2.26/elf/dl-open.c =================================================================== --- glibc-2.26.orig/elf/dl-open.c +++ glibc-2.26/elf/dl-open.c @@ -314,22 +314,25 @@ dl_open_worker (void *a) allows IFUNC relocations to work and it also means copy relocation of dependencies are if necessary overwritten. */ unsigned int nmaps = 0; - struct link_map *l = new; + unsigned int j = 0; + struct link_map *l = new->l_initfini[0]; do { if (! l->l_real->l_relocated) ++nmaps; - l = l->l_next; + l = new->l_initfini[++j]; } while (l != NULL); + /* Stack allocation is limited by the number of loaded objects. */ struct link_map *maps[nmaps]; nmaps = 0; - l = new; + j = 0; + l = new->l_initfini[0]; do { if (! l->l_real->l_relocated) maps[nmaps++] = l; - l = l->l_next; + l = new->l_initfini[++j]; } while (l != NULL); _dl_sort_maps (maps, nmaps, NULL, false);
