From c22e7c57c27ce64d01b8d0dde4a889864fb5b166 Mon Sep 17 00:00:00 2001 From: Gabriele Svelto Date: Wed, 10 May 2023 16:33:07 +0000 Subject: [PATCH] Bug 1752703 - Move the pthread_thread_create() interposer under mozglue and prepare for having a single place where we place interposer functions r=glandium Differential Revision: https://phabricator.services.mozilla.com/D164470 --- browser/app/moz.build | 5 -- ipc/app/moz.build | 5 -- js/src/make-source-package.py | 1 + js/xpconnect/shell/moz.build | 5 -- mozglue/interposers/InterposerHelper.h | 66 +++++++++++++++++++ mozglue/interposers/moz.build | 20 ++++++ .../pthread_create_interposer.cpp | 27 ++------ mozglue/moz.build | 3 + toolkit/crashreporter/moz.build | 1 - .../pthread_create_interposer/moz.build | 12 ---- 10 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 mozglue/interposers/InterposerHelper.h create mode 100644 mozglue/interposers/moz.build rename {toolkit/crashreporter/pthread_create_interposer => mozglue/interposers}/pthread_create_interposer.cpp (76%) delete mode 100644 toolkit/crashreporter/pthread_create_interposer/moz.build diff --git a/browser/app/moz.build b/browser/app/moz.build index be6748dfcbab..fcf98d6d48bf 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -53,11 +53,6 @@ LOCAL_INCLUDES += [ "/xpcom/build", ] -# The pthred_create() interposer needs to be linked as early as possible so -# that it will appear before libpthread when resolving symbols. -if CONFIG["OS_ARCH"] == "Linux" and CONFIG["MOZ_CRASHREPORTER"]: - USE_LIBS += ["pthread_create_interposer"] - if CONFIG["LIBFUZZER"]: USE_LIBS += ["fuzzer"] LOCAL_INCLUDES += [ diff --git a/ipc/app/moz.build b/ipc/app/moz.build index de426b54499b..afe1df122b27 100644 --- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -16,11 +16,6 @@ else: "MozillaRuntimeMain.cpp", ] -# The pthred_create() interposer needs to be linked as early as possible so -# that it will appear before libpthread when resolving symbols. -if CONFIG["OS_ARCH"] == "Linux" and CONFIG["MOZ_CRASHREPORTER"]: - USE_LIBS += ["pthread_create_interposer"] - include("/ipc/chromium/chromium-config.mozbuild") LOCAL_INCLUDES += [ diff --git a/js/src/make-source-package.py b/js/src/make-source-package.py index 3909ec7ba3f8..5a42ff160204 100755 --- a/js/src/make-source-package.py +++ b/js/src/make-source-package.py @@ -155,6 +155,7 @@ rsync_filter_list = """ + /mozglue/baseprofiler/** + /mozglue/build/** ++ /mozglue/interposers/** + /mozglue/misc/** + /mozglue/moz.build + /mozglue/static/** diff --git a/js/xpconnect/shell/moz.build b/js/xpconnect/shell/moz.build index 8a270fecfb08..de3b050b7972 100644 --- a/js/xpconnect/shell/moz.build +++ b/js/xpconnect/shell/moz.build @@ -10,11 +10,6 @@ SOURCES += [ "xpcshell.cpp", ] -# The pthred_create() interposer needs to be linked as early as possible so -# that it will appear before libpthread when resolving symbols. -if CONFIG["OS_ARCH"] == "Linux" and CONFIG["MOZ_CRASHREPORTER"]: - USE_LIBS += ["pthread_create_interposer"] - if CONFIG["LIBFUZZER"]: USE_LIBS += ["fuzzer"] diff --git a/mozglue/interposers/InterposerHelper.h b/mozglue/interposers/InterposerHelper.h new file mode 100644 index 000000000000..3277dd6a2d37 --- /dev/null +++ b/mozglue/interposers/InterposerHelper.h @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef InterposerHelper_h +#define InterposerHelper_h + +#include + +#ifdef MOZ_LINKER +# include "Linker.h" +#else +# include +#endif + +#include "mozilla/Assertions.h" + +template +static inline T dlsym_wrapper(void* aHandle, const char* aName) { +#ifdef MOZ_LINKER + return reinterpret_cast(__wrap_dlsym(aHandle, aName)); +#else + return reinterpret_cast(dlsym(aHandle, aName)); +#endif // MOZ_LINKER +} + +template +static T get_real_symbol(const char* aName, T aReplacementSymbol) { + // T can only be a function pointer + static_assert(std::is_function::type>::value); + + // Find the corresponding function in the linked libraries + T real_symbol = dlsym_wrapper(RTLD_NEXT, aName); + +#if defined(ANDROID) + if (real_symbol == nullptr) { + // On old versions of Android the application runtime links in libc before + // we get a chance to link libmozglue, so its symbols don't appear when + // resolving them with RTLD_NEXT but rather with RTLD_DEFAULT. If RTLD_NEXT + // failed to find a symbol we try again with RTLD_DEFAULT. The checks below + // make sure that we crash in case the symbol we get matches the + // replacement one so this is safe albeit a bit weird. + real_symbol = dlsym_wrapper(RTLD_DEFAULT, aName); + } +#endif + + if (real_symbol == nullptr) { + MOZ_CRASH_UNSAFE_PRINTF( + "%s() interposition failed but the interposer function is " + "still being called, this won't work!", + aName); + } + + if (real_symbol == aReplacementSymbol) { + MOZ_CRASH_UNSAFE_PRINTF( + "We could not obtain the real %s(). Calling the symbol we " + "got would make us enter an infinite loop so stop here instead.", + aName); + } + + return real_symbol; +} + +#define GET_REAL_SYMBOL(name) get_real_symbol(#name, name) + +#endif // InterposerHelper_h diff --git a/mozglue/interposers/moz.build b/mozglue/interposers/moz.build new file mode 100644 index 000000000000..36c49670089b --- /dev/null +++ b/mozglue/interposers/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +Library("interposers") + +DEFINES["IMPL_MFBT"] = True + +if CONFIG["MOZ_CRASHREPORTER"]: + UNIFIED_SOURCES += [ + "pthread_create_interposer.cpp", + ] + +if CONFIG["MOZ_LINKER"] and CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": + LOCAL_INCLUDES += [ + "/mozglue/linker", + ] + +FINAL_LIBRARY = "mozglue" diff --git a/toolkit/crashreporter/pthread_create_interposer/pthread_create_interposer.cpp b/mozglue/interposers/pthread_create_interposer.cpp similarity index 76% rename from toolkit/crashreporter/pthread_create_interposer/pthread_create_interposer.cpp rename to mozglue/interposers/pthread_create_interposer.cpp index e3ba6b164f70..65f60c2d1bfd 100644 --- a/toolkit/crashreporter/pthread_create_interposer/pthread_create_interposer.cpp +++ b/mozglue/interposers/pthread_create_interposer.cpp @@ -4,7 +4,6 @@ #include -#include #include #include #include @@ -13,6 +12,8 @@ #include "mozilla/Assertions.h" #include "mozilla/DebugOnly.h" +#include "InterposerHelper.h" + using mozilla::DebugOnly; struct SigAltStack { @@ -83,30 +84,12 @@ void* set_alt_signal_stack_and_start(PthreadCreateParams* params) { return thread_rv; } -using pthread_create_func_t = int (*)(pthread_t*, const pthread_attr_t*, - void* (*)(void*), void*); - extern "C" { // This interposer replaces libpthread's pthread_create() so that we can // inject an alternate signal stack in every new thread. -__attribute__((visibility("default"))) int pthread_create( - pthread_t* thread, const pthread_attr_t* attr, - void* (*start_routine)(void*), void* arg) { - // static const pthread_create_func_t real_pthread_create = - static const pthread_create_func_t real_pthread_create = - (pthread_create_func_t)dlsym(RTLD_NEXT, "pthread_create"); - - if (real_pthread_create == nullptr) { - MOZ_CRASH( - "pthread_create() interposition failed but the interposer function is " - "still being called, this won't work!"); - } - - if (real_pthread_create == pthread_create) { - MOZ_CRASH( - "We could not obtain the real pthread_create(). Calling the symbol we " - "got would make us enter an infinte loop so stop here instead."); - } +MFBT_API int pthread_create(pthread_t* thread, const pthread_attr_t* attr, + void* (*start_routine)(void*), void* arg) { + static const auto real_pthread_create = GET_REAL_SYMBOL(pthread_create); PthreadCreateParams* params = (PthreadCreateParams*)malloc(sizeof(PthreadCreateParams)); diff --git a/mozglue/moz.build b/mozglue/moz.build index 75e14589ca57..a8288b0ce3d9 100644 --- a/mozglue/moz.build +++ b/mozglue/moz.build @@ -13,6 +13,9 @@ if CONFIG["MOZ_LINKER"] or CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": if CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": DIRS += ["android"] +if CONFIG["OS_ARCH"] == "Linux": + DIRS += ["interposers"] + DIRS += [ "baseprofiler", "build", diff --git a/toolkit/crashreporter/moz.build b/toolkit/crashreporter/moz.build index c78344d9d81d..4e3b77caa7f8 100644 --- a/toolkit/crashreporter/moz.build +++ b/toolkit/crashreporter/moz.build @@ -53,7 +53,6 @@ if CONFIG["MOZ_CRASHREPORTER"]: "google-breakpad/src/common", "google-breakpad/src/common/linux", "google-breakpad/src/processor", - "pthread_create_interposer", ] if CONFIG["MOZ_OXIDIZED_BREAKPAD"]: diff --git a/toolkit/crashreporter/pthread_create_interposer/moz.build b/toolkit/crashreporter/pthread_create_interposer/moz.build deleted file mode 100644 index d0ff4cae007a..000000000000 --- a/toolkit/crashreporter/pthread_create_interposer/moz.build +++ /dev/null @@ -1,12 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -Library("pthread_create_interposer") - -NoVisibilityFlags() - -UNIFIED_SOURCES += [ - "pthread_create_interposer.cpp", -]