Close a window for a race with the system linker
commitcd5c4353b052baa4d96925cb46f47e16a697f0e1
authorsimonb <simonb@chromium.org>
Fri, 20 Feb 2015 14:15:33 +0000 (20 06:15 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 20 Feb 2015 14:16:28 +0000 (20 14:16 +0000)
treea2ded56ea72f4801b92c56b3eac06e949d6b3ae3
parent244c761f6ef763dabf708ac6794afd39b1ea7b5e
Close a window for a race with the system linker

Lock globals at the head of Add/DelEntryImpl() callback handlers.

  The crazy linker exports updates to _r_debug pages to the UI thread
  if a callback poster function has been supplied.  At the time the
  callback is posted, the crazy linker holds the globals lock, used to
  prevent other threads from loading libraries (in particular through
  ::dlopen(), used for system libraries).  When the callback is
  received on a different thread the receiving code needs to reacquire
  the lock.

Make the globals lock reentrant.

  If there is no callback poster function then the updates to _r_debug
  pages happen immediately on the current thread.  Here the globals
  lock is already held.  Reentrancy ensures that we do not deadlock
  in that case.

Fix potential inaccuracy when looking for the page to mprotect.

  The addresses checked for writability are currently the start of the
  object being modified.  This is 12 or 16 bytes (on arm, 24 or 32
  bytes on arm64) below the address that will actually be written, and
  not guaranteed to be in the same memory page where the object
  crosses a page boundary.

Workround for races with the system linker over _r_debug protections.

  There is no way to safely and accurately sense whether _r_debug is
  in a readonly page -- we might read while the system linker is in
  the process of writing to it, and conclude that it is not readonly
  when it is.  Similarly, we may set it read/write, update pointers,
  and then set it readonly between the system linker setting it to
  read/write and updating pointers.  To work round this, we always map
  it to read/write, no matter its apparent initial state, and never
  map it back to readonly.  This may leave a small security hole, but
  it is better than the alternatives (typically, a crash).

BUG=450659,458346

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

Cr-Commit-Position: refs/heads/master@{#317314}
third_party/android_crazy_linker/README.chromium
third_party/android_crazy_linker/src/src/crazy_linker_globals.cpp
third_party/android_crazy_linker/src/src/crazy_linker_rdebug.cpp
third_party/android_crazy_linker/src/src/crazy_linker_rdebug.h