Skip to content

Commit

Permalink
Fixed companion NS and moved code to namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
snake-4 committed Apr 27, 2024
1 parent e431fc2 commit 5c2ba2a
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 107 deletions.
39 changes: 21 additions & 18 deletions module/jni/include/map_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
#include <vector>
#include <sys/types.h>

class map_entry_t
namespace Parsers
{
public:
map_entry_t(uintptr_t address_start, uintptr_t address_end, uintptr_t offset,
const std::string &perms, const std::string &pathname, dev_t device, ino_t inode);
class map_entry_t
{
public:
map_entry_t(uintptr_t address_start, uintptr_t address_end, uintptr_t offset,
const std::string &perms, const std::string &pathname, dev_t device, ino_t inode);

uintptr_t getAddressStart() const;
uintptr_t getAddressEnd() const;
const std::string &getPerms() const;
uintptr_t getOffset() const;
dev_t getDevice() const;
ino_t getInode() const;
const std::string &getPathname() const;
uintptr_t getAddressStart() const;
uintptr_t getAddressEnd() const;
const std::string &getPerms() const;
uintptr_t getOffset() const;
dev_t getDevice() const;
ino_t getInode() const;
const std::string &getPathname() const;

private:
uintptr_t address_start, address_end, offset;
std::string perms, pathname;
dev_t device;
ino_t inode;
};
private:
uintptr_t address_start, address_end, offset;
std::string perms, pathname;
dev_t device;
ino_t inode;
};

const std::vector<map_entry_t> &parseSelfMaps(bool cached = true);
const std::vector<map_entry_t> &parseSelfMaps(bool cached = true);
}
36 changes: 19 additions & 17 deletions module/jni/include/mount_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@
#include <string>
#include <vector>
#include <unordered_map>

#include <mntent.h>

class mount_entry_t
namespace Parsers
{
public:
mount_entry_t(::mntent *entry);
const std::string &getFsName() const;
const std::string &getMountPoint() const;
const std::string &getType() const;
const std::unordered_map<std::string, std::string> &getOptions() const;
int getDumpFrequency() const;
int getPassNumber() const;
class mount_entry_t
{
public:
mount_entry_t(::mntent *entry);
const std::string &getFsName() const;
const std::string &getMountPoint() const;
const std::string &getType() const;
const std::unordered_map<std::string, std::string> &getOptions() const;
int getDumpFrequency() const;
int getPassNumber() const;

private:
std::string fsname, dir, type;
std::unordered_map<std::string, std::string> opts_map;
int freq, passno;
};
private:
std::string fsname, dir, type;
std::unordered_map<std::string, std::string> opts_map;
int freq, passno;
};

const std::vector<mount_entry_t> &parseSelfMounts(bool cached = true);
std::unordered_map<std::string, std::string> parseMountOptions(const std::string &input);
const std::vector<mount_entry_t> &parseSelfMounts(bool cached = true);
std::unordered_map<std::string, std::string> parseMountOptions(const std::string &input);
}
51 changes: 27 additions & 24 deletions module/jni/include/mountinfo_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,34 @@
#include <vector>
#include <unordered_map>

class mountinfo_entry_t
namespace Parsers
{
public:
mountinfo_entry_t(int mount_id, int parent_id, int major, int minor,
const std::string &root, const std::string &mount_point,
const std::string &mount_options, const std::string &optional_fields,
const std::string &filesystem_type, const std::string &mount_source,
const std::string &super_options);
class mountinfo_entry_t
{
public:
mountinfo_entry_t(int mount_id, int parent_id, int major, int minor,
const std::string &root, const std::string &mount_point,
const std::string &mount_options, const std::string &optional_fields,
const std::string &filesystem_type, const std::string &mount_source,
const std::string &super_options);

int getMountId() const;
int getParentId() const;
int getMajor() const;
int getMinor() const;
const std::string &getRoot() const;
const std::string &getMountPoint() const;
const std::unordered_map<std::string, std::string> &getMountOptions() const;
const std::string &getOptionalFields() const;
const std::string &getFilesystemType() const;
const std::string &getMountSource() const;
const std::unordered_map<std::string, std::string> &getSuperOptions() const;
int getMountId() const;
int getParentId() const;
int getMajor() const;
int getMinor() const;
const std::string &getRoot() const;
const std::string &getMountPoint() const;
const std::unordered_map<std::string, std::string> &getMountOptions() const;
const std::string &getOptionalFields() const;
const std::string &getFilesystemType() const;
const std::string &getMountSource() const;
const std::unordered_map<std::string, std::string> &getSuperOptions() const;

private:
int mount_id, parent_id, major, minor;
std::string root, mount_point, optional_fields, filesystem_type, mount_source;
std::unordered_map<std::string, std::string> mount_options, super_options;
};
private:
int mount_id, parent_id, major, minor;
std::string root, mount_point, optional_fields, filesystem_type, mount_source;
std::unordered_map<std::string, std::string> mount_options, super_options;
};

const std::vector<mountinfo_entry_t> &parseSelfMountinfo(bool cached = true);
const std::vector<mountinfo_entry_t> &parseSelfMountinfo(bool cached = true);
}
31 changes: 21 additions & 10 deletions module/jni/include/utils.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
#pragma once
#include <string>
#include <errno.h>
#include <functional>
#include "logging.hpp"
#include "zygisk.hpp"

#define DCL_HOOK_FUNC(ret, func, ...) \
ret (*old_##func)(__VA_ARGS__) = nullptr; \
#define DCL_HOOK_FUNC(ret, func, ...) \
ret (*old_##func)(__VA_ARGS__) = nullptr; \
ret new_##func(__VA_ARGS__)

#define ASSERT_LOG(tag, expr) if(!(expr)) { \
LOGE("%s:%d Assertion %s failed. %d:%s", tag, __LINE__, #expr, errno, std::strerror(errno)); }
#define ASSERT_LOG(tag, expr) \
if (!(expr)) \
{ \
LOGE("%s:%d Assertion %s failed. %d:%s", #tag, __LINE__, #expr, errno, std::strerror(errno)); \
}

#define ASSERT_EXIT(tag, expr, ret) if(!(expr)) { \
LOGE("%s:%d Assertion %s failed. %d:%s", tag, __LINE__, #expr, errno, std::strerror(errno)); \
ret; }
#define ASSERT_DO(tag, expr, ret) \
if (!(expr)) \
{ \
LOGE("%s:%d Assertion %s failed. %d:%s", #tag, __LINE__, #expr, errno, std::strerror(errno)); \
ret; \
}

bool switchMountNS(int pid);
int isUserAppUID(int uid);
bool hookPLTByName(zygisk::Api *api, const std::string &libName, const std::string &symbolName, void *hookFunc, void **origFunc);
namespace Utils
{
bool switchMountNS(int pid);
int isUserAppUID(int uid);
bool hookPLTByName(zygisk::Api *api, const std::string &libName, const std::string &symbolName, void *hookFunc, void **origFunc);
int executeLambdaInFork(const std::function<void()> &lambda);
}
43 changes: 23 additions & 20 deletions module/jni/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class ZygiskModule : public zygisk::ModuleBase
bool isRoot = (flags & zygisk::StateFlag::PROCESS_GRANTED_ROOT) != 0;
bool isOnDenylist = (flags & zygisk::StateFlag::PROCESS_ON_DENYLIST) != 0;
bool isChildZygote = args->is_child_zygote != NULL && *args->is_child_zygote;
if (isRoot || !isOnDenylist || !isUserAppUID(args->uid))
if (isRoot || !isOnDenylist || !Utils::isUserAppUID(args->uid))
{
LOGD("Skipping ppid=%d uid=%d isChildZygote=%d", getppid(), args->uid, isChildZygote);
return;
Expand All @@ -80,20 +80,20 @@ class ZygiskModule : public zygisk::ModuleBase
/*
* Read the comment above unshare hook.
*/
ASSERT_EXIT("preAppSpecialize", unshare(CLONE_NEWNS) != -1, return);
ASSERT_DO(preAppSpecialize, unshare(CLONE_NEWNS) != -1, return);

/*
* Mount the app mount namespace's root as MS_SLAVE, so every mount/umount from
* Zygote shared pre-specialization namespace is propagated to this one.
*/
ASSERT_EXIT("preAppSpecialize", mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) != -1, return);
ASSERT_DO(preAppSpecialize, mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) != -1, return);

ASSERT_EXIT("preAppSpecialize", hookPLTByName("libandroid_runtime.so", "unshare", new_unshare, &old_unshare), return);
ASSERT_EXIT("preAppSpecialize", hookPLTByName("libandroid_runtime.so", "setresuid", new_setresuid, &old_setresuid), return);
ASSERT_DO(preAppSpecialize, hookPLTByName("libandroid_runtime.so", "unshare", new_unshare, &old_unshare), return);
ASSERT_DO(preAppSpecialize, hookPLTByName("libandroid_runtime.so", "setresuid", new_setresuid, &old_setresuid), return);

int companionFd = -1;
ASSERT_LOG("preAppSpecialize", (companionFd = api->connectCompanion()) != -1);
ASSERT_LOG("preAppSpecialize", companionFd != -1 && api->exemptFd(companionFd));
ASSERT_LOG(preAppSpecialize, (companionFd = api->connectCompanion()) != -1);
ASSERT_LOG(preAppSpecialize, companionFd != -1 && api->exemptFd(companionFd));

callbackFunction = [fd = companionFd]()
{
Expand All @@ -103,8 +103,8 @@ class ZygiskModule : public zygisk::ModuleBase
do
{
pid_t pid = getpid();
ASSERT_EXIT("invokeZygiskCompanion", write(fd, &pid, sizeof(pid)) == sizeof(pid), break);
ASSERT_EXIT("invokeZygiskCompanion", read(fd, &result, sizeof(result)) == sizeof(result), break);
ASSERT_DO(invokeZygiskCompanion, write(fd, &pid, sizeof(pid)) == sizeof(pid), break);
ASSERT_DO(invokeZygiskCompanion, read(fd, &result, sizeof(result)) == sizeof(result), break);
} while (false);
close(fd);
}
Expand Down Expand Up @@ -133,15 +133,15 @@ class ZygiskModule : public zygisk::ModuleBase
void postAppSpecialize(const AppSpecializeArgs *args) override
{
if (old_unshare != nullptr)
ASSERT_LOG("postAppSpecialize", hookPLTByName("libandroid_runtime.so", "unshare", old_unshare));
ASSERT_LOG(postAppSpecialize, hookPLTByName("libandroid_runtime.so", "unshare", old_unshare));
if (old_setresuid != nullptr)
ASSERT_LOG("postAppSpecialize", hookPLTByName("libandroid_runtime.so", "setresuid", old_setresuid));
ASSERT_LOG(postAppSpecialize, hookPLTByName("libandroid_runtime.so", "setresuid", old_setresuid));
}

template <typename T>
bool hookPLTByName(const std::string &libName, const std::string &symbolName, T *hookFunction, T **originalFunction = nullptr)
{
return ::hookPLTByName(api, libName, symbolName, (void *)hookFunction, (void **)originalFunction) && api->pltHookCommit();
return Utils::hookPLTByName(api, libName, symbolName, (void *)hookFunction, (void **)originalFunction) && api->pltHookCommit();
}

private:
Expand All @@ -154,18 +154,21 @@ void zygisk_companion_handler(int fd)
bool result = [&]() -> bool
{
pid_t pid;
ASSERT_EXIT("zygisk_companion_handler", read(fd, &pid, sizeof(pid)) == sizeof(pid), return false);
ASSERT_EXIT("zygisk_companion_handler", unshare(CLONE_NEWNS) != -1, return false);
ASSERT_EXIT("zygisk_companion_handler", switchMountNS(pid), return false);
ASSERT_DO(zygisk_companion_handler, read(fd, &pid, sizeof(pid)) == sizeof(pid), return false);
ASSERT_DO(zygisk_companion_handler, unshare(CLONE_NEWNS) != -1, return false);
ASSERT_DO(zygisk_companion_handler, Utils::switchMountNS(pid), return false);
LOGD("zygisk_companion_handler processing namespace of pid=%d", pid);

doUnmount();
doRemount();

return true;
// setns mount namespace is not effective until a fork(?)
return WIFEXITED(Utils::executeLambdaInFork(
[]()
{
doUnmount();
doRemount();
}));
}();

ASSERT_LOG("zygisk_companion_handler", write(fd, &result, sizeof(result)) == sizeof(result));
ASSERT_LOG(zygisk_companion_handler, write(fd, &result, sizeof(result)) == sizeof(result));
}

REGISTER_ZYGISK_MODULE(ZygiskModule)
Expand Down
4 changes: 3 additions & 1 deletion module/jni/map_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "map_parser.hpp"
#include "logging.hpp"

using namespace Parsers;

map_entry_t::map_entry_t(uintptr_t address_start, uintptr_t address_end, uintptr_t offset, const std::string &perms, const std::string &pathname, dev_t device, ino_t inode)
: address_start(address_start), address_end(address_end), perms(perms),
offset(offset), device(device), inode(inode), pathname(pathname) {}
Expand All @@ -19,7 +21,7 @@ dev_t map_entry_t::getDevice() const { return device; }
ino_t map_entry_t::getInode() const { return inode; }
const std::string &map_entry_t::getPathname() const { return pathname; }

const std::vector<map_entry_t> &parseSelfMaps(bool cached)
const std::vector<map_entry_t> &Parsers::parseSelfMaps(bool cached)
{
static std::vector<map_entry_t> parser_cache;
if (cached && !parser_cache.empty())
Expand Down
18 changes: 9 additions & 9 deletions module/jni/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ static const std::unordered_map<std::string, int> mount_flags_procfs = {
{"relatime", MS_RELATIME},
{"nosymfollow", MS_NOSYMFOLLOW}};

static bool shouldUnmount(const mountinfo_entry_t &mount_info)
static bool shouldUnmount(const Parsers::mountinfo_entry_t &mount_info)
{
const auto &root = mount_info.getRoot();

// Unmount all module bind mounts
return root.starts_with("/adb/");
}

static bool shouldUnmount(const mount_entry_t &mount)
static bool shouldUnmount(const Parsers::mount_entry_t &mount)
{
const auto &mountPoint = mount.getMountPoint();
const auto &type = mount.getType();
Expand Down Expand Up @@ -66,7 +66,7 @@ void doUnmount()
std::vector<std::string> mountPoints;

// Check mounts first
for (const auto &mount : parseSelfMounts(false))
for (const auto &mount : Parsers::parseSelfMounts(false))
{
if (shouldUnmount(mount))
{
Expand All @@ -75,7 +75,7 @@ void doUnmount()
}

// Check mountinfos so that we can find bind mounts as well
for (const auto &mount_info : parseSelfMountinfo(false))
for (const auto &mount_info : Parsers::parseSelfMountinfo(false))
{
if (shouldUnmount(mount_info))
{
Expand All @@ -102,7 +102,7 @@ void doUnmount()

void doRemount()
{
for (const auto &mount : parseSelfMounts(false))
for (const auto &mount : Parsers::parseSelfMounts(false))
{
if (mount.getMountPoint() == "/data")
{
Expand Down Expand Up @@ -146,7 +146,7 @@ void doHideZygisk()
std::string filePath;
uintptr_t startAddress = 0, bssAddress = 0;

for (const auto &map : parseSelfMaps())
for (const auto &map : Parsers::parseSelfMaps())
{
if (map.getPathname().ends_with("/libnativebridge.so") && map.getPerms() == "r--p")
{
Expand All @@ -157,8 +157,8 @@ void doHideZygisk()
}
}

ASSERT_EXIT("doHideZygisk", startAddress != 0, return);
ASSERT_EXIT("doHideZygisk", reader.load(filePath), return);
ASSERT_DO(doHideZygisk, startAddress != 0, return);
ASSERT_DO(doHideZygisk, reader.load(filePath), return);

size_t bssSize = 0;
for (const auto &sec : reader.sections)
Expand All @@ -171,7 +171,7 @@ void doHideZygisk()
}
}

ASSERT_EXIT("doHideZygisk", bssAddress != 0, return);
ASSERT_DO(doHideZygisk, bssAddress != 0, return);
LOGD("Found .bss for \"%s\" at 0x%" PRIxPTR " sized %" PRIuPTR " bytes.", filePath.c_str(), bssAddress, bssSize);

uint8_t *pHadError = reinterpret_cast<uint8_t *>(memchr(reinterpret_cast<void *>(bssAddress), 0x01, bssSize));
Expand Down
Loading

0 comments on commit 5c2ba2a

Please sign in to comment.