18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)package org.chromium.content.app;
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)import android.os.Bundle;
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)import android.os.Parcel;
98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)import android.os.ParcelFileDescriptor;
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import android.os.Parcelable;
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)import android.util.Log;
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import org.chromium.base.SysUtils;
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.io.File;
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.io.FileInputStream;
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.util.HashMap;
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.util.Map;
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)/*
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Technical note:
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * The point of this class is to provide an alternative to System.loadLibrary()
248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * to load native shared libraries. One specific feature that it supports is the
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * ability to save RAM by sharing the ELF RELRO sections between renderer
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * processes.
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * When two processes load the same native library at the _same_ memory address,
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * the content of their RELRO section (which includes C++ vtables or any
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * constants that contain pointers) will be largely identical [1].
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * By default, the RELRO section is backed by private RAM in each process,
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * which is still significant on mobile (e.g. 1.28 MB / process on Chrome 30 for
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Android).
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * However, it is possible to save RAM by creating a shared memory region,
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * copy the RELRO content into it, then have each process swap its private,
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * regular RELRO, with a shared, read-only, mapping of the shared one.
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * This trick saves 98% of the RELRO section size per extra process, after the
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * first one. On the other hand, this requires careful communication between
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * the process where the shared RELRO is created and the one(s) where it is used.
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Note that swapping the regular RELRO with the shared one is not an atomic
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * operation. Care must be taken that no other thread tries to run native code
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * that accesses it during it. In practice, this means the swap must happen
478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * before library native code is executed.
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * [1] The exceptions are pointers to external, randomized, symbols, like
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * those from some system libraries, but these are very few in practice.
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) */
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)/*
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Security considerations:
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - Whether the browser process loads its native libraries at the same
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   addresses as the service ones (to save RAM by sharing the RELRO too)
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   depends on the configuration variable BROWSER_SHARED_RELRO_CONFIG below.
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   Not using fixed library addresses in the browser process is preferred
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   for regular devices since it maintains the efficacy of ASLR as an
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   exploit mitigation across the render <-> browser privilege boundary.
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - The shared RELRO memory region is always forced read-only after creation,
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   which means it is impossible for a compromised service process to map
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   it read-write (e.g. by calling mmap() or mprotect()) and modify its
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   content, altering values seen in other service processes.
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - Unfortunately, certain Android systems use an old, buggy kernel, that
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   doesn't check Ashmem region permissions correctly. See CVE-2011-1149
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   for details. This linker probes the system on startup and will completely
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   disable shared RELROs if it detects the problem. For the record, this is
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   common for Android emulator system images (which are still based on 2.6.29)
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - Once the RELRO ashmem region is mapped into a service process' address
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   space, the corresponding file descriptor is immediately closed. The
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   file descriptor is kept opened in the browser process, because a copy needs
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   to be sent to each new potential service process.
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - The common library load addresses are randomized for each instance of
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   the program on the device. See computeRandomBaseLoadAddress() for more
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   details on how this is computed.
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * - When loading several libraries in service processes, a simple incremental
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   approach from the original random base load address is used. This is
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   sufficient to deal correctly with component builds (which can use dozens
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   of shared libraries), while regular builds always embed a single shared
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *   library per APK.
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) */
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/**
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Here's an explanation of how this class is supposed to be used:
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - Native shared libraries should be loaded with Linker.loadLibrary(),
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    instead of System.loadLibrary(). The two functions take the same parameter
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    and should behave the same (at a high level).
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - Before loading any library, prepareLibraryLoad() should be called.
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - After loading all libraries, finishLibraryLoad() should be called, before
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    running any native code from any of the libraries (except their static
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    constructors, which can't be avoided).
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - A service process shall call either initServiceProcess() or
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    disableSharedRelros() early (i.e. before any loadLibrary() call).
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    Otherwise, the linker considers that it is running inside the browser
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    process. This is because various content-based projects have vastly
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    different initialization paths.
1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    disableSharedRelros() completely disables shared RELROs, and loadLibrary()
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    will behave exactly like System.loadLibrary().
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    initServiceProcess(baseLoadAddress) indicates that shared RELROs are to be
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    used in this process.
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - The browser is in charge of deciding where in memory each library should
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    be loaded. This address must be passed to each service process (see
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    LinkerParams.java for a helper class to do so).
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - The browser will also generate shared RELROs for each library it loads.
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    More specifically, by default when in the browser process, the linker
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    will:
1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *       - Load libraries randomly (just like System.loadLibrary()).
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *       - Compute the fixed address to be used to load the same library
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *         in service processes.
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *       - Create a shared memory region populated with the RELRO region
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *         content pre-relocated for the specific fixed address above.
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    Note that these shared RELRO regions cannot be used inside the browser
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    process. They are also never mapped into it.
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    This behaviour is altered by the BROWSER_SHARED_RELRO_CONFIG configuration
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    variable below, which may force the browser to load the libraries at
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    fixed addresses to.
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - Once all libraries are loaded in the browser process, one can call
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    getSharedRelros() which returns a Bundle instance containing a map that
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    links each loaded library to its shared RELRO region.
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    This Bundle must be passed to each service process, for example through
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    a Binder call (note that the Bundle includes file descriptors and cannot
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    be added as an Intent extra).
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *  - In a service process, finishLibraryLoad() will block until the RELRO
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    section Bundle is received. This is typically done by calling
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    useSharedRelros() from another thread.
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *    This method also ensures the process uses the shared RELROs.
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) */
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)public class Linker {
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Log tag for this class. This must match the name of the linker's native library.
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static final String TAG = "content_android_linker";
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Set to true to enable debug logs.
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static final boolean DEBUG = false;
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Constants used to control the behaviour of the browser process with
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // regards to the shared RELRO section.
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   NEVER        -> The browser never uses it itself.
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   LOW_RAM_ONLY -> It is only used on devices with low RAM.
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   ALWAYS       -> It is always used.
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // NOTE: These names are known and expected by the Linker test scripts.
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int BROWSER_SHARED_RELRO_CONFIG_NEVER = 0;
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY = 1;
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int BROWSER_SHARED_RELRO_CONFIG_ALWAYS = 2;
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Configuration variable used to control how the browser process uses the
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // shared RELRO. Only change this while debugging linker-related issues.
1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // NOTE: This variable's name is known and expected by the Linker test scripts.
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int BROWSER_SHARED_RELRO_CONFIG =
1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            BROWSER_SHARED_RELRO_CONFIG_ALWAYS;
1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Constants used to control the value of sMemoryDeviceConfig.
1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   INIT         -> Value is undetermined (will check at runtime).
1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   LOW          -> This is a low-memory device.
1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    //   NORMAL       -> This is not a low-memory device.
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int MEMORY_DEVICE_CONFIG_INIT = 0;
1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int MEMORY_DEVICE_CONFIG_LOW = 1;
1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final int MEMORY_DEVICE_CONFIG_NORMAL = 2;
1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Indicates if this is a low-memory device or not. The default is to
1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // determine this by probing the system at runtime, but this can be forced
1858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // for testing by calling setMemoryDeviceConfig().
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static int sMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT;
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Becomes true after linker initialization.
1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sInitialized = false;
1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Set to true to indicate that the system supports safe sharing of RELRO sections.
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sRelroSharingSupported = false;
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Set to true if this runs in the browser process. Disabled by initServiceProcess().
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sInBrowserProcess = true;
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Becomes true to indicate this process needs to wait for a shared RELRO in
1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // finishLibraryLoad().
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sWaitForSharedRelros = false;
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Becomes true when initialization determines that the browser process can use the
2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // shared RELRO.
2038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sBrowserUsesSharedRelro = false;
2048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // The map of all RELRO sections either created or used in this process.
2068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static Bundle sSharedRelros = null;
2078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Current common random base load address.
2098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static long sBaseLoadAddress = 0;
2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Current fixed-location load address for the next library called by loadLibrary().
2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static long sCurrentLoadAddress = 0;
2138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Becomes true if any library fails to load at a given, non-0, fixed address.
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sLoadAtFixedAddressFailed = false;
2168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Becomes true once prepareLibraryLoad() has been called.
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sPrepareLibraryLoadCalled = false;
2198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Used internally to initialize the linker's static data. Assume lock is held.
2218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static void ensureInitializedLocked() {
2228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert Thread.holdsLock(Linker.class);
2238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!sInitialized) {
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sRelroSharingSupported = false;
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (NativeLibraries.USE_LINKER) {
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "Loading lib" + TAG + ".so");
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                try {
2298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    System.loadLibrary(TAG);
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                } catch (UnsatisfiedLinkError  e) {
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    // In a component build, the ".cr" suffix is added to each library name.
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    System.loadLibrary(TAG + ".cr");
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sRelroSharingSupported = nativeCanUseSharedRelro();
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (!sRelroSharingSupported)
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.w(TAG, "This system cannot safely share RELRO sections");
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                else {
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    if (DEBUG) Log.i(TAG, "This system supports safe shared RELRO sections");
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) {
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    sMemoryDeviceConfig = SysUtils.isLowEndDevice() ?
2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL;
2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                switch (BROWSER_SHARED_RELRO_CONFIG) {
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    case BROWSER_SHARED_RELRO_CONFIG_NEVER:
2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        sBrowserUsesSharedRelro = false;
2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        break;
2508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY:
2518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        sBrowserUsesSharedRelro =
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW);
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        if (sBrowserUsesSharedRelro)
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            Log.w(TAG, "Low-memory device: shared RELROs used in all processes");
2558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        break;
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    case BROWSER_SHARED_RELRO_CONFIG_ALWAYS:
2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        Log.w(TAG, "Beware: shared RELROs used in all processes!");
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        sBrowserUsesSharedRelro = true;
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        break;
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    default:
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        assert false : "Unreached";
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        break;
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            } else {
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "Linker disabled");
2668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
2678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (!sRelroSharingSupported) {
2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Sanity.
2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sBrowserUsesSharedRelro = false;
2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sWaitForSharedRelros = false;
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
2738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sInitialized = true;
2758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * A public interface used to run runtime linker tests after loading
2808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * libraries. Should only be used to implement the linker unit tests,
2818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * which is controlled by the value of NativeLibraries.ENABLE_LINKER_TESTS
2828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * configured at build time.
2838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public interface TestRunner {
2858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        /**
2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         * Run runtime checks and return true if they all pass.
2878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         * @param memoryDeviceConfig The current memory device configuration.
2888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         * @param inBrowserProcess true iff this is the browser process.
2898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         */
2908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public boolean runChecks(int memoryDeviceConfig, boolean inBrowserProcess);
2918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // The name of a class that implements TestRunner.
2948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    static String sTestRunnerClassName = null;
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
2978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Set the TestRunner by its class name. It will be instantiated at
2988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * runtime after all libraries are loaded.
2998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param testRunnerClassName null or a String for the class name of the
3008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * TestRunner to use.
3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void setTestRunnerClassName(String testRunnerClassName) {
3038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "setTestRunnerByClassName(" + testRunnerClassName + ") called");
3048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!NativeLibraries.ENABLE_LINKER_TESTS) {
3068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Ignore this in production code to prevent malvolent runtime injection.
3078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return;
3088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            assert sTestRunnerClassName == null;
3128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sTestRunnerClassName = testRunnerClassName;
3138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this to retrieve the name of the current TestRunner class name
3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * if any. This can be useful to pass it from the browser process to
3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * child ones.
3208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return null or a String holding the name of the class implementing
3218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * the TestRunner set by calling setTestRunnerClassName() previously.
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static String getTestRunnerClassName() {
3248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return sTestRunnerClassName;
3268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method before any other Linker method to force a specific
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * memory device configuration. Should only be used for testing.
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * @param memoryDeviceConfig either MEMORY_DEVICE_CONFIG_LOW or MEMORY_DEVICE_CONFIG_NORMAL.
3338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
3348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void setMemoryDeviceConfig(int memoryDeviceConfig) {
3358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "setMemoryDeviceConfig(" + memoryDeviceConfig + ") called");
3368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Sanity check. This method should only be called during tests.
3378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert NativeLibraries.ENABLE_LINKER_TESTS;
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            assert sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT;
3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            assert memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW ||
3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL;
3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) {
3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW)
3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.i(TAG, "Simulating a low-memory device");
3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                else
3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.i(TAG, "Simulating a regular-memory device");
3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sMemoryDeviceConfig = memoryDeviceConfig;
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method to determine if this content-based project must
3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * use this linker. If not, System.loadLibrary() should be used to load
3558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * libraries instead.
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static boolean isUsed() {
3588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Only GYP targets that are APKs and have the 'use_content_linker' variable
3598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // defined as 1 will use this linker. For all others (the default), the
3608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // auto-generated NativeLibraries.USE_LINKER variable will be false.
3618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!NativeLibraries.USE_LINKER)
3628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return false;
3638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ensureInitializedLocked();
3668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // At the moment, there is also no point in using this linker if the
3678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // system does not support RELRO sharing safely.
3688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return sRelroSharingSupported;
3698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
3738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method just before loading any native shared libraries in this process.
3748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
3758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void prepareLibraryLoad() {
3768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "prepareLibraryLoad() called");
3778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sPrepareLibraryLoadCalled = true;
3798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sInBrowserProcess) {
3818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Force generation of random base load address, as well
3828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // as creation of shared RELRO sections in this process.
3838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                setupBaseLoadAddressLocked();
3848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
3858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
3898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method just after loading all native shared libraries in this process.
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Note that when in a service process, this will block until the RELRO bundle is
3918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * received, i.e. when another thread calls useSharedRelros().
3928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    public static void finishLibraryLoad() {
3948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "finishLibraryLoad() called");
3958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
3968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, String.format(
3978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    "sInBrowserProcess=%s sBrowserUsesSharedRelro=%s sWaitForSharedRelros=%s",
3988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sInBrowserProcess ? "true" : "false",
3998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sBrowserUsesSharedRelro ? "true" : "false",
4008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sWaitForSharedRelros ? "true" : "false"));
4018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sLoadedLibraries == null) {
4038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "No libraries loaded");
4048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            } else {
4058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (sInBrowserProcess) {
4068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    // Create new Bundle containing RELRO section information
4078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    // for all loaded libraries. Make it available to getSharedRelros().
4088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sSharedRelros = createBundleFromLibInfoMap(sLoadedLibraries);
4098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    if (DEBUG) {
4108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        Log.i(TAG, "Shared RELRO created");
4118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        dumpBundle(sSharedRelros);
4128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    }
4138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    if (sBrowserUsesSharedRelro) {
4158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        useSharedRelrosLocked(sSharedRelros);
4168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    }
4178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
4188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (sWaitForSharedRelros) {
4208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    assert !sInBrowserProcess;
4218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    // Wait until the shared relro bundle is received from useSharedRelros().
4238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    while (sSharedRelros == null) {
4248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        try {
4258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            Linker.class.wait();
4268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        } catch (InterruptedException ie) {
4278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        }
4288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    }
4298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    useSharedRelrosLocked(sSharedRelros);
4308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    // Clear the Bundle to ensure its file descriptor references can't be reused.
4318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sSharedRelros.clear();
4328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    sSharedRelros = null;
4338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
4348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
4358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (NativeLibraries.ENABLE_LINKER_TESTS && sTestRunnerClassName != null) {
4378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // The TestRunner implementation must be instantiated _after_
4388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // all libraries are loaded to ensure that its native methods
4398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // are properly registered.
4408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "Instantiating " + sTestRunnerClassName);
4418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                TestRunner testRunner = null;
4428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                try {
4438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    testRunner = (TestRunner)
4448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            Class.forName(sTestRunnerClassName).newInstance();
4458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                } catch (Exception e) {
4468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.e(TAG, "Could not extract test runner class name", e);
4478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    testRunner = null;
4488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
4498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (testRunner != null) {
4508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    if (!testRunner.runChecks(sMemoryDeviceConfig, sInBrowserProcess)) {
4518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        Log.wtf(TAG, "Linker runtime tests failed in this process!!");
4528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        assert false;
4538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    } else {
4548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        Log.i(TAG, "All linker tests passed!");
4558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    }
4568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
4578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
4588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
4598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "finishLibraryLoad() exiting");
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
4638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this to send a Bundle containing the shared RELRO sections to be
4648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * used in this process. If initServiceProcess() was previously called,
4658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * finishLibraryLoad() will not exit until this method is called in another
4668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * thread with a non-null value.
4678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param bundle The Bundle instance containing a map of shared RELRO sections
4688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * to use in this process.
4698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
4708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void useSharedRelros(Bundle bundle) {
4718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Ensure the bundle uses the application's class loader, not the framework
4728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // one which doesn't know anything about LibInfo.
4738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (bundle != null)
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            bundle.setClassLoader(LibInfo.class.getClassLoader());
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "useSharedRelros() called with " + bundle);
4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Note that in certain cases, this can be called before
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // initServiceProcess() in service processes.
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sSharedRelros = bundle;
4828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Tell any listener blocked in finishLibraryLoad() about it.
4838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Linker.class.notifyAll();
4848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
4858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
4868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this to retrieve the shared RELRO sections created in this process,
4898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * after loading all libraries.
4908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return a new Bundle instance, or null if RELRO sharing is disabled on
4918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * this system, or if initServiceProcess() was called previously.
4928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
4938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static Bundle getSharedRelros() {
4948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "getSharedRelros() called");
4958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
4968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (!sInBrowserProcess) {
4978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "... returning null Bundle");
4988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                return null;
4998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
5008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Return the Bundle created in finishLibraryLoad().
5028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "... returning " + sSharedRelros);
5038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return sSharedRelros;
5048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
5058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
5098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method before loading any libraries to indicate that this
5108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * process shall neither create or reuse shared RELRO sections.
5118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
5128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void disableSharedRelros() {
5138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "disableSharedRelros() called");
5148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
5158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sInBrowserProcess = false;
5168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sWaitForSharedRelros = false;
5178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sBrowserUsesSharedRelro = false;
5188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
5198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
5228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this method before loading any libraries to indicate that this
5238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * process is ready to reuse shared RELRO sections from another one.
5248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Typically used when starting service processes.
5258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param baseLoadAddress the base library load address to use.
5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
5278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void initServiceProcess(long baseLoadAddress) {
5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, String.format("initServiceProcess(0x%x) called", baseLoadAddress));
5298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
5308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ensureInitializedLocked();
5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sInBrowserProcess = false;
5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sBrowserUsesSharedRelro = false;
5338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sRelroSharingSupported) {
5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sWaitForSharedRelros = true;
5358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sBaseLoadAddress = baseLoadAddress;
5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sCurrentLoadAddress = baseLoadAddress;
5378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
5428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Retrieve the base load address of all shared RELRO sections.
5438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * This also enforces the creation of shared RELRO sections in
5448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * prepareLibraryLoad(), which can later be retrieved with getSharedRelros().
5458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return a common, random base load address, or 0 if RELRO sharing is
5468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * disabled.
5478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
5488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static long getBaseLoadAddress() {
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
5508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ensureInitializedLocked();
5518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (!sInBrowserProcess) {
5528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                Log.w(TAG, "Shared RELRO sections are disabled in this process!");
5538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                return 0;
5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
5558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            setupBaseLoadAddressLocked();
5578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, String.format("getBaseLoadAddress() returns 0x%x",
5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                sBaseLoadAddress));
5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return sBaseLoadAddress;
5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Used internally to lazily setup the common random base load address.
5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static void setupBaseLoadAddressLocked() {
5658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert Thread.holdsLock(Linker.class);
5668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (sBaseLoadAddress == 0) {
5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            long address = computeRandomBaseLoadAddress();
5688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sBaseLoadAddress = address;
5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sCurrentLoadAddress = address;
5708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (address == 0) {
571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                // If the computed address is 0, there are issues with the
572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                // entropy source, so disable RELRO shared / fixed load addresses.
573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                Log.w(TAG, "Disabling shared RELROs due to bad entropy sources");
574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                sBrowserUsesSharedRelro = false;
575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                sWaitForSharedRelros = false;
5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
5788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Compute a random base load address where to place loaded libraries.
5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return new base load address, or 0 if the system does not support
5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * RELRO sharing.
5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static long computeRandomBaseLoadAddress() {
5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // The kernel ASLR feature will place randomized mappings starting
5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // from this address. Never try to load anything above this
5898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // explicitly to avoid random conflicts.
5908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        final long baseAddressLimit = 0x40000000;
5918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Start loading libraries from this base address.
5938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        final long baseAddress = 0x20000000;
5948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Maximum randomized base address value. Used to ensure a margin
5968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // of 192 MB below baseAddressLimit.
5978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        final long baseAddressMax = baseAddressLimit - 192 * 1024 * 1024;
5988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // The maximum limit of the desired random offset.
6008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        final long pageSize = nativeGetPageSize();
601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        final int offsetLimit = (int) ((baseAddressMax - baseAddress) / pageSize);
6028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Get the greatest power of 2 that is smaller or equal to offsetLimit.
6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        int numBits = 30;
6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        for (; numBits > 1; numBits--) {
6068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if ((1 << numBits) <= offsetLimit)
6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                break;
6088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) {
6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            final int maxValue = (1 << numBits) - 1;
6128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Log.i(TAG, String.format("offsetLimit=%d numBits=%d maxValue=%d (0x%x)",
6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                offsetLimit, numBits, maxValue, maxValue));
6148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Find a random offset between 0 and (2^numBits - 1), included.
6178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        int offset = getRandomBits(numBits);
6188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        long address = 0;
6198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (offset >= 0)
6208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            address = baseAddress + offset * pageSize;
6218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) {
6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Log.i(TAG,
6248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                  String.format("Linker.computeRandomBaseLoadAddress() return 0x%x",
6258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                address));
6268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return address;
6288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
6298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
6318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Return a cryptographically-strong random number of numBits bits.
6328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param numBits The number of bits in the result. Must be in 1..31 range.
6338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return A random integer between 0 and (2^numBits - 1), inclusive, or -1
6348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * in case of error (e.g. if /dev/urandom can't be opened or read).
6358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
6368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static int getRandomBits(int numBits) {
6378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Sanity check.
6388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert numBits > 0;
6398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert numBits < 32;
6408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        FileInputStream input;
6428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        try {
6438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // A naive implementation would read a 32-bit integer then use modulo, but
6448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // this introduces a slight bias. Instead, read 32-bit integers from the
6458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // entropy source until the value is positive but smaller than maxLimit.
6468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            input = new FileInputStream(new File("/dev/urandom"));
6478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        } catch (Exception e) {
6488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Log.e(TAG, "Could not open /dev/urandom", e);
6498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return -1;
6508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        int result = 0;
6538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        try {
654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            for (int n = 0; n < 4; n++) {
6558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                result = (result << 8) | (input.read() & 255);
656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            }
6578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        } catch (Exception e) {
6588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Log.e(TAG, "Could not read /dev/urandom", e);
6598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return -1;
6608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        } finally {
6618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            try {
6628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                input.close();
6638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            } catch (Exception e) {
6648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Can't really do anything here.
6658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
6668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        result &= (1 << numBits) - 1;
6688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) {
6708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            Log.i(TAG, String.format(
6718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    "getRandomBits(%d) returned %d", numBits, result));
6728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return result;
6758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
6768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Used for debugging only.
6788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static void dumpBundle(Bundle bundle) {
6798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "Bundle has " + bundle.size() + " items: " + bundle);
6808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
6818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
6838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Use the shared RELRO section from a Bundle received form another process.
6848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Call this after calling setBaseLoadAddress() then loading all libraries
6858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * with loadLibrary().
686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * @param bundle Bundle instance generated with createSharedRelroBundle() in
6878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * another process.
6888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
6898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static void useSharedRelrosLocked(Bundle bundle) {
6908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        assert Thread.holdsLock(Linker.class);
6918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "Linker.useSharedRelrosLocked() called");
6938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (bundle == null) {
6958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "null bundle!");
6968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return;
6978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
6988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!sRelroSharingSupported) {
7008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "System does not support RELRO sharing");
7018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return;
7028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
7038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (sLoadedLibraries == null) {
7058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "No libraries loaded!");
7068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return;
7078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
7088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) dumpBundle(bundle);
7108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        HashMap<String, LibInfo> relroMap = createLibInfoMapFromBundle(bundle);
7118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Apply the RELRO section to all libraries that were already loaded.
7138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        for (Map.Entry<String, LibInfo> entry : relroMap.entrySet()) {
7148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            String libName = entry.getKey();
7158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            LibInfo libInfo = entry.getValue();
7168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (!nativeUseSharedRelro(libName, libInfo)) {
7178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                Log.w(TAG, "Could not use shared RELRO section for " + libName);
7188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            } else {
7198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "Using shared RELRO section for " + libName);
7208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
7218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
7228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // In service processes, close all file descriptors from the map now.
7248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!sInBrowserProcess)
7258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            closeLibInfoMap(relroMap);
7268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "Linker.useSharedRelrosLocked() exiting");
7288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
7298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
7318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Returns whether the linker was unable to load one library at a given fixed address.
7328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     *
7338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return true if at least one library was not loaded at the expected fixed address.
7348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
7358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static boolean loadAtFixedAddressFailed() {
7368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return sLoadAtFixedAddressFailed;
7378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
7388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
7408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Load a native shared library with the Chromium linker.
7418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * If neither initSharedRelro() or readFromBundle() were called
7428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * previously, this uses the standard linker (i.e. System.loadLibrary()).
7438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     *
7448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param library The library's base name.
7458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
7468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static void loadLibrary(String library) {
7478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (DEBUG) Log.i(TAG, "loadLibrary: " + library);
7488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Don't self-load the linker. This is because the build system is
7508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // not clever enough to understand that all the libraries packaged
7518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // in the final .apk don't need to be explicitly loaded.
7528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Also deal with the component build that adds a .cr suffix to the name.
7538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (library.equals(TAG) || library.equals(TAG + ".cr")) {
7548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "ignoring self-linker load");
7558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return;
7568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
7578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        synchronized (Linker.class) {
7598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ensureInitializedLocked();
7608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Security: Ensure prepareLibraryLoad() was called before.
7628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // In theory, this can be done lazily here, but it's more consistent
7638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // to use a pair of functions (i.e. prepareLibraryLoad() + finishLibraryLoad())
7648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // that wrap all calls to loadLibrary() in the library loader.
7658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            assert sPrepareLibraryLoadCalled;
7668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            String libName = System.mapLibraryName(library);
7688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sLoadedLibraries == null)
7708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)              sLoadedLibraries = new HashMap<String, LibInfo>();
7718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sLoadedLibraries.containsKey(libName)) {
7738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (DEBUG) Log.i(TAG, "Not loading " + libName + " twice");
7748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                return;
7758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
7768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            LibInfo libInfo = new LibInfo();
7788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            long loadAddress = 0;
7798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if ((sInBrowserProcess && sBrowserUsesSharedRelro) || sWaitForSharedRelros) {
7808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Load the library at a fixed address.
7818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                loadAddress = sCurrentLoadAddress;
7828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
7838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (!nativeLoadLibrary(libName, loadAddress, libInfo)) {
7858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                String errorMessage = "Unable to load library: " + libName;
7868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                Log.e(TAG, errorMessage);
7878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                throw new UnsatisfiedLinkError(errorMessage);
7888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
7898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Keep track whether the library has been loaded at the expected load address.
7908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (loadAddress != 0 && loadAddress != libInfo.mLoadAddress)
7918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sLoadAtFixedAddressFailed = true;
7928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Print the load address to the logcat when testing the linker. The format
7948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // of the string is expected by the Python test_runner script as one of:
7958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            //    BROWSER_LIBRARY_ADDRESS: <library-name> <address>
7968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            //    RENDERER_LIBRARY_ADDRESS: <library-name> <address>
7978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // Where <library-name> is the library name, and <address> is the hexadecimal load
7988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            // address.
7998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (NativeLibraries.ENABLE_LINKER_TESTS) {
8008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                Log.i(TAG, String.format(
8018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        "%s_LIBRARY_ADDRESS: %s %x",
8028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        sInBrowserProcess ? "BROWSER" : "RENDERER",
8038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        libName,
8048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        libInfo.mLoadAddress));
8058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
8068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sInBrowserProcess) {
8088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Create a new shared RELRO section at the 'current' fixed load address.
8098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (!nativeCreateSharedRelro(libName, sCurrentLoadAddress, libInfo)) {
810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    Log.w(TAG, String.format("Could not create shared RELRO for %s at %x",
811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            libName, sCurrentLoadAddress));
8128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                } else {
8138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    if (DEBUG) Log.i(TAG,
8148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        String.format(
8158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            "Created shared RELRO for %s at %x: %s",
8168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            libName,
8178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            sCurrentLoadAddress,
8188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            libInfo.toString()));
8198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
8208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
8218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (sCurrentLoadAddress != 0) {
8238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // Compute the next current load address. If sBaseLoadAddress
8248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // is not 0, this is an explicit library load address. Otherwise,
8258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // this is an explicit load address for relocated RELRO sections
8268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                // only.
8278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sCurrentLoadAddress = libInfo.mLoadAddress + libInfo.mLoadSize;
8288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
8298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sLoadedLibraries.put(libName, libInfo);
8318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (DEBUG) Log.i(TAG, "Library details " + libInfo.toString());
8328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
8338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
8348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
8368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Native method used to load a library.
8378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param library Platform specific library name (e.g. libfoo.so)
8388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param loadAddress Explicit load address, or 0 for randomized one.
839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * @param libInfo If not null, the mLoadAddress and mLoadSize fields
8408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * of this LibInfo instance will set on success.
8418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return true for success, false otherwise.
8428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
8438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static native boolean nativeLoadLibrary(String library,
844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    long loadAddress,
8458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                    LibInfo libInfo);
8468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
8488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Native method used to create a shared RELRO section.
8498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * If the library was already loaded at the same address using
8508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * nativeLoadLibrary(), this creates the RELRO for it. Otherwise,
8518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * this loads a new temporary library at the specified address,
8528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * creates and extracts the RELRO section from it, then unloads it.
8538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param library Library name.
8548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param loadAddress load address, which can be different from the one
8558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * used to load the library in the current process!
856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * @param libInfo libInfo instance. On success, the mRelroStart, mRelroSize
8578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * and mRelroFd will be set.
8588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return true on success, false otherwise.
8598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
8608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static native boolean nativeCreateSharedRelro(String library,
8618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                          long loadAddress,
8628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                          LibInfo libInfo);
8638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
8658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Native method used to use a shared RELRO section.
8668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param library Library name.
8678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @param libInfo A LibInfo instance containing valid RELRO information
8688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * @return true on success.
8698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
8708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static native boolean nativeUseSharedRelro(String library,
8718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                       LibInfo libInfo);
8728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
8748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Checks that the system supports shared RELROs. Old Android kernels
8758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * have a bug in the way they check Ashmem region protection flags, which
8768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * makes using shared RELROs unsafe. This method performs a simple runtime
8778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * check for this misfeature, even though nativeEnableSharedRelro() will
8788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * always fail if this returns false.
8798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
8808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static native boolean nativeCanUseSharedRelro();
8818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Returns the native page size in bytes.
8838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static native long nativeGetPageSize();
8848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    /**
8868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Record information for a given library.
8878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * IMPORTANT: Native code knows about this class's fields, so
8888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * don't change them without modifying the corresponding C++ sources.
8898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     * Also, the LibInfo instance owns the ashmem file descriptor.
8908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)     */
8918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static class LibInfo implements Parcelable {
8928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public LibInfo() {
8948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mLoadAddress = 0;
8958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mLoadSize = 0;
8968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroStart = 0;
8978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroSize = 0;
8988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroFd = -1;
8998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public void close() {
9028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (mRelroFd >= 0) {
903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                try {
904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    ParcelFileDescriptor.adoptFd(mRelroFd).close();
905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                } catch (java.io.IOException e) {
906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                }
907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                mRelroFd = -1;
9088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
9098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // from Parcelable
9128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public LibInfo(Parcel in) {
9138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mLoadAddress = in.readLong();
9148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mLoadSize = in.readLong();
9158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroStart = in.readLong();
9168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroSize = in.readLong();
9178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ParcelFileDescriptor fd = in.readFileDescriptor();
9188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            mRelroFd = fd.detachFd();
9198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // from Parcelable
9228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        @Override
9238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public void writeToParcel(Parcel out, int flags) {
9248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (mRelroFd >= 0) {
9258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                out.writeLong(mLoadAddress);
9268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                out.writeLong(mLoadSize);
9278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                out.writeLong(mRelroStart);
9288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                out.writeLong(mRelroSize);
9298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                try {
9308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    ParcelFileDescriptor fd = ParcelFileDescriptor.fromFd(mRelroFd);
9318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    fd.writeToParcel(out, 0);
9328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    fd.close();
9338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                } catch (java.io.IOException e) {
9348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.e(TAG, "Cant' write LibInfo file descriptor to parcel", e);
9358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
9368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
9378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // from Parcelable
9408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        @Override
9418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public int describeContents() {
9428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return Parcelable.CONTENTS_FILE_DESCRIPTOR;
9438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // from Parcelable
946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        public static final Parcelable.Creator<LibInfo> CREATOR =
947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                new Parcelable.Creator<LibInfo>() {
948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    @Override
949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    public LibInfo createFromParcel(Parcel in) {
950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        return new LibInfo(in);
951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    }
9528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    @Override
954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    public LibInfo[] newArray(int size) {
955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        return new LibInfo[size];
956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    }
957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                };
9588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        @Override
9608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public String toString() {
9618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return String.format("[load=0x%x-0x%x relro=0x%x-0x%x fd=%d]",
9628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                 mLoadAddress,
9638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                 mLoadAddress + mLoadSize,
9648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                 mRelroStart,
9658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                 mRelroStart + mRelroSize,
9668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                 mRelroFd);
9678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // IMPORTANT: Don't change these fields without modifying the
9708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // native code that accesses them directly!
9718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public long mLoadAddress; // page-aligned library load address.
9728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public long mLoadSize;    // page-aligned library load size.
9738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public long mRelroStart;  // page-aligned address in memory, or 0 if none.
9748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public long mRelroSize;   // page-aligned size in memory, or 0.
9758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        public int  mRelroFd;     // ashmem file descriptor, or -1
9768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
9778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Create a Bundle from a map of LibInfo objects.
9798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static Bundle createBundleFromLibInfoMap(HashMap<String, LibInfo> map) {
9808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        Bundle bundle = new Bundle(map.size());
981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        for (Map.Entry<String, LibInfo> entry : map.entrySet()) {
9828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            bundle.putParcelable(entry.getKey(), entry.getValue());
983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
9848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return bundle;
9868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
9878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Create a new LibInfo map from a Bundle.
9898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static HashMap<String, LibInfo> createLibInfoMapFromBundle(Bundle bundle) {
9908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        HashMap<String, LibInfo> map = new HashMap<String, LibInfo>();
9918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        for (String library : bundle.keySet()) {
992a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            LibInfo libInfo = bundle.getParcelable(library);
993a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            map.put(library, libInfo);
9948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
9958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return map;
9968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
9978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
9988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Call the close() method on all values of a LibInfo map.
9998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static void closeLibInfoMap(HashMap<String, LibInfo> map) {
1000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        for (Map.Entry<String, LibInfo> entry : map.entrySet()) {
10018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            entry.getValue().close();
1002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
10038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
10048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // The map of libraries that are currently loaded in this process.
10068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static HashMap<String, LibInfo> sLoadedLibraries = null;
10078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Used to pass the shared RELRO Bundle through Binder.
10098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    public static final String EXTRA_LINKER_SHARED_RELROS =
10108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "org.chromium.content.common.linker.shared_relros";
10118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1012