Skip to content

Commit b0bac8b

Browse files
committed
clean: drop unnecesary and complicated code
1 parent 9167c38 commit b0bac8b

4 files changed

Lines changed: 184 additions & 586 deletions

File tree

loader/src/injector/hook.cpp

Lines changed: 49 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
#include <dlfcn.h>
22
#include <pthread.h>
3-
#include <sched.h>
43
#include <sys/mman.h>
5-
#include <sys/mount.h>
6-
#include <sys/resource.h>
7-
#include <sys/stat.h>
84
#include <unistd.h>
9-
#include <fcntl.h>
10-
#include <linux/seccomp.h>
11-
#include <linux/filter.h>
5+
#include <sys/resource.h>
126
#include <sys/prctl.h>
13-
#include <sys/syscall.h>
14-
#include <linux/audit.h>
157
#include <stdint.h>
168
#include <stdlib.h>
179

1810
#include <lsplt.hpp>
1911

2012
#include "android_util.hpp"
21-
#include "elf_utils.hpp"
2213
#include "daemon.hpp"
2314
#include "misc.hpp"
2415
#include "module.hpp"
@@ -116,8 +107,7 @@ DCL_HOOK_FUNC(static char *, strdup, const char *str) {
116107
// Wipe the old map paths populated by hook_plt() before overwriting them.
117108
// The new scan will repopulate the map info with the same paths, but they
118109
// will be wiped again in hook_zygote_jni() after we are done with hooking.
119-
g_hook->clear_map_paths();
120-
g_hook->refresh_map_infos();
110+
g_hook->hook_unloader();
121111
zygote_hooked = true;
122112
}
123113
}
@@ -149,40 +139,6 @@ DCL_HOOK_FUNC(static int, unshare, int flags) {
149139
return old_unshare(flags);
150140
}
151141

152-
DCL_HOOK_FUNC(int, property_get, const char *key, char *value, const char *default_value) {
153-
154-
static bool unloader_triggered = false;
155-
156-
if (unlikely(!unloader_triggered)) {
157-
unloader_triggered = true;
158-
159-
if (!g_hook->skip_hooking_unloader) {
160-
g_hook->hook_unloader();
161-
g_hook->skip_hooking_unloader = true;
162-
163-
for (size_t i = g_hook->plt_backup.size; i > 0; ) {
164-
i--;
165-
const auto& bkp = g_hook->plt_backup.data[i];
166-
167-
if (bkp.backup_ptr == reinterpret_cast<void*>(old_property_get)) {
168-
if (!lsplt::RegisterHook(bkp.dev, bkp.inode, bkp.sym, *bkp.backup_ptr, nullptr) ||
169-
!lsplt::CommitHook(g_hook->cached_map_infos, true)) {
170-
PLOGE("unhook %s", bkp.sym);
171-
} else {
172-
if (i < g_hook->plt_backup.size - 1) {
173-
__builtin_memmove(&g_hook->plt_backup.data[i], &g_hook->plt_backup.data[i + 1],
174-
(g_hook->plt_backup.size - i - 1) * sizeof(PltBackupEntry));
175-
}
176-
g_hook->plt_backup.size--;
177-
}
178-
}
179-
}
180-
g_hook->clear_map_paths();
181-
}
182-
}
183-
return old_property_get(key, value, default_value);
184-
}
185-
186142
// We cannot directly call `munmap` to unload ourselves, otherwise when `munmap` returns,
187143
// it will return to our code which has been unmapped, causing segmentation fault.
188144
// Instead, we hook `pthread_attr_setstacksize` which will be called when VM daemon threads start.
@@ -212,9 +168,13 @@ DCL_HOOK_FUNC(static int, pthread_attr_setstacksize, void *target, size_t size)
212168

213169
// -----------------------------------------------------------------
214170
static size_t get_fd_max() {
215-
rlimit r{32768, 32768};
216-
getrlimit(RLIMIT_NOFILE, &r);
217-
return r.rlim_max;
171+
static size_t cached_max = 0;
172+
if (unlikely(cached_max == 0)) {
173+
rlimit r{32768, 32768};
174+
getrlimit(RLIMIT_NOFILE, &r);
175+
cached_max = r.rlim_max;
176+
}
177+
return cached_max;
218178
}
219179

220180
ZygiskContext::ZygiskContext(JNIEnv *env, void *args)
@@ -223,14 +183,12 @@ ZygiskContext::ZygiskContext(JNIEnv *env, void *args)
223183
process(nullptr),
224184
pid(-1),
225185
flags(0),
226-
info_flags(0),
227-
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) {
186+
info_flags(0) {
228187

229188
size_t fd_max = get_fd_max();
230189
allowed_fds.capacity = fd_max;
231190
allowed_fds.size = fd_max;
232-
allowed_fds.data = (bool*)malloc(fd_max * sizeof(bool));
233-
__builtin_memset(allowed_fds.data, 0, fd_max * sizeof(bool));
191+
allowed_fds.data = static_cast<bool*>(calloc(fd_max, sizeof(bool)));
234192
g_ctx = this;
235193
}
236194

@@ -264,90 +222,53 @@ void HookContext::register_hook(dev_t dev, ino_t inode, const char *symbol, void
264222

265223
#define PLT_HOOK_REGISTER(DEV, INODE, NAME) PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, NAME)
266224

267-
void HookContext::refresh_map_infos() {
268-
map_info_cache.size = 0;
269-
cached_map_infos = lsplt::Scan();
270-
271-
for (size_t i = 0; i < cached_map_infos.size; i++) {
272-
const auto& map = cached_map_infos.data[i];
273-
if (map.path[0] != '\0') {
274-
const char* filename = __builtin_strrchr(map.path, '/');
275-
filename = filename ? filename + 1 : map.path;
276-
CachedMapEntry entry;
277-
entry.name = filename;
278-
entry.name_hash = calc_gnu_hash(filename);
279-
entry.info = &map;
280-
map_info_cache.push_back(entry);
281-
}
282-
}
283-
284-
if (map_info_cache.size > 0) {
285-
::sort(map_info_cache.data, map_info_cache.data + map_info_cache.size,
286-
[](const CachedMapEntry& a, const CachedMapEntry& b) {
287-
return a.name_hash < b.name_hash;
288-
});
289-
}
290-
}
291-
292225
void HookContext::hook_plt() {
293226
ino_t android_runtime_inode = 0;
294227
dev_t android_runtime_dev = 0;
295228

296-
refresh_map_infos();
229+
cached_map_infos = lsplt::Scan();
297230

298-
if (const auto* info = find_in_cache(map_info_cache, "libandroid_runtime.so")) {
299-
android_runtime_inode = info->inode;
300-
android_runtime_dev = info->dev;
301-
}
231+
for (size_t i = 0; i < cached_map_infos.size; i++) {
232+
const char* path = cached_map_infos.data[i].path;
233+
if (path[0] == '\0') continue;
234+
235+
const char* filename = __builtin_strrchr(path, '/');
236+
filename = filename ? filename + 1 : path;
237+
238+
if (__builtin_strcmp(filename, "libandroid_runtime.so") == 0) {
239+
android_runtime_inode = cached_map_infos.data[i].inode;
240+
android_runtime_dev = cached_map_infos.data[i].dev;
241+
} else if (__builtin_strcmp(filename, "libart.so") == 0) {
242+
g_art_inode = cached_map_infos.data[i].inode;
243+
g_art_dev = cached_map_infos.data[i].dev;
244+
}
302245

303-
if (const auto* info = find_in_cache(map_info_cache, "libart.so")) {
304-
g_art_inode = info->inode;
305-
g_art_dev = info->dev;
246+
if (android_runtime_inode && g_art_inode) break;
306247
}
307248

308249
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork);
309250
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare);
310251
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, strdup);
311-
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, property_get);
312252

313253
if (!lsplt::CommitHook(cached_map_infos)) LOGE("HookContext::hook_plt failed");
314-
315-
size_t new_size = 0;
316-
for (size_t i = 0; i < plt_backup.size; i++) {
317-
if (*plt_backup.data[i].backup_ptr != nullptr) {
318-
plt_backup.data[new_size++] = plt_backup.data[i];
319-
}
320-
}
321-
plt_backup.size = new_size;
322254
}
323255

324256
void HookContext::hook_unloader() {
325-
clear_map_paths();
326-
refresh_map_infos();
327-
if (g_art_inode == 0 || g_art_dev == 0) {
328-
if (const auto* info = find_in_cache(map_info_cache, "libart.so")) {
329-
g_art_inode = info->inode;
330-
g_art_dev = info->dev;
257+
if (g_art_inode != 0 && g_art_dev != 0) {
258+
PLT_HOOK_REGISTER(g_art_dev, g_art_inode, pthread_attr_setstacksize);
259+
if (!lsplt::CommitHook(cached_map_infos)) {
260+
LOGE("HookContext::hook_unloader failed");
331261
}
262+
} else {
263+
LOGE("libart.so not found! Unloader hook failed.");
332264
}
333-
334-
PLT_HOOK_REGISTER(g_art_dev, g_art_inode, pthread_attr_setstacksize);
335-
if (!lsplt::CommitHook(cached_map_infos)) {
336-
LOGE("HookContext::hook_unloader failed");
337-
}
265+
clear_map_paths();
338266
}
339267

340268
void HookContext::clear_map_paths() {
341-
static atomic_flag clearing = ATOMIC_FLAG_INIT;
342-
if (atomic_flag_test_and_set_explicit(&clearing, memory_order_acquire)) return;
343-
344269
for (size_t i = 0; i < cached_map_infos.size; i++) {
345-
auto& map = cached_map_infos.data[i];
346-
size_t len = strnlen(map.path, sizeof(map.path));
347-
if (len > 0) memzero(map.path, len);
270+
__builtin_memset(cached_map_infos.data[i].path, 0, sizeof(cached_map_infos.data[i].path));
348271
}
349-
350-
atomic_flag_clear_explicit(&clearing, memory_order_release);
351272
}
352273

353274
void HookContext::restore_plt_hook() {
@@ -362,10 +283,6 @@ void HookContext::restore_plt_hook() {
362283
LOGE("failed to restore plt_hook");
363284
should_unmap = false;
364285
}
365-
366-
// Clear cached map info
367-
clear_map_paths();
368-
cached_map_infos.size = 0;
369286
}
370287

371288
// -----------------------------------------------------------------
@@ -378,7 +295,7 @@ void HookContext::hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods meth
378295
return;
379296
}
380297

381-
JNINativeMethod* hooks = new JNINativeMethod[methods.size()];
298+
auto* hooks = static_cast<JNINativeMethod*>(alloca(sizeof(JNINativeMethod) * methods.size()));
382299
size_t hooks_count = 0;
383300

384301
for (auto &native_method : methods) {
@@ -397,11 +314,6 @@ void HookContext::hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods meth
397314
continue;
398315
}
399316
auto method = util::jni::ToReflectedMethod(env, clazz, method_id, is_static);
400-
auto modifier = util::jni::CallIntMethod(env, method, member_getModifiers);
401-
if ((modifier & MODIFIER_NATIVE) == 0) {
402-
native_method.fnPtr = nullptr;
403-
continue;
404-
}
405317
auto artMethod = util::art::ArtMethod::FromReflectedMethod(env, method);
406318
hooks[hooks_count++] = native_method;
407319
auto original_method = artMethod->GetData();
@@ -410,50 +322,28 @@ void HookContext::hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods meth
410322
}
411323

412324
if (hooks_count > 0) env->RegisterNatives(clazz, hooks, hooks_count);
413-
delete[] hooks;
414325
}
415326

416327
void HookContext::hook_zygote_jni() {
417328
auto get_created_java_vms = reinterpret_cast<jint (*)(JavaVM **, jsize, jsize *)>(
418329
dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs"));
419330
if (!get_created_java_vms) {
420-
void* sym = resolve_symbol("libnativehelper.so", "JNI_GetCreatedJavaVMs");
421-
if (sym) {
422-
get_created_java_vms = reinterpret_cast<decltype(get_created_java_vms)>(sym);
423-
} else {
424-
LOGW("JNI_GetCreatedJavaVMs not found in memory");
425-
return;
426-
}
331+
LOGE("JNI_GetCreatedJavaVMs not found in memory!");
332+
return;
427333
}
428334
JavaVM *vm = nullptr;
429335
jsize num = 0;
430-
jint res = get_created_java_vms(&vm, 1, &num);
431-
if (res != JNI_OK || vm == nullptr) return;
336+
if (get_created_java_vms(&vm, 1, &num) != JNI_OK || vm == nullptr) return;
432337
JNIEnv *env = nullptr;
433-
res = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
434-
if (res != JNI_OK || env == nullptr) return;
435-
436-
auto classMember = util::jni::FindClass(env, "java/lang/reflect/Member");
437-
if (classMember != nullptr)
438-
member_getModifiers = util::jni::GetMethodID(env, classMember, "getModifiers", "()I");
439-
auto classModifier = util::jni::FindClass(env, "java/lang/reflect/Modifier");
440-
if (classModifier != nullptr) {
441-
auto fieldId = util::jni::GetStaticFieldID(env, classModifier, "NATIVE", "I");
442-
if (fieldId != nullptr)
443-
MODIFIER_NATIVE = util::jni::GetStaticIntField(env, classModifier, fieldId);
444-
}
445-
if (member_getModifiers == nullptr || MODIFIER_NATIVE == 0) return;
338+
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK || env == nullptr) return;
339+
446340
if (!util::art::ArtMethod::Init(env)) {
447341
LOGE("failed to init ArtMethod");
448342
return;
449343
}
450344
hook_jni_methods(env, kZygote, JNIMethods(zygote_methods, sizeof(zygote_methods) / sizeof(zygote_methods[0])));
451345
}
452346

453-
void HookContext::restore_zygote_hook(JNIEnv *env) {
454-
hook_jni_methods(env, kZygote, JNIMethods(zygote_methods, sizeof(zygote_methods) / sizeof(zygote_methods[0])));
455-
}
456-
457347
// -----------------------------------------------------------------
458348

459349
void hook_entry(void *start_addr, size_t block_size) {
@@ -475,6 +365,14 @@ void hook_entry(void *start_addr, size_t block_size) {
475365
g_hook->hook_plt();
476366
}
477367

368+
void HookContext::restore_zygote_hook(JNIEnv *env) {
369+
auto clazz = env->FindClass(kZygote);
370+
if (clazz) {
371+
env->RegisterNatives(clazz, zygote_methods, sizeof(zygote_methods) / sizeof(zygote_methods[0]));
372+
}
373+
env->ExceptionClear();
374+
}
375+
478376
void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods, int numMethods) {
479377
g_hook->hook_jni_methods(env, clz, {methods, (size_t) numMethods});
480378
}

0 commit comments

Comments
 (0)