diff --git a/.gitmodules b/.gitmodules index b19adfd..f1521c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "module/jni/system_properties"] path = module/jni/system_properties url = https://github.com/topjohnwu/system_properties +[submodule "module/jni/aosp_fd_utils"] + path = module/jni/aosp_fd_utils + url = https://github.com/snake-4/aosp_fd_utils.git diff --git a/module/jni/Android.mk b/module/jni/Android.mk index 7d86b01..c1e7cb1 100644 --- a/module/jni/Android.mk +++ b/module/jni/Android.mk @@ -3,10 +3,11 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/elfio LOCAL_MODULE := zygisk -LOCAL_SRC_FILES := utils.cpp map_parser.cpp mountinfo_parser.cpp modules.cpp main.cpp -LOCAL_STATIC_LIBRARIES := libcxx libsystemproperties +LOCAL_SRC_FILES := fd_reopener.cpp utils.cpp map_parser.cpp mountinfo_parser.cpp modules.cpp main.cpp +LOCAL_STATIC_LIBRARIES := libcxx libsystemproperties libfdutils LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) include jni/libcxx/Android.mk -include jni/system_properties/Android.mk \ No newline at end of file +include jni/system_properties/Android.mk +include jni/aosp_fd_utils/Android.mk diff --git a/module/jni/aosp_fd_utils b/module/jni/aosp_fd_utils new file mode 160000 index 0000000..303bcb1 --- /dev/null +++ b/module/jni/aosp_fd_utils @@ -0,0 +1 @@ +Subproject commit 303bcb1577a22025e59d433bf5ac1c87ba429897 diff --git a/module/jni/fd_reopener.cpp b/module/jni/fd_reopener.cpp new file mode 100644 index 0000000..e536a94 --- /dev/null +++ b/module/jni/fd_reopener.cpp @@ -0,0 +1,33 @@ +#include "fd_reopener.hpp" +#include +#include +#include +#include "logging.hpp" + +FDReopener::ScopedRegularReopener::ScopedRegularReopener() +{ + auto pFdSet = GetOpenFds([](const std::string &error) + { LOGE("GetOpenFds: %s", error.c_str()); }); + if (pFdSet) + { + for (const auto &fd : *pFdSet) + { + auto pFDI = FileDescriptorInfo::CreateFromFd(fd, [fd](const std::string &error) + { LOGE("CreateFromFd(%d): %s", fd, error.c_str()); }); + + // Only process regular files that are not memfds + if (pFDI && !pFDI->is_sock && !pFDI->file_path.starts_with("/memfd:")) + fdi_vector.emplace_back(std::move(pFDI)); + } + } +} + +FDReopener::ScopedRegularReopener::~ScopedRegularReopener() +{ + for (const auto &pFDI : fdi_vector) + { + LOGD("Reopening FD %d with %s", pFDI->fd, pFDI->file_path.c_str()); + pFDI->ReopenOrDetach([fd = pFDI->fd](const std::string &error) + { LOGE("ReopenOrDetach(%d): %s", fd, error.c_str()); }); + } +} diff --git a/module/jni/include/fd_reopener.hpp b/module/jni/include/fd_reopener.hpp new file mode 100644 index 0000000..dc31710 --- /dev/null +++ b/module/jni/include/fd_reopener.hpp @@ -0,0 +1,19 @@ +#pragma once +#include "fd_utils.h" +#include +#include + +namespace FDReopener +{ + class ScopedRegularReopener + { + public: + ScopedRegularReopener(); + ~ScopedRegularReopener(); + + private: + ScopedRegularReopener(const ScopedRegularReopener &); + void operator=(const ScopedRegularReopener &); + std::vector> fdi_vector; + }; +} diff --git a/module/jni/main.cpp b/module/jni/main.cpp index 99e5d65..71b6092 100644 --- a/module/jni/main.cpp +++ b/module/jni/main.cpp @@ -9,6 +9,7 @@ #include "logging.hpp" #include "utils.hpp" #include "modules.hpp" +#include "fd_reopener.hpp" using zygisk::Api; using zygisk::AppSpecializeArgs; @@ -46,6 +47,8 @@ DCL_HOOK_FUNC(static int, unshare, int flags) /* * The reason why we hook setresuid is because so far it has been unconditionally called * and we still have CAP_SYS_ADMIN during this call. + * Also, KSU hooks setuid and unmounts some overlays + * so we have to run our code before the syscall. */ DCL_HOOK_FUNC(static int, setresuid, uid_t ruid, uid_t euid, uid_t suid) { @@ -97,6 +100,8 @@ class ZygiskModule : public zygisk::ModuleBase callbackFunction = [fd = companionFd]() { + FDReopener::ScopedRegularReopener srr; + bool result = false; if (fd != -1) {