Skip to content

Commit

Permalink
Support unload self and module
Browse files Browse the repository at this point in the history
  • Loading branch information
RikkaW committed Mar 14, 2021
1 parent 0f78ff8 commit bef0b0c
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 84 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ ext {
minSdkVersion = 23
targetSdkVersion = 30

riruApiVersion = 24
riruApiVersion = 25
riruMinApiVersion = 9
}

Expand Down
6 changes: 3 additions & 3 deletions riru/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ plugins {
def gitCommitId = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()
def gitCommitCount = Integer.parseInt('git rev-list --count HEAD'.execute([], project.rootDir).text.trim())

def versionNameMajor = 24
def versionNameMinor = 1
def versionNamePatch = 2
def versionNameMajor = rootProject.ext.riruApiVersion
def versionNameMinor = 0
def versionNamePatch = 0
def versionNameShort = "v${versionNameMajor}.${versionNameMinor}.${versionNamePatch}"
def versionName = "${versionNameShort}.r${gitCommitCount}.${gitCommitId}"
def versionCode = gitCommitCount
Expand Down
4 changes: 3 additions & 1 deletion riru/src/main/cpp/daemon.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef _MAIN_H
#define _MAIN_H

void RestoreEnvironment(JNIEnv *env, jboolean hide_maps);
void RestoreHooks(JNIEnv *env);

void Unload(jboolean hide_maps);

#endif // _MAIN_H
48 changes: 2 additions & 46 deletions riru/src/main/cpp/include_riru/riru.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ typedef struct {

typedef struct {
int riruApiVersion;
RiruApi *riruApi;
void *unused;
const char *magiskModulePath;
int *allowUnload;
} Riru;

typedef RiruVersionedModuleInfo *(RiruInit_t)(Riru *);
Expand All @@ -102,51 +103,6 @@ typedef RiruVersionedModuleInfo *(RiruInit_t)(Riru *);

RiruVersionedModuleInfo *init(Riru *riru) RIRU_EXPORT;

extern int riru_api_version;
extern RiruApi *riru_api;
extern const char *riru_magisk_module_path;

#if !defined(__cplusplus)
#define RIRU_INLINE __attribute__((always_inline))
#else
#define RIRU_INLINE inline
#endif

RIRU_INLINE const char *riru_get_magisk_module_path() {
if (riru_api_version >= 24) {
return riru_magisk_module_path;
}
return NULL;
}

RIRU_INLINE void *riru_get_func(const char *name) {
return riru_api->getFunc(riru_api->token, name);
}

RIRU_INLINE void *riru_get_native_method_func(const char *className, const char *name, const char *signature) {
return riru_api->getJNINativeMethodFunc(riru_api->token, className, name, signature);
}

RIRU_INLINE const JNINativeMethod *riru_get_original_native_methods(const char *className, const char *name, const char *signature) {
return riru_api->getOriginalJNINativeMethodFunc(className, name, signature);
}

RIRU_INLINE void riru_set_func(const char *name, void *func) {
riru_api->setFunc(riru_api->token, name, func);
}

RIRU_INLINE void riru_set_native_method_func(const char *className, const char *name, const char *signature, void *func) {
riru_api->setJNINativeMethodFunc(riru_api->token, className, name, signature, func);
}

RIRU_INLINE void *riru_get_global_value(const char *key) {
return riru_api->getGlobalValue(key);
}

RIRU_INLINE void riru_put_global_value(const char *key, void *value) {
riru_api->putGlobalValue(key, value);
}

#endif

#ifdef __cplusplus
Expand Down
40 changes: 30 additions & 10 deletions riru/src/main/cpp/jni_native_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ static void nativeForkAndSpecialize_pre(
if (!module->hasForkAndSpecializePre())
continue;

module->resetAllowUnload();

if (module->hasShouldSkipUid() && module->shouldSkipUid(uid))
continue;

Expand All @@ -63,8 +65,7 @@ static void nativeForkAndSpecialize_pre(

static void nativeForkAndSpecialize_post(JNIEnv *env, jclass clazz, jint uid, jboolean is_child_zygote, jint res) {

// On pre-29, child zygote is always webview zygote, webview zygote does not have execmem permission
if (res == 0) RestoreEnvironment(env, AndroidProp::GetApiLevel() < 29 && !is_child_zygote);
if (res == 0) RestoreHooks(env);

for (auto module : *get_modules()) {
if (!module->hasForkAndSpecializePost())
Expand Down Expand Up @@ -92,6 +93,9 @@ static void nativeForkAndSpecialize_post(JNIEnv *env, jclass clazz, jint uid, jb

module->forkAndSpecializePost(env, clazz, res);
}

// On pre-29, child zygote is always webview zygote, webview zygote does not have execmem permission
if (res == 0) Unload(AndroidProp::GetApiLevel() < 29 && !is_child_zygote);
}

// -----------------------------------------------------------------
Expand All @@ -107,24 +111,40 @@ static void nativeSpecializeAppProcess_pre(
if (!module->hasSpecializeAppProcessPre())
continue;

module->resetAllowUnload();

if (module->hasShouldSkipUid() && module->shouldSkipUid(uid))
continue;

if (!module->hasShouldSkipUid() && shouldSkipUid(uid))
continue;

module->specializeAppProcessPre(
env, clazz, &uid, &gid, &gids, &runtimeFlags, &rlimits, &mountExternal, &seInfo,
&niceName, &startChildZygote, &instructionSet, &appDataDir, &isTopApp,
&pkgDataInfoList, &whitelistedDataInfoList, &bindMountAppDataDirs, &bindMountAppStorageDirs);
}
}

static void nativeSpecializeAppProcess_post(JNIEnv *env, jclass clazz) {
static void nativeSpecializeAppProcess_post(JNIEnv *env, jclass clazz, jint uid) {

RestoreEnvironment(env, false);
RestoreHooks(env);

for (auto module : *get_modules()) {
if (!module->hasSpecializeAppProcessPost())
continue;

if (module->hasShouldSkipUid() && module->shouldSkipUid(uid))
continue;

if (!module->hasShouldSkipUid() && shouldSkipUid(uid))
continue;

LOGD("%s: specializeAppProcessPost", module->id);
module->specializeAppProcessPost(env, clazz);
}

Unload(false);
}

// -----------------------------------------------------------------
Expand Down Expand Up @@ -450,7 +470,7 @@ void nativeSpecializeAppProcess_q(
env, clazz, uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName,
startChildZygote, instructionSet, appDataDir);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}

void nativeSpecializeAppProcess_q_alternative(
Expand All @@ -473,7 +493,7 @@ void nativeSpecializeAppProcess_q_alternative(
env, clazz, uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName,
startChildZygote, instructionSet, appDataDir, isTopApp);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}

void nativeSpecializeAppProcess_r(
Expand All @@ -493,7 +513,7 @@ void nativeSpecializeAppProcess_r(
startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList,
whitelistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}

void nativeSpecializeAppProcess_r_dp3(
Expand All @@ -515,7 +535,7 @@ void nativeSpecializeAppProcess_r_dp3(
startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList,
bindMountAppStorageDirs);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}

void nativeSpecializeAppProcess_r_dp2(
Expand All @@ -537,7 +557,7 @@ void nativeSpecializeAppProcess_r_dp2(
env, clazz, uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName,
startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}


Expand All @@ -561,7 +581,7 @@ void nativeSpecializeAppProcess_samsung_q(
env, clazz, uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, space,
accessInfo, niceName, startChildZygote, instructionSet, appDataDir);

nativeSpecializeAppProcess_post(env, clazz);
nativeSpecializeAppProcess_post(env, clazz, uid);
}

// -----------------------------------------------------------------
Expand Down
12 changes: 11 additions & 1 deletion riru/src/main/cpp/loader/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,17 @@ __used __attribute__((constructor)) void constructor() {
#endif
strcat(riru_path, "/libriru.so");

dlopen_ext(riru_path, 0);
auto handle = dlopen_ext(riru_path, 0);
if (handle) {
auto init = (void(*)(void *)) dlsym(handle, "init");
if (init) {
init(handle);
} else {
LOGE("dlsym init %s", dlerror());
}
} else {
LOGE("dlopen riru.so %s", dlerror());
}

#ifdef HAS_NATIVE_BRIDGE

Expand Down
67 changes: 61 additions & 6 deletions riru/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <dlfcn.h>
#include <plt.h>
#include <android_prop.h>
#include <pthread.h>
#include "misc.h"
#include "jni_native_method.h"
#include "logging.h"
Expand All @@ -15,6 +16,9 @@
#include "config.h"
#include "magisk.h"

static void *self_handle;
static pthread_mutex_t self_close_mutext = PTHREAD_MUTEX_INITIALIZER;

static bool useTableOverride = false;

using GetJniNativeInterface_t = const JNINativeInterface *();
Expand Down Expand Up @@ -230,16 +234,26 @@ static int new_RegisterNative(JNIEnv *env, jclass cls, const JNINativeMethod *me
return res;
}

void SelfUnload() {
LOGD("attempt to self unload");

pthread_mutex_lock(&self_close_mutext);

pthread_t thread;
pthread_create(&thread, nullptr, (void *(*)(void *)) &dlclose, self_handle);
pthread_detach(thread);

pthread_mutex_unlock(&self_close_mutext);
}

#define restoreMethod(_cls, method) \
if (JNI::_cls::method != nullptr) { \
if (old_jniRegisterNativeMethods) \
old_jniRegisterNativeMethods(env, JNI::_cls::classname, JNI::_cls::method, 1); \
delete JNI::_cls::method; \
}

void RestoreEnvironment(JNIEnv *env, jboolean hide_maps) {
Hide::DoHide(false, hide_maps);

void RestoreHooks(JNIEnv *env) {
if (useTableOverride) {
setTableOverride(nullptr);
} else {
Expand All @@ -258,9 +272,45 @@ void RestoreEnvironment(JNIEnv *env, jboolean hide_maps) {
restoreMethod(SystemProperties, set)
}

extern "C" void constructor() __attribute__((constructor));
void Unload(jboolean hide_maps) {
Hide::DoHide(false, hide_maps);

bool allowUnload = true;
for (auto module : *get_modules()) {
if (strcmp(module->id, MODULE_NAME_CORE) == 0) {
continue;
}

if (module->allowUnload() != 0) {
LOGV("unload module %s", module->id);
dlclose(module->handle);
} else {
if (module->apiVersion >= 25)
LOGV("unload is not allow by module %s", module->id);
else
LOGV("unload is not supported by module %s (API < 25)", module->id);

allowUnload = false;
}
}

if (!allowUnload) {
LOGV("don't unload self because at least one module does not allow unload");
} else {
SelfUnload();
}
}

extern "C" __attribute__((destructor)) void destructor() {
pthread_mutex_lock(&self_close_mutext);

LOGI("self unload successful");

void constructor() {
timespec ts = {.tv_sec = 0, .tv_nsec = 1000000L};
nanosleep(&ts, nullptr);
}

extern "C" __attribute__((constructor)) void constructor() {
#ifdef DEBUG_APP
hide::hide_modules(nullptr, 0);
#endif
Expand All @@ -282,7 +332,8 @@ void constructor() {

LOGI("Riru %s (%d) in %s", RIRU_VERSION_NAME, RIRU_VERSION_CODE, cmdline);
LOGI("Magisk tmpfs path is %s", Magisk::GetPath());
LOGI("Android %s (api %d, preview_api %d)", AndroidProp::GetRelease(), AndroidProp::GetApiLevel(), AndroidProp::GetPreviewApiLevel());
LOGI("Android %s (api %d, preview_api %d)", AndroidProp::GetRelease(), AndroidProp::GetApiLevel(),
AndroidProp::GetPreviewApiLevel());

XHOOK_REGISTER(".*\\libandroid_runtime.so$", jniRegisterNativeMethods);

Expand Down Expand Up @@ -325,3 +376,7 @@ void constructor() {

Status::WriteSelfAndModules();
}

extern "C" __attribute__((visibility("default"))) __attribute__((used)) void init(void *handle) {
self_handle = handle;
}
Loading

0 comments on commit bef0b0c

Please sign in to comment.