diff --git a/daemon/src/main/kotlin/org/matrix/vector/daemon/VectorDaemon.kt b/daemon/src/main/kotlin/org/matrix/vector/daemon/VectorDaemon.kt index d1d398c3a..a53862c91 100644 --- a/daemon/src/main/kotlin/org/matrix/vector/daemon/VectorDaemon.kt +++ b/daemon/src/main/kotlin/org/matrix/vector/daemon/VectorDaemon.kt @@ -102,10 +102,17 @@ object VectorDaemon { applyNotificationWorkaround() + // Read this before `sendToBridge`, which leaves the main thread at euid 1000: the config + // database lives under a directory only root can enter, so the first process to open it has + // to do so while we still have root. On a successful injection a binder thread opens it for + // us during specialization, but when the injection fails nothing else has, and the daemon + // used to die here on an unreadable preference. + val isVerboseLog = ManagerService.isVerboseLog() + // Setup IPC channel for applications by injecting DaemonService binder sendToBridge(VectorService.asBinder(), false, systemServerMaxRetry) - if (!ManagerService.isVerboseLog()) { + if (!isVerboseLog) { LogcatMonitor.stopVerbose() } diff --git a/zygisk/src/main/cpp/ipc_bridge.cpp b/zygisk/src/main/cpp/ipc_bridge.cpp index 71217c6d4..bc19adfd8 100644 --- a/zygisk/src/main/cpp/ipc_bridge.cpp +++ b/zygisk/src/main/cpp/ipc_bridge.cpp @@ -290,9 +290,9 @@ lsplant::ScopedLocalRef IPCBridge::RequestAppBinder(JNIEnv *env, jstrin env->NewGlobalRef(heartbeat_binder.get()); } } - } else { - LOGD("Transact call to request app binder failed."); } + // No else: a false transaction is the daemon declining, which is the ordinary answer for a + // process no module has in scope. The caller logs that outcome, with the process name. return result_binder; } diff --git a/zygisk/src/main/cpp/module.cpp b/zygisk/src/main/cpp/module.cpp index 7753b3d1b..0dbb21472 100644 --- a/zygisk/src/main/cpp/module.cpp +++ b/zygisk/src/main/cpp/module.cpp @@ -324,12 +324,14 @@ void VectorModule::postAppSpecialize(const zygisk::AppSpecializeArgs *args) { // --- Framework Injection --- lsplant::JUTFString nice_name_str(env_, args->nice_name); - LOGD("Attempting injection into '{}'.", nice_name_str.get()); + LOGD("Asking the daemon about '{}'.", nice_name_str.get()); auto &ipc_bridge = IPCBridge::GetInstance(); auto binder = ipc_bridge.RequestAppBinder(env_, args->nice_name); if (!binder) { - LOGD("No IPC binder obtained for '{}'. Skipping injection.", nice_name_str.get()); + // Usually because nothing has it in scope, but the daemon may also not be up yet or have + // registered this process already. Only it knows which, and it logs the reason itself. + LOGD("Not injecting '{}': the daemon has no binder for it.", nice_name_str.get()); SetAllowUnload(true); return; }