From 23ea813c50e539c03f847294eb90d6d2c86f8e2e Mon Sep 17 00:00:00 2001 From: Christian Gagneraud Date: Thu, 7 Mar 2019 14:48:46 +0100 Subject: [PATCH 1/3] PreloadInjector: Modernise use of foreach --- launcher/core/injector/preloadinjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/core/injector/preloadinjector.cpp b/launcher/core/injector/preloadinjector.cpp index ec2b1bc1ad..58053daafd 100644 --- a/launcher/core/injector/preloadinjector.cpp +++ b/launcher/core/injector/preloadinjector.cpp @@ -68,7 +68,7 @@ bool PreloadInjector::launch(const QStringList &programAndArgs, const QString &p // ASAN requires to be loaded first, so check if the target uses that // and if so inject it before GammaRay QStringList ldPreload; - foreach (const auto &lib, LibraryUtil::dependencies(exePath)) { + for (const auto &lib: LibraryUtil::dependencies(exePath)) { if (lib.contains("libasan.so") || lib.contains("libclang_rt.asan")) { ldPreload.push_back(QString::fromLocal8Bit(lib)); break; From 36ad06165def4f7a25fa84533c8bf2dfb062b191 Mon Sep 17 00:00:00 2001 From: Christian Gagneraud Date: Thu, 7 Mar 2019 14:49:20 +0100 Subject: [PATCH 2/3] PreloadInjector: Honor launcher's injector-override option This allow to overwrite the LD_PRELOAD, which can be useful when ld.so is in secure-execution mode. See https://mail.kdab.com/pipermail/gammaray-interest/2019-March/000317.html --- launcher/core/injector/injectorfactory.cpp | 2 +- launcher/core/injector/preloadinjector.cpp | 14 ++++++++++---- launcher/core/injector/preloadinjector.h | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/launcher/core/injector/injectorfactory.cpp b/launcher/core/injector/injectorfactory.cpp index 26bf4b875a..264b4b7980 100644 --- a/launcher/core/injector/injectorfactory.cpp +++ b/launcher/core/injector/injectorfactory.cpp @@ -62,7 +62,7 @@ AbstractInjector::Ptr createInjector(const QString &name, const QString &executa #ifndef Q_OS_WIN if (name == QLatin1String("preload")) { - return AbstractInjector::Ptr(new PreloadInjector); + return AbstractInjector::Ptr(new PreloadInjector(executableOverride)); } #else if (name == QLatin1String("windll")) { diff --git a/launcher/core/injector/preloadinjector.cpp b/launcher/core/injector/preloadinjector.cpp index 58053daafd..26630a35cd 100644 --- a/launcher/core/injector/preloadinjector.cpp +++ b/launcher/core/injector/preloadinjector.cpp @@ -39,7 +39,11 @@ using namespace GammaRay; -PreloadInjector::PreloadInjector() = default; +PreloadInjector::PreloadInjector(const QString &probeDllOverride) + : ProcessInjector() + , m_probeDllOverride(probeDllOverride) +{ +} QString PreloadInjector::name() const { @@ -51,13 +55,15 @@ bool PreloadInjector::launch(const QStringList &programAndArgs, const QString &p { Q_UNUSED(probeFunc); + const QString actualProbeDll = m_probeDllOverride.isEmpty() ? probeDll : m_probeDllOverride; + QProcessEnvironment env(_env); #ifdef Q_OS_MAC - env.insert(QStringLiteral("DYLD_INSERT_LIBRARIES"), probeDll); + env.insert(QStringLiteral("DYLD_INSERT_LIBRARIES"), actualProbeDll); env.insert(QStringLiteral("GAMMARAY_UNSET_DYLD"), QStringLiteral("1")); // Make sure Qt do load it's correct libs/plugins. - if (probeDll.contains(QStringLiteral("_debug"), Qt::CaseInsensitive)) + if (actualProbeDll.contains(QStringLiteral("_debug"), Qt::CaseInsensitive)) env.insert(QStringLiteral("DYLD_IMAGE_SUFFIX"), QStringLiteral("_debug")); #else @@ -74,7 +80,7 @@ bool PreloadInjector::launch(const QStringList &programAndArgs, const QString &p break; } } - ldPreload.push_back(probeDll); + ldPreload.push_back(actualProbeDll); env.insert(QStringLiteral("LD_PRELOAD"), ldPreload.join(QLatin1String(":"))); env.insert(QStringLiteral("GAMMARAY_UNSET_PRELOAD"), QStringLiteral("1")); diff --git a/launcher/core/injector/preloadinjector.h b/launcher/core/injector/preloadinjector.h index 34daf5d78b..6f366bfe12 100644 --- a/launcher/core/injector/preloadinjector.h +++ b/launcher/core/injector/preloadinjector.h @@ -37,10 +37,13 @@ class PreloadInjector : public ProcessInjector { Q_OBJECT public: - PreloadInjector(); + PreloadInjector(const QString &probeDllOverride = QString()); QString name() const override; bool launch(const QStringList &programAndArgs, const QString &probeDll, const QString &probeFunc, const QProcessEnvironment &_env) override; + +private: + const QString m_probeDllOverride; }; } From 0be80c2c7da35be205e833292823eeb7b17bd980 Mon Sep 17 00:00:00 2001 From: Christian Gagneraud Date: Thu, 7 Mar 2019 15:51:29 +0100 Subject: [PATCH 3/3] PreloadInjector: Update User's Manual --- docs/manual/gammaray-advanced-usage.qdoc | 11 +++++++++++ docs/manual/gammaray-command-line.qdoc | 3 +++ 2 files changed, 14 insertions(+) diff --git a/docs/manual/gammaray-advanced-usage.qdoc b/docs/manual/gammaray-advanced-usage.qdoc index b19c04018b..ad618e6641 100644 --- a/docs/manual/gammaray-advanced-usage.qdoc +++ b/docs/manual/gammaray-advanced-usage.qdoc @@ -66,4 +66,15 @@ For more details on how to integrate the GammaRay client with and IDE, please see the \l{https://docs.kdab.com/gammaray/latest/}{API documentation}. + + \section1 Working around \c{ld.so} secure-execution mode (Linux only) + + If your environment triggers the dynamic linker's secure-execution + mode, then the default \c{preload} injector will fail. In that + case, you can copy or link \c{gammaray_probe.so} into a standard + search directory (eg. \c{/usr/lib}), enable the set-user-ID mode + bit (eg. \c{chmod u+s /usr/lib/gammaray_probe.so}), and finally + use the \c{--injector-override gammaray_probe.so} + + For more information about \c{ld.so}'s secure mode, see the \l{http://man7.org/linux/man-pages/man8/ld.so.8.html#ENVIRONMENT}{man page} */ diff --git a/docs/manual/gammaray-command-line.qdoc b/docs/manual/gammaray-command-line.qdoc index 2cb304dc8f..d167675928 100644 --- a/docs/manual/gammaray-command-line.qdoc +++ b/docs/manual/gammaray-command-line.qdoc @@ -56,6 +56,9 @@ \row \li \c -i, \c --injector \c \li Specify injector type to use (see below). + \row + \li \c -o, \c --injector-override \c + \li Override the injector executable if handled (requires \c{-i/--injector}) \row \li \c --inprocess \li Use the Gammaray 1.x in-process UI. This is not necessary in most cases,