1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker // This is the Android-specific Chromium dynamic linker (loader of dynamic
6*6777b538SAndroid Build Coastguard Worker // libraries), a tiny shared library implementing a custom dynamic linker that
7*6777b538SAndroid Build Coastguard Worker // can be used to load the real Chromium libraries.
8*6777b538SAndroid Build Coastguard Worker //
9*6777b538SAndroid Build Coastguard Worker // The purpose of this custom linker is to be able to share the RELRO section of
10*6777b538SAndroid Build Coastguard Worker // libcontentshell.so (or equivalent) between the browser process and all other
11*6777b538SAndroid Build Coastguard Worker // processes it asks to create.
12*6777b538SAndroid Build Coastguard Worker //
13*6777b538SAndroid Build Coastguard Worker // This source code *cannot* depend on anything from //base or the C++ standard
14*6777b538SAndroid Build Coastguard Worker // library to keep this DSO small and avoid dependency issues. An exception is
15*6777b538SAndroid Build Coastguard Worker // made for std::unique_ptr as a risky header-only definition.
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #ifndef BASE_ANDROID_LINKER_LINKER_JNI_H_
18*6777b538SAndroid Build Coastguard Worker #define BASE_ANDROID_LINKER_LINKER_JNI_H_
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker #include <android/log.h>
21*6777b538SAndroid Build Coastguard Worker #include <jni.h>
22*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
25*6777b538SAndroid Build Coastguard Worker #include "third_party/jni_zero/jni_zero.h"
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker // Set this to 1 to enable debug traces to the Android log.
28*6777b538SAndroid Build Coastguard Worker // Note that LOG() from "base/logging.h" cannot be used, since it is
29*6777b538SAndroid Build Coastguard Worker // in base/ which hasn't been loaded yet.
30*6777b538SAndroid Build Coastguard Worker #define DEBUG 0
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker #define TAG "cr_ChromiumAndroidLinker"
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker #if DEBUG
35*6777b538SAndroid Build Coastguard Worker #define LOG_INFO(FORMAT, ...) \
36*6777b538SAndroid Build Coastguard Worker __android_log_print(ANDROID_LOG_INFO, TAG, "%s: " FORMAT, __FUNCTION__, \
37*6777b538SAndroid Build Coastguard Worker ##__VA_ARGS__)
38*6777b538SAndroid Build Coastguard Worker #else
39*6777b538SAndroid Build Coastguard Worker #define LOG_INFO(FORMAT, ...) ((void)0)
40*6777b538SAndroid Build Coastguard Worker #endif
41*6777b538SAndroid Build Coastguard Worker #define LOG_ERROR(FORMAT, ...) \
42*6777b538SAndroid Build Coastguard Worker __android_log_print(ANDROID_LOG_ERROR, TAG, "%s: " FORMAT, __FUNCTION__, \
43*6777b538SAndroid Build Coastguard Worker ##__VA_ARGS__)
44*6777b538SAndroid Build Coastguard Worker #define PLOG_ERROR(FORMAT, ...) \
45*6777b538SAndroid Build Coastguard Worker LOG_ERROR(FORMAT ": %s", ##__VA_ARGS__, strerror(errno))
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker #if defined(__arm__) && defined(__ARM_ARCH_7A__)
48*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "armeabi-v7a"
49*6777b538SAndroid Build Coastguard Worker #elif defined(__arm__)
50*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "armeabi"
51*6777b538SAndroid Build Coastguard Worker #elif defined(__i386__)
52*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "x86"
53*6777b538SAndroid Build Coastguard Worker #elif defined(__mips__)
54*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "mips"
55*6777b538SAndroid Build Coastguard Worker #elif defined(__x86_64__)
56*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "x86_64"
57*6777b538SAndroid Build Coastguard Worker #elif defined(__aarch64__)
58*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "arm64-v8a"
59*6777b538SAndroid Build Coastguard Worker #elif defined(__riscv) && (__riscv_xlen == 64)
60*6777b538SAndroid Build Coastguard Worker #define CURRENT_ABI "riscv64"
61*6777b538SAndroid Build Coastguard Worker #else
62*6777b538SAndroid Build Coastguard Worker #error "Unsupported target abi"
63*6777b538SAndroid Build Coastguard Worker #endif
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker // Copied from //base/posix/eintr_wrapper.h to avoid depending on //base.
66*6777b538SAndroid Build Coastguard Worker #define HANDLE_EINTR(x) \
67*6777b538SAndroid Build Coastguard Worker ({ \
68*6777b538SAndroid Build Coastguard Worker decltype(x) eintr_wrapper_result; \
69*6777b538SAndroid Build Coastguard Worker do { \
70*6777b538SAndroid Build Coastguard Worker eintr_wrapper_result = (x); \
71*6777b538SAndroid Build Coastguard Worker } while (eintr_wrapper_result == -1 && errno == EINTR); \
72*6777b538SAndroid Build Coastguard Worker eintr_wrapper_result; \
73*6777b538SAndroid Build Coastguard Worker })
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Worker namespace chromium_android_linker {
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker // Larger than the largest library we might attempt to load.
78*6777b538SAndroid Build Coastguard Worker static const size_t kAddressSpaceReservationSize = 192 * 1024 * 1024;
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker // A simple scoped UTF String class that can be initialized from
81*6777b538SAndroid Build Coastguard Worker // a Java jstring handle. Modeled like std::string, which cannot
82*6777b538SAndroid Build Coastguard Worker // be used here.
83*6777b538SAndroid Build Coastguard Worker class String {
84*6777b538SAndroid Build Coastguard Worker public:
85*6777b538SAndroid Build Coastguard Worker String(JNIEnv* env, jstring str);
86*6777b538SAndroid Build Coastguard Worker
~String()87*6777b538SAndroid Build Coastguard Worker inline ~String() { ::free(ptr_); }
88*6777b538SAndroid Build Coastguard Worker
c_str()89*6777b538SAndroid Build Coastguard Worker inline const char* c_str() const { return ptr_ ? ptr_ : ""; }
size()90*6777b538SAndroid Build Coastguard Worker inline size_t size() const { return size_; }
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker private:
93*6777b538SAndroid Build Coastguard Worker char* ptr_;
94*6777b538SAndroid Build Coastguard Worker size_t size_;
95*6777b538SAndroid Build Coastguard Worker };
96*6777b538SAndroid Build Coastguard Worker
PageStart(size_t page_size,uintptr_t x)97*6777b538SAndroid Build Coastguard Worker inline uintptr_t PageStart(size_t page_size, uintptr_t x) {
98*6777b538SAndroid Build Coastguard Worker return x & ~(page_size - 1);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker
PageEnd(size_t page_size,uintptr_t x)101*6777b538SAndroid Build Coastguard Worker inline uintptr_t PageEnd(size_t page_size, uintptr_t x) {
102*6777b538SAndroid Build Coastguard Worker return PageStart(page_size, x + page_size - 1);
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker // Returns true iff casting a java-side |address| to uintptr_t does not lose
106*6777b538SAndroid Build Coastguard Worker // bits.
107*6777b538SAndroid Build Coastguard Worker bool IsValidAddress(jlong address);
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker // Find the jclass JNI reference corresponding to a given |class_name|.
110*6777b538SAndroid Build Coastguard Worker // |env| is the current JNI environment handle.
111*6777b538SAndroid Build Coastguard Worker // On success, return true and set |*clazz|.
112*6777b538SAndroid Build Coastguard Worker bool InitClassReference(JNIEnv* env, const char* class_name, jclass* clazz);
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker // Finds the region reserved by the WebView zygote if the current process is
115*6777b538SAndroid Build Coastguard Worker // inherited from the modern enough zygote that has this reservation. If the
116*6777b538SAndroid Build Coastguard Worker // lookup is successful, returns true and sets |address| and |size|. Otherwise
117*6777b538SAndroid Build Coastguard Worker // returns false.
118*6777b538SAndroid Build Coastguard Worker bool FindWebViewReservation(uintptr_t* address, size_t* size);
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker // Initialize a jfieldID corresponding to the field of a given |clazz|,
121*6777b538SAndroid Build Coastguard Worker // with name |field_name| and signature |field_sig|.
122*6777b538SAndroid Build Coastguard Worker // |env| is the current JNI environment handle.
123*6777b538SAndroid Build Coastguard Worker // On success, return true and set |*field_id|.
124*6777b538SAndroid Build Coastguard Worker bool InitFieldId(JNIEnv* env,
125*6777b538SAndroid Build Coastguard Worker jclass clazz,
126*6777b538SAndroid Build Coastguard Worker const char* field_name,
127*6777b538SAndroid Build Coastguard Worker const char* field_sig,
128*6777b538SAndroid Build Coastguard Worker jfieldID* field_id);
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker // Initialize a jfieldID corresponding to the static field of a given |clazz|,
131*6777b538SAndroid Build Coastguard Worker // with name |field_name| and signature |field_sig|.
132*6777b538SAndroid Build Coastguard Worker // |env| is the current JNI environment handle.
133*6777b538SAndroid Build Coastguard Worker // On success, return true and set |*field_id|.
134*6777b538SAndroid Build Coastguard Worker bool InitStaticFieldId(JNIEnv* env,
135*6777b538SAndroid Build Coastguard Worker jclass clazz,
136*6777b538SAndroid Build Coastguard Worker const char* field_name,
137*6777b538SAndroid Build Coastguard Worker const char* field_sig,
138*6777b538SAndroid Build Coastguard Worker jfieldID* field_id);
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker // A class used to model the field IDs of the org.chromium.base.Linker
141*6777b538SAndroid Build Coastguard Worker // LibInfo inner class, used to communicate data with the Java side
142*6777b538SAndroid Build Coastguard Worker // of the linker.
143*6777b538SAndroid Build Coastguard Worker struct LibInfo_class {
144*6777b538SAndroid Build Coastguard Worker jfieldID load_address_id;
145*6777b538SAndroid Build Coastguard Worker jfieldID load_size_id;
146*6777b538SAndroid Build Coastguard Worker jfieldID relro_start_id;
147*6777b538SAndroid Build Coastguard Worker jfieldID relro_size_id;
148*6777b538SAndroid Build Coastguard Worker jfieldID relro_fd_id;
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker // Initialize an instance.
InitLibInfo_class151*6777b538SAndroid Build Coastguard Worker bool Init(JNIEnv* env) {
152*6777b538SAndroid Build Coastguard Worker jclass clazz;
153*6777b538SAndroid Build Coastguard Worker if (!InitClassReference(
154*6777b538SAndroid Build Coastguard Worker env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) {
155*6777b538SAndroid Build Coastguard Worker return false;
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) &&
159*6777b538SAndroid Build Coastguard Worker InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) &&
160*6777b538SAndroid Build Coastguard Worker InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) &&
161*6777b538SAndroid Build Coastguard Worker InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) &&
162*6777b538SAndroid Build Coastguard Worker InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id);
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker
SetLoadInfoLibInfo_class165*6777b538SAndroid Build Coastguard Worker void SetLoadInfo(JNIEnv* env,
166*6777b538SAndroid Build Coastguard Worker jobject library_info_obj,
167*6777b538SAndroid Build Coastguard Worker uintptr_t load_address,
168*6777b538SAndroid Build Coastguard Worker size_t load_size) {
169*6777b538SAndroid Build Coastguard Worker env->SetLongField(library_info_obj, load_address_id, load_address);
170*6777b538SAndroid Build Coastguard Worker env->SetLongField(library_info_obj, load_size_id, load_size);
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
SetRelroInfoLibInfo_class173*6777b538SAndroid Build Coastguard Worker void SetRelroInfo(JNIEnv* env,
174*6777b538SAndroid Build Coastguard Worker jobject library_info_obj,
175*6777b538SAndroid Build Coastguard Worker uintptr_t relro_start,
176*6777b538SAndroid Build Coastguard Worker size_t relro_size,
177*6777b538SAndroid Build Coastguard Worker int relro_fd) {
178*6777b538SAndroid Build Coastguard Worker env->SetLongField(library_info_obj, relro_start_id, relro_start);
179*6777b538SAndroid Build Coastguard Worker env->SetLongField(library_info_obj, relro_size_id, relro_size);
180*6777b538SAndroid Build Coastguard Worker env->SetIntField(library_info_obj, relro_fd_id, relro_fd);
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
GetLoadInfoLibInfo_class183*6777b538SAndroid Build Coastguard Worker bool GetLoadInfo(JNIEnv* env,
184*6777b538SAndroid Build Coastguard Worker jobject library_info_obj,
185*6777b538SAndroid Build Coastguard Worker uintptr_t* load_address,
186*6777b538SAndroid Build Coastguard Worker size_t* load_size) {
187*6777b538SAndroid Build Coastguard Worker if (load_address) {
188*6777b538SAndroid Build Coastguard Worker jlong java_address = env->GetLongField(library_info_obj, load_address_id);
189*6777b538SAndroid Build Coastguard Worker if (!IsValidAddress(java_address))
190*6777b538SAndroid Build Coastguard Worker return false;
191*6777b538SAndroid Build Coastguard Worker *load_address = static_cast<uintptr_t>(java_address);
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker if (load_size) {
194*6777b538SAndroid Build Coastguard Worker *load_size = static_cast<uintptr_t>(
195*6777b538SAndroid Build Coastguard Worker env->GetLongField(library_info_obj, load_size_id));
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker return true;
198*6777b538SAndroid Build Coastguard Worker }
199*6777b538SAndroid Build Coastguard Worker
GetRelroInfoLibInfo_class200*6777b538SAndroid Build Coastguard Worker void GetRelroInfo(JNIEnv* env,
201*6777b538SAndroid Build Coastguard Worker jobject library_info_obj,
202*6777b538SAndroid Build Coastguard Worker uintptr_t* relro_start,
203*6777b538SAndroid Build Coastguard Worker size_t* relro_size,
204*6777b538SAndroid Build Coastguard Worker int* relro_fd) {
205*6777b538SAndroid Build Coastguard Worker if (relro_start) {
206*6777b538SAndroid Build Coastguard Worker *relro_start = static_cast<uintptr_t>(
207*6777b538SAndroid Build Coastguard Worker env->GetLongField(library_info_obj, relro_start_id));
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker
210*6777b538SAndroid Build Coastguard Worker if (relro_size) {
211*6777b538SAndroid Build Coastguard Worker *relro_size = static_cast<size_t>(
212*6777b538SAndroid Build Coastguard Worker env->GetLongField(library_info_obj, relro_size_id));
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker if (relro_fd) {
216*6777b538SAndroid Build Coastguard Worker *relro_fd = env->GetIntField(library_info_obj, relro_fd_id);
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker };
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Worker // Used to find out whether RELRO sharing is often rejected due to mismatch of
222*6777b538SAndroid Build Coastguard Worker // the contents.
223*6777b538SAndroid Build Coastguard Worker //
224*6777b538SAndroid Build Coastguard Worker // These values are persisted to logs. Entries should not be renumbered and
225*6777b538SAndroid Build Coastguard Worker // numeric values should never be reused. Must be kept in sync with the enum
226*6777b538SAndroid Build Coastguard Worker // in enums.xml. A java @IntDef is generated from this.
227*6777b538SAndroid Build Coastguard Worker // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
228*6777b538SAndroid Build Coastguard Worker enum class RelroSharingStatus {
229*6777b538SAndroid Build Coastguard Worker NOT_ATTEMPTED = 0,
230*6777b538SAndroid Build Coastguard Worker SHARED = 1,
231*6777b538SAndroid Build Coastguard Worker NOT_IDENTICAL = 2,
232*6777b538SAndroid Build Coastguard Worker EXTERNAL_RELRO_FD_NOT_PROVIDED = 3,
233*6777b538SAndroid Build Coastguard Worker EXTERNAL_RELRO_NOT_FOUND = 4,
234*6777b538SAndroid Build Coastguard Worker NO_SHMEM_FUNCTIONS = 5,
235*6777b538SAndroid Build Coastguard Worker REMAP_FAILED = 6,
236*6777b538SAndroid Build Coastguard Worker CORRUPTED_IN_JAVA = 7,
237*6777b538SAndroid Build Coastguard Worker EXTERNAL_LOAD_ADDRESS_RESET = 8,
238*6777b538SAndroid Build Coastguard Worker COUNT = 9,
239*6777b538SAndroid Build Coastguard Worker };
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker struct SharedMemoryFunctions;
242*6777b538SAndroid Build Coastguard Worker
243*6777b538SAndroid Build Coastguard Worker // Holds address ranges of the loaded native library, its RELRO region, along
244*6777b538SAndroid Build Coastguard Worker // with the RELRO FD identifying the shared memory region. Carries the same
245*6777b538SAndroid Build Coastguard Worker // members as the Java-side LibInfo (without mLibFilePath), allowing to
246*6777b538SAndroid Build Coastguard Worker // internally import/export the member values from/to the Java-side counterpart.
247*6777b538SAndroid Build Coastguard Worker //
248*6777b538SAndroid Build Coastguard Worker // Does *not* own the RELRO FD as soon as the latter gets exported to Java
249*6777b538SAndroid Build Coastguard Worker // (as a result of 'spawning' the RELRO region as shared memory.
250*6777b538SAndroid Build Coastguard Worker //
251*6777b538SAndroid Build Coastguard Worker // *Not* threadsafe.
252*6777b538SAndroid Build Coastguard Worker class NativeLibInfo {
253*6777b538SAndroid Build Coastguard Worker public:
254*6777b538SAndroid Build Coastguard Worker // Constructs an empty instance. The |java_object| indicates the handle to
255*6777b538SAndroid Build Coastguard Worker // import and export member fields.
256*6777b538SAndroid Build Coastguard Worker //
257*6777b538SAndroid Build Coastguard Worker // Having |env| as |nullptr| disables export to java for the lifetime of the
258*6777b538SAndroid Build Coastguard Worker // instance. This is useful as a scratch info that is gradually populated for
259*6777b538SAndroid Build Coastguard Worker // comparison with another NativeLibInfo, and then discarded.
260*6777b538SAndroid Build Coastguard Worker NativeLibInfo(JNIEnv* env, jobject java_object);
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker // Copies the java-side object state to this native instance. Returns false
263*6777b538SAndroid Build Coastguard Worker // iff an imported value is invalid.
264*6777b538SAndroid Build Coastguard Worker bool CopyFromJavaObject();
265*6777b538SAndroid Build Coastguard Worker
set_load_address(uintptr_t a)266*6777b538SAndroid Build Coastguard Worker void set_load_address(uintptr_t a) { load_address_ = a; }
267*6777b538SAndroid Build Coastguard Worker
load_address()268*6777b538SAndroid Build Coastguard Worker uintptr_t load_address() const { return load_address_; }
269*6777b538SAndroid Build Coastguard Worker
270*6777b538SAndroid Build Coastguard Worker // Loads the native library using android_dlopen_ext and invokes JNI_OnLoad().
271*6777b538SAndroid Build Coastguard Worker //
272*6777b538SAndroid Build Coastguard Worker // On a successful load exports the address range of the library to the
273*6777b538SAndroid Build Coastguard Worker // Java-side LibInfo.
274*6777b538SAndroid Build Coastguard Worker //
275*6777b538SAndroid Build Coastguard Worker // Iff |spawn_relro_region| is true, also finds the RELRO region in the
276*6777b538SAndroid Build Coastguard Worker // library (PT_GNU_RELRO), converts it to be backed by a shared memory region
277*6777b538SAndroid Build Coastguard Worker // (here referred as "RELRO FD") and exports the RELRO information to Java
278*6777b538SAndroid Build Coastguard Worker // (the address range and the RELRO FD).
279*6777b538SAndroid Build Coastguard Worker //
280*6777b538SAndroid Build Coastguard Worker // When spawned, the shared memory region is exported only after sealing as
281*6777b538SAndroid Build Coastguard Worker // read-only and without writable memory mappings. This allows any process to
282*6777b538SAndroid Build Coastguard Worker // provide RELRO FD before it starts processing arbitrary input. For example,
283*6777b538SAndroid Build Coastguard Worker // an App Zygote can create a RELRO FD in a sufficiently trustworthy way to
284*6777b538SAndroid Build Coastguard Worker // make the Browser/Privileged processes share the region with it.
285*6777b538SAndroid Build Coastguard Worker bool LoadLibrary(const String& library_path, bool spawn_relro_region);
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker // Finds the RELRO region in the native library identified by
288*6777b538SAndroid Build Coastguard Worker // |this->load_address()| and replaces it with the shared memory region
289*6777b538SAndroid Build Coastguard Worker // identified by |other_lib_info|.
290*6777b538SAndroid Build Coastguard Worker //
291*6777b538SAndroid Build Coastguard Worker // The external NativeLibInfo can arrive from a different process.
292*6777b538SAndroid Build Coastguard Worker //
293*6777b538SAndroid Build Coastguard Worker // Note on security: The RELRO region is treated as *trusted*, no untrusted
294*6777b538SAndroid Build Coastguard Worker // user/website/network input can be processed in an isolated process before
295*6777b538SAndroid Build Coastguard Worker // it sends the RELRO FD. This is because there is no way to check whether the
296*6777b538SAndroid Build Coastguard Worker // process has a writable mapping of the region remaining.
297*6777b538SAndroid Build Coastguard Worker bool CompareRelroAndReplaceItBy(const NativeLibInfo& other_lib_info);
298*6777b538SAndroid Build Coastguard Worker
set_relro_info_for_testing(uintptr_t start,size_t size)299*6777b538SAndroid Build Coastguard Worker void set_relro_info_for_testing(uintptr_t start, size_t size) {
300*6777b538SAndroid Build Coastguard Worker relro_start_ = start;
301*6777b538SAndroid Build Coastguard Worker relro_size_ = size;
302*6777b538SAndroid Build Coastguard Worker }
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker // Creates a shared RELRO region as it normally would during LoadLibrary()
305*6777b538SAndroid Build Coastguard Worker // with |spawn_relro_region=true|. Exposed here because it is difficult to
306*6777b538SAndroid Build Coastguard Worker // unittest LoadLibrary() directly.
307*6777b538SAndroid Build Coastguard Worker bool CreateSharedRelroFdForTesting();
308*6777b538SAndroid Build Coastguard Worker
set_relro_fd_for_testing(int fd)309*6777b538SAndroid Build Coastguard Worker void set_relro_fd_for_testing(int fd) { relro_fd_ = fd; }
get_relro_fd_for_testing()310*6777b538SAndroid Build Coastguard Worker int get_relro_fd_for_testing() const { return relro_fd_; }
get_relro_start_for_testing()311*6777b538SAndroid Build Coastguard Worker size_t get_relro_start_for_testing() const { return relro_start_; }
get_load_size_for_testing()312*6777b538SAndroid Build Coastguard Worker size_t get_load_size_for_testing() const { return load_size_; }
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker static bool SharedMemoryFunctionsSupportedForTesting();
315*6777b538SAndroid Build Coastguard Worker
FindRelroAndLibraryRangesInElfForTesting()316*6777b538SAndroid Build Coastguard Worker bool FindRelroAndLibraryRangesInElfForTesting() {
317*6777b538SAndroid Build Coastguard Worker return FindRelroAndLibraryRangesInElf();
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker private:
321*6777b538SAndroid Build Coastguard Worker NativeLibInfo() = delete;
322*6777b538SAndroid Build Coastguard Worker
323*6777b538SAndroid Build Coastguard Worker // Not copyable or movable.
324*6777b538SAndroid Build Coastguard Worker NativeLibInfo(const NativeLibInfo&) = delete;
325*6777b538SAndroid Build Coastguard Worker NativeLibInfo& operator=(const NativeLibInfo&) = delete;
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker // Exports the address range of the library described by |this| to the
328*6777b538SAndroid Build Coastguard Worker // Java-side LibInfo.
329*6777b538SAndroid Build Coastguard Worker void ExportLoadInfoToJava() const;
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker // Exports the address range of the RELRO region and RELRO FD described by
332*6777b538SAndroid Build Coastguard Worker // |this| to the Java-side LibInfo.
333*6777b538SAndroid Build Coastguard Worker void ExportRelroInfoToJava() const;
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker void CloseRelroFd();
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker // Determines the minimal address ranges for the union of all the loadable
338*6777b538SAndroid Build Coastguard Worker // (and RELRO) segments by parsing ELF starting at |load_address()|. May fail
339*6777b538SAndroid Build Coastguard Worker // or return incorrect results for some creative ELF libraries.
340*6777b538SAndroid Build Coastguard Worker bool FindRelroAndLibraryRangesInElf();
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker // Loads and initializes the load address ranges: |load_address_|,
343*6777b538SAndroid Build Coastguard Worker // |load_size_|. Assumes that the memory range is reserved (in Linker.java).
344*6777b538SAndroid Build Coastguard Worker bool LoadWithDlopenExt(const String& path, void** handle);
345*6777b538SAndroid Build Coastguard Worker
346*6777b538SAndroid Build Coastguard Worker // Initializes |relro_fd_| with a newly created read-only shared memory region
347*6777b538SAndroid Build Coastguard Worker // sized as the library's RELRO and with identical data.
348*6777b538SAndroid Build Coastguard Worker bool CreateSharedRelroFd(const SharedMemoryFunctions& functions);
349*6777b538SAndroid Build Coastguard Worker
350*6777b538SAndroid Build Coastguard Worker // Assuming that RELRO-related information is populated, memory-maps the RELRO
351*6777b538SAndroid Build Coastguard Worker // FD on top of the library's RELRO.
352*6777b538SAndroid Build Coastguard Worker bool ReplaceRelroWithSharedOne(const SharedMemoryFunctions& functions) const;
353*6777b538SAndroid Build Coastguard Worker
354*6777b538SAndroid Build Coastguard Worker // Returns true iff the RELRO address and size, along with the contents are
355*6777b538SAndroid Build Coastguard Worker // equal among the two.
356*6777b538SAndroid Build Coastguard Worker bool RelroIsIdentical(const NativeLibInfo& external_lib_info,
357*6777b538SAndroid Build Coastguard Worker const SharedMemoryFunctions& functions) const;
358*6777b538SAndroid Build Coastguard Worker
359*6777b538SAndroid Build Coastguard Worker static constexpr int kInvalidFd = -1;
360*6777b538SAndroid Build Coastguard Worker uintptr_t load_address_ = 0;
361*6777b538SAndroid Build Coastguard Worker size_t load_size_ = 0;
362*6777b538SAndroid Build Coastguard Worker uintptr_t relro_start_ = 0;
363*6777b538SAndroid Build Coastguard Worker size_t relro_size_ = 0;
364*6777b538SAndroid Build Coastguard Worker int relro_fd_ = kInvalidFd;
365*6777b538SAndroid Build Coastguard Worker JNIEnv* const env_;
366*6777b538SAndroid Build Coastguard Worker const jobject java_object_;
367*6777b538SAndroid Build Coastguard Worker };
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker // JNI_OnLoad() initialization hook for the linker.
370*6777b538SAndroid Build Coastguard Worker // Sets up JNI and other initializations for native linker code.
371*6777b538SAndroid Build Coastguard Worker // |vm| is the Java VM handle passed to JNI_OnLoad().
372*6777b538SAndroid Build Coastguard Worker // |env| is the current JNI environment handle.
373*6777b538SAndroid Build Coastguard Worker // On success, returns true.
374*6777b538SAndroid Build Coastguard Worker bool LinkerJNIInit(JavaVM* vm, JNIEnv* env);
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker } // namespace chromium_android_linker
377*6777b538SAndroid Build Coastguard Worker
378*6777b538SAndroid Build Coastguard Worker #endif // BASE_ANDROID_LINKER_LINKER_JNI_H_
379