diff --git a/glibc-rh2128615-1.patch b/glibc-rh2128615-1.patch new file mode 100644 index 0000000..b4783d8 --- /dev/null +++ b/glibc-rh2128615-1.patch @@ -0,0 +1,37 @@ +commit 183d99737298bb3200f0610fdcd1c7549c8ed560 +Author: Florian Weimer +Date: Tue Sep 6 07:38:10 2022 +0200 + + scripts/dso-ordering-test.py: Generate program run-time dependencies + + The main program needs to depend on all shared objects, even objects + that have link-time dependencies among shared objects. Filtering + out shared objects that already have an link-time dependencies is not + necessary here; make will do this automatically. + + Reviewed-by: Adhemerval Zanella + +diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py +index bde0406be9da14fc..4ffcff6136145ef1 100644 +--- a/scripts/dso-ordering-test.py ++++ b/scripts/dso-ordering-test.py +@@ -707,13 +707,12 @@ def process_testcase(t): + "\t$(compile.c) $(OUTPUT_OPTION)\n") + makefile.write (rule) + +- not_depended_objs = find_objs_not_depended_on(test_descr) +- if not_depended_objs: +- depstr = "" +- for dep in not_depended_objs: +- depstr += (" $(objpfx)" + test_subdir + "/" +- + test_name + "-" + dep + ".so") +- makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr)) ++ # Ensure that all shared objects are built before running the ++ # test, whether there link-time dependencies or not. ++ depobjs = ["$(objpfx){}/{}-{}.so".format(test_subdir, test_name, dep) ++ for dep in test_descr.objs] ++ makefile.write("$(objpfx){}.out: {}\n".format( ++ base_test_name, " ".join(depobjs))) + + # Add main executable to test-srcs + makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name)) diff --git a/glibc-rh2128615-2.patch b/glibc-rh2128615-2.patch new file mode 100644 index 0000000..2d8d4ac --- /dev/null +++ b/glibc-rh2128615-2.patch @@ -0,0 +1,79 @@ +commit dbb75513f5cf9285c77c9e55777c5c35b653f890 +Author: Florian Weimer +Date: Tue Sep 6 07:38:10 2022 +0200 + + elf: Rename _dl_sort_maps parameter from skip to force_first + + The new implementation will not be able to skip an arbitrary number + of objects. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index 72f4ff0e6eda3377..7c614bca5d8115c6 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -27,12 +27,12 @@ + If FOR_FINI is true, this is called for finishing an object. */ + static void + _dl_sort_maps_original (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) ++ bool force_first, bool for_fini) + { + /* Allows caller to do the common optimization of skipping the first map, + usually the main binary. */ +- maps += skip; +- nmaps -= skip; ++ maps += force_first; ++ nmaps -= force_first; + + /* A list of one element need not be sorted. */ + if (nmaps <= 1) +@@ -182,7 +182,7 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map, + + static void + _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, +- unsigned int skip __attribute__ ((unused)), bool for_fini) ++ bool force_first __attribute__ ((unused)), bool for_fini) + { + for (int i = nmaps - 1; i >= 0; i--) + maps[i]->l_visited = 0; +@@ -286,7 +286,7 @@ _dl_sort_maps_init (void) + + void + _dl_sort_maps (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) ++ bool force_first, bool for_fini) + { + /* It can be tempting to use a static function pointer to store and call + the current selected sorting algorithm routine, but experimentation +@@ -296,9 +296,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, + input cases. A simple if-case with direct function calls appears to + be the fastest. */ + if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original)) +- _dl_sort_maps_original (maps, nmaps, skip, for_fini); ++ _dl_sort_maps_original (maps, nmaps, force_first, for_fini); + else +- _dl_sort_maps_dfs (maps, nmaps, skip, for_fini); ++ _dl_sort_maps_dfs (maps, nmaps, force_first, for_fini); + } + + #endif /* HAVE_TUNABLES. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 87ad2f3f4d89eb7d..8c0fe98f69a88f1e 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1106,9 +1106,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv, + initializer functions have completed. */ + extern void _dl_fini (void) attribute_hidden; + +-/* Sort array MAPS according to dependencies of the contained objects. */ ++/* Sort array MAPS according to dependencies of the contained objects. ++ If FORCE_FIRST, MAPS[0] keeps its place even if the dependencies ++ say otherwise. */ + extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) attribute_hidden; ++ bool force_first, bool for_fini) attribute_hidden; + + /* The dynamic linker calls this function before and having changing + any shared object mappings. The `r_state' member of `struct r_debug' diff --git a/glibc-rh2128615-3.patch b/glibc-rh2128615-3.patch new file mode 100644 index 0000000..bf8a9a4 --- /dev/null +++ b/glibc-rh2128615-3.patch @@ -0,0 +1,90 @@ +commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891 +Author: Florian Weimer +Date: Tue Sep 20 11:00:42 2022 +0200 + + elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937) + + The implementation in _dl_close_worker requires that the first + element of l_initfini is always this very map (“We are always the + zeroth entry, and since we don't include ourselves in the + dependency analysis start at 1.”). Rather than fixing that + assumption, this commit adds an implementation of the force_first + argument to the new dependency sorting algorithm. This also means + that the directly dlopen'ed shared object is always initialized last, + which is the least surprising behavior in the presence of cycles. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index 7c614bca5d8115c6..e8ef5e8b3588ab53 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map, + + static void + _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, +- bool force_first __attribute__ ((unused)), bool for_fini) ++ bool force_first, bool for_fini) + { ++ struct link_map *first_map = maps[0]; + for (int i = nmaps - 1; i >= 0; i--) + maps[i]->l_visited = 0; + +@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, + Adjusting the order so that maps[0] is last traversed naturally avoids + this problem. + +- Further, the old "optimization" of skipping the main object at maps[0] +- from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general +- no longer valid, since traversing along object dependency-links +- may "find" the main object even when it is not included in the initial +- order (e.g. a dlopen()'ed shared object can have circular dependencies +- linked back to itself). In such a case, traversing N-1 objects will +- create a N-object result, and raise problems. +- + To summarize, just passing in the full list, and iterating from back + to front makes things much more straightforward. */ + +@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, + } + + 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 ++ first object even when it is not included in the initial order ++ (e.g., a dlopen'ed shared object can have circular dependencies ++ linked back to itself). In such a case, traversing N-1 objects ++ will create a N-object result, and raise problems. Instead, ++ force the object back into first place after sorting. This naive ++ approach may introduce further dependency ordering violations ++ compared to rotating the cycle until the first map is again in ++ the first position, but as there is a cycle, at least one ++ violation is already present. */ ++ if (force_first && maps[0] != first_map) ++ { ++ int i; ++ for (i = 0; maps[i] != first_map; ++i) ++ ; ++ assert (i < nmaps); ++ memmove (&maps[1], maps, i * sizeof (maps[0])); ++ maps[0] = first_map; ++ } + } + + void +diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def +index 5f7f18ef270bc12d..4bf9052db16fb352 100644 +--- a/elf/dso-sort-tests-1.def ++++ b/elf/dso-sort-tests-1.def +@@ -64,3 +64,10 @@ output: b>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[a1;a->a2;a2->a;b->b1;c->a1;c=>a1 ++output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[];%c(a1());}a1>a>];+b[b1>b>];-b[];%c(a1());} - 2.34-46 +- DSO dependency sort must put new map first even if in cycle (#2128615) + * Tue Oct 11 2022 Florian Weimer - 2.34-45 - Run tst-audit-tlsdesc{,-dlopen} on all architectures (#2118666)