Commit 6e299018 authored by topjohnwu's avatar topjohnwu

Preserve logd_fd after specialization

Also add more comments regarding FD checks
parent 555a54ec
...@@ -125,27 +125,28 @@ static void *logfile_writer(void *arg) { ...@@ -125,27 +125,28 @@ static void *logfile_writer(void *arg) {
} }
void magisk_log_write(int prio, const char *msg, int len) { void magisk_log_write(int prio, const char *msg, int len) {
if (logd_fd >= 0) { if (logd_fd < 0)
// Truncate return;
len = std::min(MAX_MSG_LEN, len);
// Truncate
log_meta meta = { len = std::min(MAX_MSG_LEN, len);
.prio = prio,
.len = len, log_meta meta = {
.pid = getpid(), .prio = prio,
.tid = gettid() .len = len,
}; .pid = getpid(),
.tid = gettid()
iovec iov[2]; };
iov[0].iov_base = &meta;
iov[0].iov_len = sizeof(meta); iovec iov[2];
iov[1].iov_base = (void *) msg; iov[0].iov_base = &meta;
iov[1].iov_len = len; iov[0].iov_len = sizeof(meta);
iov[1].iov_base = (void *) msg;
if (writev(logd_fd, iov, 2) < 0) { iov[1].iov_len = len;
// Stop trying to write to file
close(logd_fd.exchange(-1)); if (writev(logd_fd, iov, 2) < 0) {
} // Stop trying to write to file
close(logd_fd.exchange(-1));
} }
} }
......
...@@ -76,36 +76,51 @@ extern "C" void zygisk_inject_entry(void *handle) { ...@@ -76,36 +76,51 @@ extern "C" void zygisk_inject_entry(void *handle) {
// The following code runs in zygote/app process // The following code runs in zygote/app process
extern "C" void zygisk_log_write(int prio, const char *msg, int len) { extern "C" void zygisk_log_write(int prio, const char *msg, int len) {
// If we don't have log pipe set, ask magiskd for it // If we don't have the log pipe set, request magiskd for it. This could actually happen
// This could happen multiple times in zygote because it was closed to prevent crashing // multiple times in the zygote daemon (parent process) because we had to close this
// file descriptor to prevent crashing.
//
// For some reason, zygote sanitizes and checks FDs *before* forking. This results in the fact
// that *every* time before zygote forks, it has to close all logging related FDs in order
// to pass FD checks, just to have it re-initialized immediately after any
// logging happens ¯\_(ツ)_/¯.
//
// To be consistent with this behavior, we also have to close the log pipe to magiskd
// to make zygote NOT crash if necessary. For nativeForkAndSpecialize, we can actually
// add this FD into fds_to_ignore to pass the check. For other cases, we accomplish this by
// hooking __android_log_close and closing it at the same time as the rest of logging FDs.
if (logd_fd < 0) { if (logd_fd < 0) {
// Change logging temporarily to prevent infinite recursion and stack overflow
android_logging(); android_logging();
if (int fd = zygisk_request(ZygiskRequest::GET_LOG_PIPE); fd >= 0) { if (int fd = zygisk_request(ZygiskRequest::GET_LOG_PIPE); fd >= 0) {
int log_pipe = -1;
if (read_int(fd) == 0) { if (read_int(fd) == 0) {
logd_fd = recv_fd(fd); log_pipe = recv_fd(fd);
} }
close(fd); close(fd);
if (log_pipe >= 0) {
// Only re-enable zygisk logging if possible
logd_fd = log_pipe;
zygisk_logging();
}
} else {
return;
} }
zygisk_logging();
} }
// Block SIGPIPE
sigset_t mask; sigset_t mask;
sigset_t orig_mask; sigset_t orig_mask;
bool sig = false; sigemptyset(&mask);
// Make sure SIGPIPE won't crash zygote sigaddset(&mask, SIGPIPE);
if (logd_fd >= 0) { pthread_sigmask(SIG_BLOCK, &mask, &orig_mask);
sig = true;
sigemptyset(&mask);
sigaddset(&mask, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &mask, &orig_mask);
}
magisk_log_write(prio, msg, len); magisk_log_write(prio, msg, len);
if (sig) {
timespec ts{}; // Consume SIGPIPE if exists, then restore mask
sigtimedwait(&mask, nullptr, &ts); timespec ts{};
pthread_sigmask(SIG_SETMASK, &orig_mask, nullptr); sigtimedwait(&mask, nullptr, &ts);
} pthread_sigmask(SIG_SETMASK, &orig_mask, nullptr);
} }
static inline bool should_load_modules(uint32_t flags) { static inline bool should_load_modules(uint32_t flags) {
......
This diff is collapsed.
...@@ -173,7 +173,7 @@ struct ZygiskModule { ...@@ -173,7 +173,7 @@ struct ZygiskModule {
ZygiskModule(int id, void *handle, void *entry); ZygiskModule(int id, void *handle, void *entry);
static bool RegisterModule(api_abi_base *api, long *module); static bool RegisterModuleImpl(api_abi_base *api, long *module);
private: private:
const int id; const int id;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment