Commit ba254c4e authored by spang's avatar spang Committed by Commit bot

crypto: Load libchaps.so with RTLD_DEEPBIND

This fixes the component=shared_library build on Chrome OS. Previously,
the TPM token initialization would crash the browser because libchaps.so
loads a 2nd, incompatible copy of the protobuf-lite library into the
browser.

The crash happens because by default the global scope takes precedence,
so symbols in the bundled copy shadow symbols in the system copy. This
can lead to accessing the wrong object or calling the wrong function.
The usual symptom is a crash during static initialization of libchaps.so.

RTL_DEEPBIND rearranges the scope for libchaps.so so that the system
library takes precedence instead. The scope for chrome is unaffected.

Some other possibilities were considered:

  - Unbundling the library. This would cause us to lose our local
    modifications to libprotobuf on Chrome OS.

  - Fixing the soname so that the bundled copy is used by chaps. This
    doesn't even link because the bundled code is not ABI compatible
    with upstream.

  - Statically linking libchaps.so. This is tricky because we need
    position-independent static libs for its deps, and we don't support
    building those currently. It will also cause bloat.

This hack is minimally invasive and allows use of shared library builds
on Chrome OS devices.

BUG=175508
TEST=cros chrome-sdk --board=link
  GYP_DEFINES="$GYP_DEFINES component=shared_library" gclient runhooks
  ninja -C out_link/Release chrome chrome-sandbox
  deploy_chrome --board link --build-dir out_link/Release --to $IP
  Log into the system. No crash.
  TPM-backed user certs show up in chrome://certificate-manager.

Review URL: https://codereview.chromium.org/1111373003

Cr-Commit-Position: refs/heads/master@{#329743}
parent 3c6d7afb
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include <sys/param.h> #include <sys/param.h>
#endif #endif
#if defined(OS_CHROMEOS)
#include <dlfcn.h>
#endif
#include <map> #include <map>
#include <vector> #include <vector>
...@@ -267,6 +271,38 @@ class ChromeOSUserData { ...@@ -267,6 +271,38 @@ class ChromeOSUserData {
SlotReadyCallbackList; SlotReadyCallbackList;
SlotReadyCallbackList tpm_ready_callback_list_; SlotReadyCallbackList tpm_ready_callback_list_;
}; };
class ScopedChapsLoadFixup {
public:
ScopedChapsLoadFixup();
~ScopedChapsLoadFixup();
private:
#if defined(COMPONENT_BUILD)
void *chaps_handle_;
#endif
};
#if defined(COMPONENT_BUILD)
ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
// HACK: libchaps links the system protobuf and there are symbol conflicts
// with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
}
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
// LoadModule() will have taken a 2nd reference.
if (chaps_handle_)
dlclose(chaps_handle_);
}
#else
ScopedChapsLoadFixup::ScopedChapsLoadFixup() {}
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {}
#endif // defined(COMPONENT_BUILD)
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
class NSSInitSingleton { class NSSInitSingleton {
...@@ -360,6 +396,8 @@ class NSSInitSingleton { ...@@ -360,6 +396,8 @@ class NSSInitSingleton {
// This tries to load the Chaps module so NSS can talk to the hardware // This tries to load the Chaps module so NSS can talk to the hardware
// TPM. // TPM.
if (!tpm_args->chaps_module) { if (!tpm_args->chaps_module) {
ScopedChapsLoadFixup chaps_loader;
DVLOG(3) << "Loading chaps..."; DVLOG(3) << "Loading chaps...";
tpm_args->chaps_module = LoadModule( tpm_args->chaps_module = LoadModule(
kChapsModuleName, kChapsModuleName,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment