Log to zygiskd

This commit is contained in:
Nullptr
2023-02-08 14:49:32 +08:00
parent 4ecb4a9276
commit 814476ea7a
14 changed files with 180 additions and 51 deletions

View File

@@ -29,7 +29,6 @@ namespace zygiskd {
}
bool PingHeartbeat() {
LOGD("Daemon socket: %s", kZygiskSocket.data());
UniqueFd fd = Connect(5);
if (fd == -1) {
PLOGE("Connect to zygiskd");
@@ -39,6 +38,16 @@ namespace zygiskd {
return true;
}
int RequestLogcatFd() {
int fd = Connect(1);
if (fd == -1) {
PLOGE("RequestLogcatFd");
return -1;
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestLogcatFd);
return fd;
}
std::string ReadNativeBridge() {
UniqueFd fd = Connect(1);
if (fd == -1) {

View File

@@ -0,0 +1,36 @@
#include <android/log.h>
#include <unistd.h>
#include "logging.h"
#include "socket_utils.h"
namespace logging {
static int logfd = -1;
void setfd(int fd) {
close(logfd);
logfd = fd;
}
int getfd() {
return logfd;
}
void log(int prio, const char* tag, const char* fmt, ...) {
if (logfd == -1) {
va_list ap;
va_start(ap, fmt);
__android_log_vprint(prio, tag, fmt, ap);
va_end(ap);
} else {
char buf[BUFSIZ];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
socket_utils::write_u8(logfd, prio);
socket_utils::write_string(logfd, tag);
socket_utils::write_string(logfd, buf);
}
}
}

View File

@@ -110,6 +110,10 @@ namespace socket_utils {
return write_exact<uint8_t>(fd, val);
}
bool write_string(int fd, std::string_view str) {
return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size());
}
int recv_fd(int sockfd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];

View File

@@ -52,6 +52,7 @@ namespace zygiskd {
enum class SocketAction {
PingHeartBeat,
RequestLogcatFd,
ReadNativeBridge,
ReadModules,
RequestCompanionSocket,
@@ -60,6 +61,8 @@ namespace zygiskd {
bool PingHeartbeat();
int RequestLogcatFd();
std::string ReadNativeBridge();
std::vector<Module> ReadModules();

View File

@@ -20,15 +20,24 @@
#define LOGE(...)
#else
#ifndef NDEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#else
#define LOGD(...)
#define LOGV(...)
#endif
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
#define LOGI(...) logging::log(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) logging::log(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) logging::log(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGF(...) logging::log(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
#endif
namespace logging {
void setfd(int fd);
int getfd();
[[gnu::format(printf, 3, 4)]]
void log(int prio, const char* tag, const char* fmt, ...);
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <string_view>
#include "logging.h"
@@ -21,4 +22,6 @@ namespace socket_utils {
int recv_fd(int fd);
bool write_usize(int fd, size_t val);
bool write_string(int fd, std::string_view str);
}

View File

@@ -1,3 +1,4 @@
#include "daemon.h"
#include "logging.h"
#include "zygisk.hpp"
#include "module.hpp"
@@ -17,8 +18,10 @@ static void zygisk_cleanup_wait() {
extern "C" [[gnu::visibility("default")]]
void entry(void *handle) {
LOGD("Load injector successfully");
logging::setfd(zygiskd::RequestLogcatFd());
self_handle = handle;
LOGD("Load injector successfully");
hook_functions();
}

View File

@@ -204,7 +204,17 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
return res;
}
/* Zygisksu changed: No android_log_close hook */
// Close logd_fd if necessary to prevent crashing
// For more info, check comments in zygisk_log_write
DCL_HOOK_FUNC(void, android_log_close) {
if (g_ctx == nullptr) {
// Happens during un-managed fork like nativeForkApp, nativeForkUsap
logging::setfd(-1);
} else if (!g_ctx->flags[SKIP_FD_SANITIZATION]) {
logging::setfd(-1);
}
old_android_log_close();
}
// Last point before process secontext changes
DCL_HOOK_FUNC(int, selinux_android_setcontext,
@@ -595,7 +605,7 @@ void HookContext::app_specialize_post() {
// Cleanups
env->ReleaseStringUTFChars(args.app->nice_name, process);
g_ctx = nullptr;
/* Zygisksu changed: No android_log_close */
logging::setfd(-1);
}
void HookContext::unload_zygisk() {
@@ -668,7 +678,9 @@ void HookContext::nativeForkAndSpecialize_pre() {
flags[APP_FORK_AND_SPECIALIZE] = true;
/* Zygisksu changed: No args.app->fds_to_ignore check since we are Android 10+ */
flags[SKIP_FD_SANITIZATION] = true;
if (logging::getfd() != -1) {
exempted_fds.push_back(logging::getfd());
}
fork_pre();
if (pid == 0) {
@@ -729,7 +741,7 @@ void hook_functions() {
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, jniRegisterNativeMethods);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, selinux_android_setcontext);
/* Zygisksu changed: No android_log_close hook */
PLT_HOOK_REGISTER_SYM(android_runtime_dev, android_runtime_inode, "__android_log_close", android_log_close);
hook_commit();
// Remove unhooked methods

View File

@@ -42,9 +42,10 @@ void Constructor() {
std::string native_bridge;
do {
LOGD("Ping heartbeat");
if (!zygiskd::PingHeartbeat()) break;
logging::setfd(zygiskd::RequestLogcatFd());
LOGI("Read native bridge");
native_bridge = zygiskd::ReadNativeBridge();
@@ -63,32 +64,37 @@ void Constructor() {
reinterpret_cast<void (*)(void*)>(entry)(handle);
} while (false);
if (native_bridge.empty() || native_bridge == "0") return;
LOGI("Load original native bridge: %s", native_bridge.data());
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
if (sOriginalBridge == nullptr) {
LOGE("dlopen failed: %s", dlerror());
return;
}
do {
if (native_bridge.empty() || native_bridge == "0") break;
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
if (original_native_bridge_itf == nullptr) {
LOGE("dlsym failed: %s", dlerror());
return;
}
LOGI("Load original native bridge: %s", native_bridge.data());
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
if (sOriginalBridge == nullptr) {
LOGE("dlopen failed: %s", dlerror());
break;
}
long sdk = 0;
char value[PROP_VALUE_MAX + 1];
if (__system_property_get("ro.build.version.sdk", value) > 0) {
sdk = strtol(value, nullptr, 10);
}
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
if (original_native_bridge_itf == nullptr) {
LOGE("dlsym failed: %s", dlerror());
break;
}
auto callbacks_size = 0;
if (sdk >= __ANDROID_API_R__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_R__>);
} else if (sdk == __ANDROID_API_Q__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_Q__>);
}
long sdk = 0;
char value[PROP_VALUE_MAX + 1];
if (__system_property_get("ro.build.version.sdk", value) > 0) {
sdk = strtol(value, nullptr, 10);
}
memcpy(NativeBridgeItf, original_native_bridge_itf, callbacks_size);
auto callbacks_size = 0;
if (sdk >= __ANDROID_API_R__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_R__>);
} else if (sdk == __ANDROID_API_Q__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_Q__>);
}
memcpy(NativeBridgeItf, original_native_bridge_itf, callbacks_size);
} while (false);
logging::setfd(-1);
}