Skip to content

Commit

Permalink
Remove Riru support
Browse files Browse the repository at this point in the history
The repository RikkaApps/Riru is archived since Jan 8, 2024, which
recommends Zygisk as its alternative.
  • Loading branch information
JingMatrix committed Sep 23, 2024
1 parent ea2e1c8 commit 4d8e011
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 533 deletions.
16 changes: 0 additions & 16 deletions .github/workflows/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,27 +104,11 @@ jobs:
if: success()
id: prepareArtifact
run: |
riruReleaseName=`ls magisk-loader/release/LSPosed-v*-riru-release.zip | awk -F '(/|.zip)' '{print $3}'` && echo "riruReleaseName=$riruReleaseName" >> $GITHUB_OUTPUT
riruDebugName=`ls magisk-loader/release/LSPosed-v*-riru-debug.zip | awk -F '(/|.zip)' '{print $3}'` && echo "riruDebugName=$riruDebugName" >> $GITHUB_OUTPUT
zygiskReleaseName=`ls magisk-loader/release/LSPosed-v*-zygisk-release.zip | awk -F '(/|.zip)' '{print $3}'` && echo "zygiskReleaseName=$zygiskReleaseName" >> $GITHUB_OUTPUT
zygiskDebugName=`ls magisk-loader/release/LSPosed-v*-zygisk-debug.zip | awk -F '(/|.zip)' '{print $3}'` && echo "zygiskDebugName=$zygiskDebugName" >> $GITHUB_OUTPUT
unzip magisk-loader/release/LSPosed-v*-riru-release.zip -d LSPosed-riru-release
unzip magisk-loader/release/LSPosed-v*-riru-debug.zip -d LSPosed-riru-debug
unzip magisk-loader/release/LSPosed-v*-zygisk-release.zip -d LSPosed-zygisk-release
unzip magisk-loader/release/LSPosed-v*-zygisk-debug.zip -d LSPosed-zygisk-debug
- name: Upload riru release
uses: actions/upload-artifact@v4
with:
name: ${{ steps.prepareArtifact.outputs.riruReleaseName }}
path: "./LSPosed-riru-release/*"

- name: Upload riru debug
uses: actions/upload-artifact@v4
with:
name: ${{ steps.prepareArtifact.outputs.riruDebugName }}
path: "./LSPosed-riru-debug/*"

- name: Upload zygisk release
uses: actions/upload-artifact@v4
with:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Introduction

A Riru / Zygisk module trying to provide an ART hooking framework which delivers consistent APIs with the OG Xposed, leveraging LSPlant hooking framework.
A Zygisk module trying to provide an ART hooking framework which delivers consistent APIs with the OG Xposed, leveraging LSPlant hooking framework.

> Xposed is a framework for modules that can change the behavior of the system and apps without touching any APKs. That's great because it means that modules can work for different versions and even ROMs without any changes (as long as the original code was not changed too much). It's also easy to undo. As all changes are done in the memory, you just need to deactivate the module and reboot to get your original system back. There are many other advantages, but here is just one more: multiple modules can do changes to the same part of the system or app. With modified APKs, you have to choose one. No way to combine them, unless the author builds multiple APKs with different combinations.
Expand Down Expand Up @@ -55,13 +55,13 @@ You can contribute translation [here](https://crowdin.com/project/lsposed_jingma
## Credits

- [Magisk](https://github.com/topjohnwu/Magisk/): makes all these possible
- [Riru](https://github.com/RikkaApps/Riru): provides a way to inject code into zygote process
- [XposedBridge](https://github.com/rovo89/XposedBridge): the OG Xposed framework APIs
- [LSPlt](https://github.com/LSPosed/LSPlt): used for (Android 15) `libart` inline hooking
- [Dobby](https://github.com/JingMatrix/Dobby): used for fallback and `native_api` inline hooking
- [LSPlant](https://github.com/JingMatrix/LSPlant): the core ART hooking framework
- [EdXposed](https://github.com/ElderDrivers/EdXposed): fork source
- [xz-embedded](https://github.com/tukaani-project/xz-embedded): decompress `.gnu_debugdata` header section of stripped `libart.so`
- ~~[Riru](https://github.com/RikkaApps/Riru): provides a way to inject code into zygote process~~
- ~[SandHook](https://github.com/ganyao114/SandHook/): ART hooking framework for SandHook variant~
- ~[YAHFA](https://github.com/rk700/YAHFA): previous ART hooking framework~
- ~[dexmaker](https://github.com/linkedin/dexmaker) and [dalvikdx](https://github.com/JakeWharton/dalvik-dx): to dynamically generate YAHFA hooker classes~
Expand Down
178 changes: 90 additions & 88 deletions daemon/src/main/jni/logcat.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#include "logcat.h"

#include <android/log.h>
#include <jni.h>
#include <sys/system_properties.h>
#include <unistd.h>
#include <string>
#include <android/log.h>

#include <array>
#include <atomic>
#include <cinttypes>
#include <chrono>
#include <thread>
#include <cinttypes>
#include <functional>
#include <sys/system_properties.h>
#include <string>
#include <thread>

using namespace std::string_view_literals;
using namespace std::chrono_literals;
Expand All @@ -19,74 +20,75 @@ constexpr size_t kMaxLogSize = 4 * 1024 * 1024;
constexpr size_t kLogBufferSize = 64 * 1024;

namespace {
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
/*ANDROID_LOG_UNKNOWN*/'?',
/*ANDROID_LOG_DEFAULT*/ '?',
/*ANDROID_LOG_VERBOSE*/ 'V',
/*ANDROID_LOG_DEBUG*/ 'D',
/*ANDROID_LOG_INFO*/'I',
/*ANDROID_LOG_WARN*/'W',
/*ANDROID_LOG_ERROR*/ 'E',
/*ANDROID_LOG_FATAL*/ 'F',
/*ANDROID_LOG_SILENT*/ 'S',
};

size_t ParseUint(const char *s) {
if (s[0] == '\0') return -1;

while (isspace(*s)) {
s++;
}
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
/*ANDROID_LOG_UNKNOWN*/ '?',
/*ANDROID_LOG_DEFAULT*/ '?',
/*ANDROID_LOG_VERBOSE*/ 'V',
/*ANDROID_LOG_DEBUG*/ 'D',
/*ANDROID_LOG_INFO*/ 'I',
/*ANDROID_LOG_WARN*/ 'W',
/*ANDROID_LOG_ERROR*/ 'E',
/*ANDROID_LOG_FATAL*/ 'F',
/*ANDROID_LOG_SILENT*/ 'S',
};

if (s[0] == '-') {
return -1;
}
size_t ParseUint(const char *s) {
if (s[0] == '\0') return -1;

int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
char *end;
auto result = strtoull(s, &end, base);
if (end == s) {
return -1;
}
if (*end != '\0') {
const char *suffixes = "bkmgtpe";
const char *suffix;
if ((suffix = strchr(suffixes, tolower(*end))) == nullptr ||
__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) {
return -1;
}
}
if (std::numeric_limits<size_t>::max() < result) {
return -1;
}
return static_cast<size_t>(result);
while (isspace(*s)) {
s++;
}

inline size_t GetByteProp(std::string_view prop, size_t def = -1) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return ParseUint(buf.data());
if (s[0] == '-') {
return -1;
}

inline std::string GetStrProp(std::string_view prop, std::string def = {}) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return {buf.data()};
int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
char *end;
auto result = strtoull(s, &end, base);
if (end == s) {
return -1;
}

inline bool SetIntProp(std::string_view prop, int val) {
auto buf = std::to_string(val);
return __system_property_set(prop.data(), buf.data()) >= 0;
if (*end != '\0') {
const char *suffixes = "bkmgtpe";
const char *suffix;
if ((suffix = strchr(suffixes, tolower(*end))) == nullptr ||
__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) {
return -1;
}
}

inline bool SetStrProp(std::string_view prop, std::string_view val) {
return __system_property_set(prop.data(), val.data()) >= 0;
if (std::numeric_limits<size_t>::max() < result) {
return -1;
}
return static_cast<size_t>(result);
}

inline size_t GetByteProp(std::string_view prop, size_t def = -1) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return ParseUint(buf.data());
}

inline std::string GetStrProp(std::string_view prop, std::string def = {}) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return {buf.data()};
}

inline bool SetIntProp(std::string_view prop, int val) {
auto buf = std::to_string(val);
return __system_property_set(prop.data(), buf.data()) >= 0;
}

inline bool SetStrProp(std::string_view prop, std::string_view val) {
return __system_property_set(prop.data(), val.data()) >= 0;
}

} // namespace

class UniqueFile : public std::unique_ptr<FILE, std::function<void(FILE *)>> {
inline static deleter_type deleter = [](auto f) { f && f != stdout && fclose(f); };
inline static deleter_type deleter = [](auto f) { f &&f != stdout &&fclose(f); };

public:
explicit UniqueFile(FILE *f) : std::unique_ptr<FILE, std::function<void(FILE *)>>(f, deleter) {}

Expand All @@ -97,8 +99,8 @@ class UniqueFile : public std::unique_ptr<FILE, std::function<void(FILE *)>> {

class Logcat {
public:
explicit Logcat(JNIEnv *env, jobject thiz, jmethodID method) :
env_(env), thiz_(thiz), refresh_fd_method_(method) {}
explicit Logcat(JNIEnv *env, jobject thiz, jmethodID method)
: env_(env), thiz_(thiz), refresh_fd_method_(method) {}

[[noreturn]] void Run();

Expand Down Expand Up @@ -136,7 +138,7 @@ class Logcat {
size_t Logcat::PrintLogLine(const AndroidLogEntry &entry, FILE *out) {
if (!out) return 0;
constexpr static size_t kMaxTimeBuff = 64;
struct tm tm{};
struct tm tm {};
std::array<char, kMaxTimeBuff> time_buff{};

auto now = entry.tv_sec;
Expand All @@ -151,12 +153,10 @@ size_t Logcat::PrintLogLine(const AndroidLogEntry &entry, FILE *out) {
}
localtime_r(&now, &tm);
strftime(time_buff.data(), time_buff.size(), "%Y-%m-%dT%H:%M:%S", &tm);
int len = fprintf(out, "[ %s.%03ld %8d:%6d:%6d %c/%-15.*s ] %.*s\n",
time_buff.data(),
nsec / MS_PER_NSEC,
entry.uid, entry.pid, entry.tid,
kLogChar[entry.priority], static_cast<int>(entry.tagLen),
entry.tag, static_cast<int>(message_len), message);
int len =
fprintf(out, "[ %s.%03ld %8d:%6d:%6d %c/%-15.*s ] %.*s\n", time_buff.data(),
nsec / MS_PER_NSEC, entry.uid, entry.pid, entry.tid, kLogChar[entry.priority],
static_cast<int>(entry.tagLen), entry.tag, static_cast<int>(message_len), message);
fflush(out);
// trigger overflow when failed to generate a new fd
if (len <= 0) len = kMaxLogSize;
Expand Down Expand Up @@ -222,13 +222,13 @@ void Logcat::ProcessBuffer(struct log_msg *buf) {

std::string_view tag(entry.tag, entry.tagLen);
bool shortcut = false;
if (tag == "LSPosed-Bridge"sv || tag == "XSharedPreferences"sv || tag == "LSPosedContext") [[unlikely]] {
if (tag == "LSPosed-Bridge"sv || tag == "XSharedPreferences"sv || tag == "LSPosedContext")
[[unlikely]] {
modules_print_count_ += PrintLogLine(entry, modules_file_.get());
shortcut = true;
}
if (verbose_ && (shortcut || buf->id() == log_id::LOG_ID_CRASH ||
entry.pid == my_pid_ || tag == "Magisk"sv || tag == "LSPlt"sv ||
tag.starts_with("Riru"sv) || tag.starts_with("zygisk"sv) ||
if (verbose_ && (shortcut || buf->id() == log_id::LOG_ID_CRASH || entry.pid == my_pid_ ||
tag == "Magisk"sv || tag == "LSPlt"sv || tag.starts_with("zygisk"sv) ||
tag == "LSPlant"sv || tag.starts_with("LSPosed"sv))) [[unlikely]] {
verbose_print_count_ += PrintLogLine(entry, verbose_file_.get());
}
Expand Down Expand Up @@ -270,8 +270,7 @@ void Logcat::EnsureLogWatchDog() {
!((logd_main_size == kErr && logd_crash_size == kErr && logd_size != kErr &&
logd_size >= kLogBufferSize) ||
(logd_main_size != kErr && logd_main_size >= kLogBufferSize &&
logd_crash_size != kErr &&
logd_crash_size >= kLogBufferSize))) {
logd_crash_size != kErr && logd_crash_size >= kLogBufferSize))) {
SetIntProp(kLogdSizeProp, std::max(kLogBufferSize, logd_size));
SetIntProp(kLogdMainSizeProp, std::max(kLogBufferSize, logd_main_size));
SetIntProp(kLogdCrashSizeProp, std::max(kLogBufferSize, logd_crash_size));
Expand All @@ -281,14 +280,15 @@ void Logcat::EnsureLogWatchDog() {
const auto *pi = __system_property_find(kLogdTagProp.data());
uint32_t serial = 0;
if (pi != nullptr) {
__system_property_read_callback(pi, [](auto *c, auto, auto, auto s) {
*reinterpret_cast<uint32_t *>(c) = s;
}, &serial);
__system_property_read_callback(
pi, [](auto *c, auto, auto, auto s) { *reinterpret_cast<uint32_t *>(c) = s; },
&serial);
}
if (!__system_property_wait(pi, serial, &serial, nullptr)) break;
if (pi != nullptr) {
if (enable_watchdog) Log("\nResetting log settings\n");
} else std::this_thread::sleep_for(1s);
} else
std::this_thread::sleep_for(1s);
// log tag prop was not found; to avoid frequently trigger wait, sleep for a while
}
});
Expand All @@ -306,35 +306,37 @@ void Logcat::Run() {

while (true) {
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
android_logger_list_alloc(0, tail, 0), &android_logger_list_free};
android_logger_list_alloc(0, tail, 0), &android_logger_list_free};
tail = tail_after_crash;

for (log_id id:{LOG_ID_MAIN, LOG_ID_CRASH}) {
for (log_id id : {LOG_ID_MAIN, LOG_ID_CRASH}) {
auto *logger = android_logger_open(logger_list.get(), id);
if (logger == nullptr) continue;
if (auto size = android_logger_get_log_size(logger);
size >= 0 && static_cast<size_t>(size) < kLogBufferSize) {
size >= 0 && static_cast<size_t>(size) < kLogBufferSize) {
android_logger_set_log_size(logger, kLogBufferSize);
}
}

struct log_msg msg{};
struct log_msg msg {};

while (true) {
if (android_logger_list_read(logger_list.get(), &msg) <= 0) [[unlikely]] break;
if (android_logger_list_read(logger_list.get(), &msg) <= 0) [[unlikely]]
break;

ProcessBuffer(&msg);

if (verbose_print_count_ >= kMaxLogSize) [[unlikely]] RefreshFd(true);
if (modules_print_count_ >= kMaxLogSize) [[unlikely]] RefreshFd(false);
if (verbose_print_count_ >= kMaxLogSize) [[unlikely]]
RefreshFd(true);
if (modules_print_count_ >= kMaxLogSize) [[unlikely]]
RefreshFd(false);
}

OnCrash(errno);
}
}

extern "C"
JNIEXPORT void JNICALL
extern "C" JNIEXPORT void JNICALL
// NOLINTNEXTLINE
Java_org_lsposed_lspd_service_LogcatService_runLogcat(JNIEnv *env, jobject thiz) {
jclass clazz = env->GetObjectClass(thiz);
Expand Down
Loading

0 comments on commit 4d8e011

Please sign in to comment.