diff options
| author | Mister Oyster <oysterized@gmail.com> | 2017-08-03 15:47:16 +0200 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-08-03 15:49:33 +0200 |
| commit | 766400d1e6dbe9739b093fe0919b40cb3869caf1 (patch) | |
| tree | a58c69f842f617f859c5fd81d98f7deb8d895894 | |
| parent | 58da79a794e599fbc1a4c283005dc439d4a774ec (diff) | |
patch: add shim and force_shim & soong flags
| -rw-r--r-- | patches/bionic/0001-linker-Add-support-for-dynamic-SHIM-libraries.patch | 320 | ||||
| -rw-r--r-- | patches/bionic/0002-bionic-linker_forced_shim_libs.patch | 65 | ||||
| -rw-r--r-- | patches/build/make/core/0002-O-export-FORCED_SHIM_LIBS-to-Soong.patch | 25 | ||||
| -rw-r--r-- | patches/build/soong/0001-O-add-LINKER_FORCED_SHIM_LIBS-to-Soong.patch | 41 | ||||
| -rw-r--r-- | patches/install.sh | 2 | ||||
| -rw-r--r-- | patches/uninstall.sh | 2 |
6 files changed, 453 insertions, 2 deletions
diff --git a/patches/bionic/0001-linker-Add-support-for-dynamic-SHIM-libraries.patch b/patches/bionic/0001-linker-Add-support-for-dynamic-SHIM-libraries.patch new file mode 100644 index 0000000..544d2c6 --- /dev/null +++ b/patches/bionic/0001-linker-Add-support-for-dynamic-SHIM-libraries.patch @@ -0,0 +1,320 @@ +From 8ed801855ba609cee1f413b7cea4b9b5f6b03c53 Mon Sep 17 00:00:00 2001 +From: Adrian DC <radian.dc@gmail.com> +Date: Sat, 8 Apr 2017 22:40:01 +0200 +Subject: [PATCH] linker: Add support for dynamic SHIM libraries + + * Adapt to latest AOSP bionic linker changes + * Additional header to avoid unused function + +linker: Add support for dynamic "shim" libs + +Add a new environment variable + +LD_SHIM_LIBS + +that is a colon (":") separated list of vertical bar ("|") separated pairs. +The pairs are the name for a soinfo reference (executable or shared library) +followed by the name of the shim library to load. For example: + +LD_SHIM_LIBS=rmt_storage|libshim_ioprio.so:/system/lib/libicuuv.so|libshim_icu53.so + +will instruct the linker to load the dynamic library libshim_ioprio.so +whenver rmt_storage is executed [*] and will load libshim_icu53.so whenever +any executable or other shared library links against /system/lib/libicuuv.so. + +There are no restrictions against circular references. In this example, +libshim_icu53.so can link against libicuuv.so which provides a simple and +convenient means of adding compatibility symbols. + +[*] Note that the absolute path is not available to the linker and therefore +using the name of executables does depend on the invocation and therefore +should only be used if absolutely necessary. That is, running +/system/bin/rmt_storage would not load any shim libs in this example because +it does not match the name of the invocation of the command. + +If you have trouble determining the sonames being loaded, you can also set +the environment variable LD_DEBUG=1 which will cause additional information +to be logged to help trace the detection of the shim libs. + +Change-Id: I0ef80fa466167f7bcb7dac90842bef1c3cf879b6 + +linker: Fix the fact that shim libs do not properly call constructors + +Change-Id: I34333e13443a154e675b853fa41442351bc4243a + +linker: Don't try to walk the g_active_shim_libs when doing dlsym + +This is a bug in the original shim_lib implementation which was +doing the shim lib resolution both when loading the libraries +and when doing the dynamic symbol resolution. + +Change-Id: Ib2df0498cf551b3bbd37d7c351410b9908eb1795 + +Revert "Revert "linker: Reset the active shim libs each time we do a dlopen"" + +This reverts commit fd0140b028dedabc572f4659cc015edfeee3cd60. + +Change-Id: I42b3acfcdc6b84251a396b9e42604bb5685196bd + +Make shim lib load failure non-fatal. + +Instead, print an appropriate warning message. Aborting symbol +resolution on shim lib load failure leads to weird symbol lookup +failures, because symbols in libraries referenced after the one loading +the shim won't be loaded anymore without a log message stating why that +happened. + +Change-Id: Ic3ad7095ddae7ea1039cb6a18603d5cde8a16143 + +bionic: Do not allow LD_SHIM_LIBS for setuid executables + +That's really not safe... + +Change-Id: If79af951830966fc21812cd0f60a8998a752a941 + +bionic: linker: Load shim libs *before* the self-linked libs + +By loading them earlier, this allows us to override a symbol in +a library that is being directly linked. + +I believe this explains why some people have had problems shimming +one lib but when the changet he shim to be against a different +lib it magically works. + +It also makes it possible to override some symbols that were +nearly impossible to override before this change. For example, it is +pretty much impossible to override a symbol in libutils without +this change because it's loaded almost everywhere so no matter +where you try to place the shimming, it will be too late and +the other symbol will have priority. + +In particularly, this is necessary to be able to correctly +shim the VectorImpl symbols for dlx. + +Change-Id: I461ca416bc288e28035352da00fde5f34f8d9ffa + +linker: Allow text-relocs for x86 (only) + +This effectively reverts + +https://android.googlesource.com/platform/bionic/+/e4ad91f86a47b39612e030a162f4793cb3421d31%5E%21/#F0 + +for x86 platforms. Unfortunately, this seems like it is required +if we are going to support ffmpeg. The ffmpeg team decreed that they +require text relocations for x86 (only) and that they would not +fix the fact that android 6.0 makes ffmpeg unusable on x86: + +https://trac.ffmpeg.org/ticket/4928 + +Change-Id: I68397f4d62f4f6acd8e0d41b7ecdc115969b890a + +linker: Update find_library call for shimlibs + +commits 0cdef7e7f3c6837b56a969120d9098463d1df8d8 +"Respect caller DT_RUNPATH in dlopen()." +and 42d5fcb9f494eb45de3b6bf759f4a18076e84728 +"Introducing linker namespaces" +added new arguments to find_library, add them here. + +Change-Id: I8f35a45b00d14f8b2ce01a0a96d2dc7759be04a6 + +linker: Update LD_SHIM_LIBS parser function + + * Upgrade the code using the same changes as + 42d5fcb9f494eb45de3b6bf759f4a18076e84728 + bda20e78f0f314dbbf0f0bbcf0740cf2d6a4b85e + +Change-Id: Ic8be0871945bd9feccd0f94a6770f3cc78a70a0f + +Inject shim libs as if they were DT_NEEDED. + +The previous separate approach had one flaw: If the shim lib requires +another lib that's already loaded, find_library_internal() would return +the previously loaded copy, but the later load action would fail as the +ELF reader map of the initial loading round was already discarded and +thus a new ElfReader instance for the soinfo instance was created, which +didn't know about the previous reading/loading state. + +Change-Id: Ib224dbd35d114197097e3dee14a077cc9130fedb + +linker: Make platform text relocations denial enabled by default + + * msm8960 variant to support relocations by default + + * Partial revert "Remove textrels support for platform libs" + commit 8068786ae67835291521e52f39c695e40f3ad20d. + +Change-Id: I994ab1a600a0b237b496ceebe2dd54febc28a6bd + +linker: load shims prior to dt_needed check + +This allows shims to override existing symbols, not just +inject new symbols. + +Change-Id: Ib9216bcc651d8d38999c593babb94d76dc1dbc95 +--- + libc/bionic/libc_init_common.cpp | 1 + + linker/linker.cpp | 69 +++++++++++++++++++++++++++++++++++++++- + linker/linker.h | 2 ++ + linker/linker_main.cpp | 3 ++ + 4 files changed, 74 insertions(+), 1 deletion(-) + +diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp +index e051762fddf..aad3d2cb8a7 100644 +--- a/libc/bionic/libc_init_common.cpp ++++ b/libc/bionic/libc_init_common.cpp +@@ -262,6 +262,7 @@ static bool __is_unsafe_environment_variable(const char* name) { + "LD_ORIGIN_PATH", + "LD_PRELOAD", + "LD_PROFILE", ++ "LD_SHIM_LIBS", + "LD_SHOW_AUXV", + "LD_USE_LOAD_BIAS", + "LOCALDOMAIN", +diff --git a/linker/linker.cpp b/linker/linker.cpp +index 8e7a1411c86..104f22325d7 100644 +--- a/linker/linker.cpp ++++ b/linker/linker.cpp +@@ -691,6 +691,68 @@ enum walk_action_result_t : uint32_t { + kWalkSkip = 2 + }; + ++static soinfo* find_library(android_namespace_t* ns, ++ const char* name, int rtld_flags, ++ const android_dlextinfo* extinfo, ++ soinfo* needed_by); ++ ++// g_ld_all_shim_libs maintains the references to memory as it used ++// in the soinfo structures and in the g_active_shim_libs list. ++ ++typedef std::pair<std::string, std::string> ShimDescriptor; ++static std::vector<ShimDescriptor> g_ld_all_shim_libs; ++ ++// g_active_shim_libs are all shim libs that are still eligible ++// to be loaded. We must remove a shim lib from the list before ++// we load the library to avoid recursive loops (load shim libA ++// for libB where libA also links against libB). ++ ++static linked_list_t<const ShimDescriptor> g_active_shim_libs; ++ ++static void reset_g_active_shim_libs(void) { ++ g_active_shim_libs.clear(); ++ for (const auto& pair : g_ld_all_shim_libs) { ++ g_active_shim_libs.push_back(&pair); ++ } ++} ++ ++void parse_LD_SHIM_LIBS(const char* path) { ++ g_ld_all_shim_libs.clear(); ++ if (path != nullptr) { ++ // We have historically supported ':' as well as ' ' in LD_SHIM_LIBS. ++ for (const auto& pair : android::base::Split(path, " :")) { ++ size_t pos = pair.find('|'); ++ if (pos > 0 && pos < pair.length() - 1) { ++ auto desc = std::pair<std::string, std::string>(pair.substr(0, pos), pair.substr(pos + 1)); ++ g_ld_all_shim_libs.push_back(desc); ++ } ++ } ++ } ++ reset_g_active_shim_libs(); ++} ++ ++template<typename F> ++static void for_each_matching_shim(const char *const path, F action) { ++ if (path == nullptr) return; ++ INFO("Finding shim libs for \"%s\"\n", path); ++ std::vector<const ShimDescriptor *> matched; ++ ++ g_active_shim_libs.for_each([&](const ShimDescriptor *a_pair) { ++ if (a_pair->first == path) { ++ matched.push_back(a_pair); ++ } ++ }); ++ ++ g_active_shim_libs.remove_if([&](const ShimDescriptor *a_pair) { ++ return a_pair->first == path; ++ }); ++ ++ for (const auto& one_pair : matched) { ++ INFO("Injecting shim lib \"%s\" as needed for %s", one_pair->second.c_str(), path); ++ action(one_pair->second.c_str()); ++ } ++} ++ + // This function walks down the tree of soinfo dependencies + // in breadth-first order and + // * calls action(soinfo* si) for each node, and +@@ -1108,6 +1170,7 @@ const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) { + + template<typename F> + static void for_each_dt_needed(const ElfReader& elf_reader, F action) { ++ for_each_matching_shim(elf_reader.name(), action); + for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) { + if (d->d_tag == DT_NEEDED) { + action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name())); +@@ -1967,6 +2030,7 @@ void* do_dlopen(const char* name, int flags, + } + + ProtectedDataGuard guard; ++ reset_g_active_shim_libs(); + soinfo* si = find_library(ns, translated_name, flags, extinfo, caller); + loading_trace.End(); + +@@ -3278,12 +3342,15 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& + #if !defined(__LP64__) + if (has_text_relocations) { + // Fail if app is targeting M or above. +- if (get_application_target_sdk_version() >= __ANDROID_API_M__) { ++#if !defined(__i386__) // ffmpeg says that they require text relocations on x86 ++ if (get_application_target_sdk_version() != __ANDROID_API__ ++ && get_application_target_sdk_version() >= __ANDROID_API_M__) { + DL_ERR_AND_LOG("\"%s\" has text relocations (https://android.googlesource.com/platform/" + "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-" + "Enforced-for-API-level-23)", get_realpath()); + return false; + } ++#endif + // Make segments writable to allow text relocations to work properly. We will later call + // phdr_table_protect_segments() after all of them are applied. + DL_WARN("\"%s\" has text relocations (https://android.googlesource.com/platform/" +diff --git a/linker/linker.h b/linker/linker.h +index 43d345c4520..2b5666ca4c6 100644 +--- a/linker/linker.h ++++ b/linker/linker.h +@@ -100,6 +100,8 @@ enum RelocationKind { + + void count_relocation(RelocationKind kind); + ++void parse_LD_SHIM_LIBS(const char* path); ++ + soinfo* get_libdl_info(const char* linker_path, const link_map& linker_map); + + soinfo* find_containing_library(const void* p); +diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp +index db369761892..fb77f22e5fb 100644 +--- a/linker/linker_main.cpp ++++ b/linker/linker_main.cpp +@@ -253,6 +253,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { + // doesn't cost us anything. + const char* ldpath_env = nullptr; + const char* ldpreload_env = nullptr; ++ const char* ldshim_libs_env = nullptr; + if (!getauxval(AT_SECURE)) { + ldpath_env = getenv("LD_LIBRARY_PATH"); + if (ldpath_env != nullptr) { +@@ -262,6 +263,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { + if (ldpreload_env != nullptr) { + INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env); + } ++ ldshim_libs_env = getenv("LD_SHIM_LIBS"); + } + + struct stat file_stat; +@@ -336,6 +338,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { + // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid). + parse_LD_LIBRARY_PATH(ldpath_env); + parse_LD_PRELOAD(ldpreload_env); ++ parse_LD_SHIM_LIBS(ldshim_libs_env); + + somain = si; + diff --git a/patches/bionic/0002-bionic-linker_forced_shim_libs.patch b/patches/bionic/0002-bionic-linker_forced_shim_libs.patch new file mode 100644 index 0000000..99636da --- /dev/null +++ b/patches/bionic/0002-bionic-linker_forced_shim_libs.patch @@ -0,0 +1,65 @@ +From 08aff0dce57252bae09f501a3b2f0b25832c48e5 Mon Sep 17 00:00:00 2001 +From: "Christopher R. Palmer" <crpalmer@gmail.com> +Date: Thu, 16 Mar 2017 21:33:27 -0400 +Subject: [PATCH] linker: Allow devices to force shim libs + +There are certain contexts in which the environment is cleansed. +Two examples that I know of are gps processes and mali gles blobs. + +Generally, it is a better idea to use the environment variable because +then you can customize it on a per-service / script level and it is +easier to test and debug changes on the fly. + +However, to avoid having libdimytry hexedit these blobs, allow a +last resort device level forced list of shim libraries. + +Change-Id: I2f6aff9325beb5aa2f748bf72e6c3c0535d5aac2 +--- + Android.mk | 4 ++++ + linker/linker.cpp | 10 +++++++++- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/Android.mk b/Android.mk +index 888404cf7..60a5db1fe 100644 +--- a/Android.mk ++++ b/Android.mk +@@ -1,4 +1,8 @@ + LOCAL_PATH := $(call my-dir) + ++ifneq ($(LINKER_FORCED_SHIM_LIBS),) ++ LOCAL_CFLAGS += -DFORCED_SHIM_LIBS="\"$(LINKER_FORCED_SHIM_LIBS)\"" ++endif ++ + include $(call all-makefiles-under,$(LOCAL_PATH)) + +diff --git a/linker/linker.cpp b/linker/linker.cpp +index 104f22325..cd114f888 100644 +--- a/linker/linker.cpp ++++ b/linker/linker.cpp +@@ -716,7 +716,7 @@ static void reset_g_active_shim_libs(void) { + } + } + +-void parse_LD_SHIM_LIBS(const char* path) { ++void parse_shim_libs(const char* path) { + g_ld_all_shim_libs.clear(); + if (path != nullptr) { + // We have historically supported ':' as well as ' ' in LD_SHIM_LIBS. +@@ -731,6 +731,14 @@ void parse_LD_SHIM_LIBS(const char* path) { + reset_g_active_shim_libs(); + } + ++void parse_LD_SHIM_LIBS(const char* path) { ++ g_ld_all_shim_libs.clear(); ++#ifdef FORCED_SHIM_LIBS ++ parse_shim_libs(FORCED_SHIM_LIBS); ++#endif ++ parse_shim_libs(path); ++} ++ + template<typename F> + static void for_each_matching_shim(const char *const path, F action) { + if (path == nullptr) return; +-- +2.11.0 + diff --git a/patches/build/make/core/0002-O-export-FORCED_SHIM_LIBS-to-Soong.patch b/patches/build/make/core/0002-O-export-FORCED_SHIM_LIBS-to-Soong.patch new file mode 100644 index 0000000..4827fa5 --- /dev/null +++ b/patches/build/make/core/0002-O-export-FORCED_SHIM_LIBS-to-Soong.patch @@ -0,0 +1,25 @@ +From e58e067d4dcc608f5e4a39abfdb3c344477dcad5 Mon Sep 17 00:00:00 2001 +From: Mister Oyster <oysterized@gmail.com> +Date: Wed, 28 Jun 2017 21:24:51 +0200 +Subject: [PATCH] O: export FORCED_SHIM_LIBS to Soong + +Change-Id: Iec2e6bb8a9c53693d90088f9c37c011687c78d28 +--- + core/soong_config.mk | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/core/soong_config.mk b/core/soong_config.mk +index 9cda3b109..7c90c8b80 100644 +--- a/core/soong_config.mk ++++ b/core/soong_config.mk +@@ -82,6 +82,7 @@ $(SOONG_VARIABLES): FORCE + echo ''; \ + echo ' "ArtUseReadBarrier": $(if $(filter false,$(PRODUCT_ART_USE_READ_BARRIER)),false,true),'; \ + echo ''; \ ++ echo ' "ForcedShimLibs": "$(LINKER_FORCED_SHIM_LIBS)",'; \ + echo ' "BtConfigIncludeDir": "$(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)"'; \ + echo '}') > $(SOONG_VARIABLES_TMP); \ + if ! cmp -s $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); then \ +-- +2.11.0 + diff --git a/patches/build/soong/0001-O-add-LINKER_FORCED_SHIM_LIBS-to-Soong.patch b/patches/build/soong/0001-O-add-LINKER_FORCED_SHIM_LIBS-to-Soong.patch new file mode 100644 index 0000000..5e45369 --- /dev/null +++ b/patches/build/soong/0001-O-add-LINKER_FORCED_SHIM_LIBS-to-Soong.patch @@ -0,0 +1,41 @@ +From 4e9a6f3dd8c1044658dc2f3d3ad3f7c3edb5f3b6 Mon Sep 17 00:00:00 2001 +From: Mister Oyster <oysterized@gmail.com> +Date: Wed, 28 Jun 2017 20:59:47 +0200 +Subject: [PATCH] O: add LINKER_FORCED_SHIM_LIBS to Soong + +Change-Id: I996ba7475fc8b7d5ec7cb3899060b1e625f97cdf +--- + android/config.go | 4 ++++ + android/variable.go | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/android/config.go b/android/config.go +index 8be16cf..f692cd3 100644 +--- a/android/config.go ++++ b/android/config.go +@@ -486,6 +486,10 @@ func (c *deviceConfig) BtConfigIncludeDir() string { + return String(c.config.ProductVariables.BtConfigIncludeDir) + } + ++func (c *deviceConfig) ForcedShimLibs() string { ++ return String(c.config.ProductVariables.ForcedShimLibs) ++ } ++ + func (c *deviceConfig) NativeCoverageEnabled() bool { + return Bool(c.config.ProductVariables.NativeCoverage) + } +diff --git a/android/variable.go b/android/variable.go +index 3d5e618..dcb3c42 100644 +--- a/android/variable.go ++++ b/android/variable.go +@@ -141,6 +141,7 @@ type productVariables struct { + ArtUseReadBarrier *bool `json:",omitempty"` + + BtConfigIncludeDir *string `json:",omitempty"` ++ ForcedShimLibs *string `json:",omitempty"` + } + + func boolPtr(v bool) *bool { +-- +2.11.0 + diff --git a/patches/install.sh b/patches/install.sh index cf6d18d..f9addc9 100644 --- a/patches/install.sh +++ b/patches/install.sh @@ -4,7 +4,7 @@ echo $1 rootdirectory="$PWD" # --------------------------------- -dirs="build/make/core build/soong system/core" +dirs="bionic build/make/core build/soong system/core" # red + nocolor RED='\033[0;31m' diff --git a/patches/uninstall.sh b/patches/uninstall.sh index d3d1448..1819211 100644 --- a/patches/uninstall.sh +++ b/patches/uninstall.sh @@ -4,7 +4,7 @@ echo $1 rootdirectory="$PWD" # --------------------------------- -dirs="build/make/core build/soong system/core" +dirs="bionic build/make/core build/soong system/core" for dir in $dirs ; do cd $rootdirectory |
