8 Commits

Author SHA1 Message Date
snake-4
b3d8493612 Added commit hash to version strings 2024-03-26 19:49:18 +01:00
snake-4
b63132e9f8 Updated README.md and added LICENSE 2024-03-26 18:55:55 +01:00
snake-4
58782b21f8 unshare on parent Zygote only
Calling unshare on child Zygotes crash at a sanity check but they end up inheriting the namespace either way.

closes #1
2024-03-26 18:26:24 +01:00
snake-4
72afc9e4fc dlclose on servers processes too 2024-03-26 18:24:20 +01:00
snake-4
916558491a Moved headers to includes, various changes...
+ Added better UID checks.
+ Added MS_SLAVE root mount in the new mount namespace.
2024-03-26 15:37:07 +01:00
snake-4
ba80d6d181 Bumped version to v2.0.0 (200) 2024-03-25 21:37:11 +01:00
snake-4
c1070182a2 Added usermode unmounter and mounts parser
+ Added a mounts parser implementation using mntent API.
+ Added logging functions.
+ Added usermode unmounter which calls unshare pre app-specialization.
* Updated module.prop.
2024-03-25 21:36:47 +01:00
snake-4
08cc6f7e33 Changed to C++14, updated README.md 2024-03-25 21:21:45 +01:00
15 changed files with 553 additions and 22 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 snake-4
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,6 +1,40 @@
## Zygisk Assistant <h3 align="center">Zygisk Assistant</h3>
This module makes Zygisk more stealthy.
The module sets **DLCLOSE_MODULE_LIBRARY** and **FORCE_DENYLIST_UNMOUNT** Zygisk flags for all non-root application processes. <p align="center">
A Zygisk module that hides root by unmounting suspicious mounts in user-mode.
<br />
<br />
<a href="https://github.com/snake-4/Zygisk-Assistant/issues">Report Bug</a>
·
<a href="https://github.com/snake-4/Zygisk-Assistant/issues">Request Feature</a>
·
<a href="https://github.com/snake-4/Zygisk-Assistant/releases">Latest Release</a>
</p>
</div>
Please note that installing this module could lead to compatibility issues with other Zygisk modules. If you encounter any problems, please create an issue in this repository.
<!-- ABOUT THE PROJECT -->
## About The Project
This module creates a new transparent namespace for each application in preAppSpecialize and unmounts common root mounts.
<!-- CONTRIBUTING -->
## Contributing
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
Don't forget to give the project a star! Thanks again!
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/FeatureName`)
3. Commit your Changes (`git commit -m 'Add some FeatureName'`)
4. Push to the Branch (`git push origin feature/FeatureName`)
5. Open a Pull Request
<!-- LICENSE -->
## License
Distributed under the MIT License. See `LICENSE` for more information.

View File

@@ -4,8 +4,17 @@ plugins {
alias(libs.plugins.agp.lib) apply false alias(libs.plugins.agp.lib) apply false
} }
val commitHash: String by extra({
val stdout = ByteArrayOutputStream()
rootProject.exec {
commandLine("git", "rev-parse", "--short", "HEAD")
standardOutput = stdout
}
stdout.toString().trim()
})
val moduleId by extra("zygisk-assistant") val moduleId by extra("zygisk-assistant")
val moduleName by extra("Zygisk Assistant") val moduleName by extra("Zygisk Assistant")
val verName by extra("v1.1.0") val verName by extra("v2.0.0")
val verCode by extra(110) val verCode by extra(200)
val abiList by extra(listOf("armeabi-v7a","arm64-v8a","x86","x86_64")) val abiList by extra(listOf("armeabi-v7a","arm64-v8a","x86","x86_64"))

View File

@@ -7,6 +7,7 @@ plugins {
val moduleId: String by rootProject.extra val moduleId: String by rootProject.extra
val moduleName: String by rootProject.extra val moduleName: String by rootProject.extra
val verCode: Int by rootProject.extra val verCode: Int by rootProject.extra
val commitHash: String by rootProject.extra
val verName: String by rootProject.extra val verName: String by rootProject.extra
val abiList: List<String> by rootProject.extra val abiList: List<String> by rootProject.extra
@@ -39,7 +40,7 @@ androidComponents.onVariants { variant ->
val libOutDir = layout.buildDirectory.dir("intermediates/stripped_native_libs/$variantLowered/out/lib").get() val libOutDir = layout.buildDirectory.dir("intermediates/stripped_native_libs/$variantLowered/out/lib").get()
val moduleDir = layout.buildDirectory.dir("outputs/module/$variantLowered").get() val moduleDir = layout.buildDirectory.dir("outputs/module/$variantLowered").get()
val zipOutDir = layout.buildDirectory.dir("outputs/release").get() val zipOutDir = layout.buildDirectory.dir("outputs/release").get()
val zipFileName = "$moduleName-$verName-$verCode-$buildTypeLowered.zip".replace(' ', '-') val zipFileName = "$moduleName-$verName-$commitHash-$buildTypeLowered.zip".replace(' ', '-')
val prepareModuleFilesTask = task<Sync>("prepareModuleFiles$variantCapped") { val prepareModuleFilesTask = task<Sync>("prepareModuleFiles$variantCapped") {
group = "module" group = "module"
@@ -50,7 +51,7 @@ androidComponents.onVariants { variant ->
expand( expand(
"moduleId" to moduleId, "moduleId" to moduleId,
"moduleName" to moduleName, "moduleName" to moduleName,
"versionName" to "$verName ($verCode-$variantLowered)", "versionName" to "$verName ($commitHash-$variantLowered)",
"versionCode" to verCode "versionCode" to verCode
) )
} }

View File

@@ -1,8 +1,9 @@
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := zygisk LOCAL_MODULE := zygisk
LOCAL_SRC_FILES := main.cpp LOCAL_SRC_FILES := mount_parser.cpp unmount.cpp main.cpp
LOCAL_STATIC_LIBRARIES := libcxx LOCAL_STATIC_LIBRARIES := libcxx
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_CPPFLAGS := -std=c++20 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden APP_CPPFLAGS := -std=c++14 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
APP_STL := none APP_STL := none
APP_PLATFORM := android-31 APP_PLATFORM := android-31

View File

@@ -0,0 +1,219 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file is consumed by build/tools/fs_config and is used
* for generating various files. Anything #define AID_<name>
* becomes the mapping for getpwnam/getpwuid, etc. The <name>
* field is lowercased.
* For example:
* #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
*
* The above holds true with the exception of:
* mediacodec
* mediaex
* mediadrm
* Whose friendly names do not match the #define statements.
*
* This file must only be used for platform (Google managed, and submitted through AOSP), AIDs. 3rd
* party AIDs must be added via config.fs, which will place them in the corresponding partition's
* passwd and group files. There are ranges in this file reserved for AIDs for each 3rd party
* partition, from which the system reads passwd and group files.
*/
#pragma once
/* This is the main Users and Groups config for the platform.
* DO NOT EVER RENUMBER
*/
#define AID_ROOT 0 /* traditional unix root user */
/* The following are for LTP and should only be used for testing */
#define AID_DAEMON 1 /* traditional unix daemon owner */
#define AID_BIN 2 /* traditional unix binaries owner */
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
#define AID_INPUT 1004 /* input devices */
#define AID_AUDIO 1005 /* audio devices */
#define AID_CAMERA 1006 /* camera devices */
#define AID_LOG 1007 /* log devices */
#define AID_COMPASS 1008 /* compass device */
#define AID_MOUNT 1009 /* mountd socket */
#define AID_WIFI 1010 /* wifi subsystem */
#define AID_ADB 1011 /* android debug bridge (adbd) */
#define AID_INSTALL 1012 /* group for installing packages */
#define AID_MEDIA 1013 /* mediaserver process */
#define AID_DHCP 1014 /* dhcp client */
#define AID_SDCARD_RW 1015 /* external storage write access */
#define AID_VPN 1016 /* vpn system */
#define AID_KEYSTORE 1017 /* keystore subsystem */
#define AID_USB 1018 /* USB devices */
#define AID_DRM 1019 /* DRM server */
#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */
#define AID_GPS 1021 /* GPS daemon */
#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
#define AID_MEDIA_RW 1023 /* internal media storage write access */
#define AID_MTP 1024 /* MTP USB driver access */
#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */
#define AID_DRMRPC 1026 /* group for drm rpc */
#define AID_NFC 1027 /* nfc subsystem */
#define AID_SDCARD_R 1028 /* external storage read access */
#define AID_CLAT 1029 /* clat part of nat464 */
#define AID_LOOP_RADIO 1030 /* loop radio devices */
#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */
#define AID_PACKAGE_INFO 1032 /* access to installed package details */
#define AID_SDCARD_PICS 1033 /* external storage photos access */
#define AID_SDCARD_AV 1034 /* external storage audio/video access */
#define AID_SDCARD_ALL 1035 /* access all users external storage */
#define AID_LOGD 1036 /* log daemon */
#define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */
#define AID_DBUS 1038 /* dbus-daemon IPC broker process */
#define AID_TLSDATE 1039 /* tlsdate unprivileged user */
#define AID_MEDIA_EX 1040 /* mediaextractor process */
#define AID_AUDIOSERVER 1041 /* audioserver process */
#define AID_METRICS_COLL 1042 /* metrics_collector process */
#define AID_METRICSD 1043 /* metricsd process */
#define AID_WEBSERV 1044 /* webservd process */
#define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */
#define AID_MEDIA_CODEC 1046 /* mediacodec process */
#define AID_CAMERASERVER 1047 /* cameraserver process */
#define AID_FIREWALL 1048 /* firewalld process */
#define AID_TRUNKS 1049 /* trunksd process (TPM daemon) */
#define AID_NVRAM 1050 /* Access-controlled NVRAM */
#define AID_DNS 1051 /* DNS resolution daemon (system: netd) */
#define AID_DNS_TETHER 1052 /* DNS resolution daemon (tether: dnsmasq) */
#define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
#define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
#define AID_MEDIA_AUDIO 1055 /* GID for audio files on internal media storage */
#define AID_MEDIA_VIDEO 1056 /* GID for video files on internal media storage */
#define AID_MEDIA_IMAGE 1057 /* GID for image files on internal media storage */
#define AID_TOMBSTONED 1058 /* tombstoned user */
#define AID_MEDIA_OBB 1059 /* GID for OBB files on internal media storage */
#define AID_ESE 1060 /* embedded secure element (eSE) subsystem */
#define AID_OTA_UPDATE 1061 /* resource tracking UID for OTA updates */
#define AID_AUTOMOTIVE_EVS 1062 /* Automotive rear and surround view system */
#define AID_LOWPAN 1063 /* LoWPAN subsystem */
#define AID_HSM 1064 /* hardware security module subsystem */
#define AID_RESERVED_DISK 1065 /* GID that has access to reserved disk space */
#define AID_STATSD 1066 /* statsd daemon */
#define AID_INCIDENTD 1067 /* incidentd daemon */
#define AID_SECURE_ELEMENT 1068 /* secure element subsystem */
#define AID_LMKD 1069 /* low memory killer daemon */
#define AID_LLKD 1070 /* live lock daemon */
#define AID_IORAPD 1071 /* input/output readahead and pin daemon */
#define AID_GPU_SERVICE 1072 /* GPU service daemon */
#define AID_NETWORK_STACK 1073 /* network stack service */
#define AID_GSID 1074 /* GSI service daemon */
#define AID_FSVERITY_CERT 1075 /* fs-verity key ownership in keystore */
#define AID_CREDSTORE 1076 /* identity credential manager service */
#define AID_EXTERNAL_STORAGE 1077 /* Full external storage access including USB OTG volumes */
#define AID_EXT_DATA_RW 1078 /* GID for app-private data directories on external storage */
#define AID_EXT_OBB_RW 1079 /* GID for OBB directories on external storage */
#define AID_CONTEXT_HUB 1080 /* GID for access to the Context Hub */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
#define AID_DIAG 2002 /* access to diagnostic resources */
/* The range 2900-2999 is reserved for the vendor partition */
/* Note that the two 'OEM' ranges pre-dated the vendor partition, so they take the legacy 'OEM'
* name. Additionally, they pre-dated passwd/group files, so there are users and groups named oem_#
* created automatically for all values in these ranges. If there is a user/group in a passwd/group
* file corresponding to this range, both the oem_# and user/group names will resolve to the same
* value. */
#define AID_OEM_RESERVED_START 2900
#define AID_OEM_RESERVED_END 2999
/* The 3000 series are intended for use as supplemental group id's only.
* They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW 3004 /* can create raw INET sockets */
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
#define AID_READPROC 3009 /* Allow /proc read access */
#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */
#define AID_UHID 3011 /* Allow read/write to /dev/uhid node */
/* The range 5000-5999 is also reserved for vendor partition. */
#define AID_OEM_RESERVED_2_START 5000
#define AID_OEM_RESERVED_2_END 5999
/* The range 6000-6499 is reserved for the system partition. */
#define AID_SYSTEM_RESERVED_START 6000
#define AID_SYSTEM_RESERVED_END 6499
/* The range 6500-6999 is reserved for the odm partition. */
#define AID_ODM_RESERVED_START 6500
#define AID_ODM_RESERVED_END 6999
/* The range 7000-7499 is reserved for the product partition. */
#define AID_PRODUCT_RESERVED_START 7000
#define AID_PRODUCT_RESERVED_END 7499
/* The range 7500-7999 is reserved for the system_ext partition. */
#define AID_SYSTEM_EXT_RESERVED_START 7500
#define AID_SYSTEM_EXT_RESERVED_END 7999
#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
#define AID_MISC 9998 /* access to misc storage */
#define AID_NOBODY 9999
#define AID_APP 10000 /* TODO: switch users over to AID_APP_START */
#define AID_APP_START 10000 /* first app user */
#define AID_APP_END 19999 /* last app user */
#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
#define AID_CACHE_GID_END 29999 /* end of gids for apps to mark cached data */
#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
#define AID_EXT_GID_END 39999 /* end of gids for apps to mark external data */
#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */
#define AID_EXT_CACHE_GID_END 49999 /* end of gids for apps to mark external cached data */
#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
/*
* This is a magic number in the kernel and not something that was picked
* arbitrarily. This value is returned whenever a uid that has no mapping in the
* user namespace is returned to userspace:
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40
*/
#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */
/* use the ranges below to determine whether a process is isolated */
#define AID_ISOLATED_START 90000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
/*
* android_ids has moved to pwd/grp functionality.
* If you need to add one, the structure is now
* auto-generated based on the AID_ constraints
* documented at the top of this header file.
* Also see build/tools/fs_config for more details.
*/

View File

@@ -0,0 +1,15 @@
#pragma once
#include <android/log.h>
#include <string.h>
#include <errno.h>
#ifndef NDEBUG
static constexpr auto TAG = "ZygiskAssistant/JNI";
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#else
#define LOGD(...)
#define LOGI(...)
#define LOGE(...)
#endif

View File

@@ -0,0 +1,29 @@
#include <string>
#include <vector>
#include <unordered_map>
#include <mntent.h>
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:
void parseMountOptions(const std::string &input);
std::string fsname;
std::string dir;
std::string type;
std::unordered_map<std::string, std::string> opts_map;
int freq;
int passno;
};
std::vector<mount_entry_t> parseMountsFromPath(const char *path);

View File

@@ -1,14 +1,28 @@
#include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <sched.h>
#include <android/log.h>
#include <sys/mount.h>
#include "zygisk.hpp" #include "zygisk.hpp"
#include "logging.hpp"
#include "android_filesystem_config.h"
using zygisk::Api; using zygisk::Api;
using zygisk::AppSpecializeArgs; using zygisk::AppSpecializeArgs;
using zygisk::ServerSpecializeArgs; using zygisk::ServerSpecializeArgs;
void do_unmount();
static int shouldSkipUid(int uid)
{
int appid = uid % AID_USER_OFFSET;
if (appid >= AID_APP_START && appid <= AID_APP_END)
return false;
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END)
return false;
return true;
}
class ZygiskModule : public zygisk::ModuleBase class ZygiskModule : public zygisk::ModuleBase
{ {
public: public:
@@ -25,14 +39,49 @@ public:
uint32_t flags = api->getFlags(); uint32_t flags = api->getFlags();
bool isRoot = (flags & zygisk::StateFlag::PROCESS_GRANTED_ROOT) != 0; bool isRoot = (flags & zygisk::StateFlag::PROCESS_GRANTED_ROOT) != 0;
bool isOnDenylist = (flags & zygisk::StateFlag::PROCESS_ON_DENYLIST) != 0; bool isOnDenylist = (flags & zygisk::StateFlag::PROCESS_ON_DENYLIST) != 0;
if (isRoot || !isOnDenylist || shouldSkipUid(args->uid))
if (!isRoot && isOnDenylist && args->uid > 1000)
{ {
api->setOption(zygisk::Option::FORCE_DENYLIST_UNMOUNT); LOGD("Skipping pid=%d uid=%d", getpid(), args->uid);
return;
} }
LOGD("Unmounting in preAppSpecialize for pid=%d uid=%d", getpid(), args->uid);
/*
* Create only one namespace per zygote, child Zygotes will inherit it
* But then again, why won't they also inherit the unmounts of the parent?
* Either way, unshare in child Zygote will crash at the open FD sanity check.
*/
if (!*args->is_child_zygote)
{
LOGD("Creating new mount namespace for parent pid=%d uid=%d", getpid(), args->uid);
/*
* preAppSpecialize is before ensureInAppMountNamespace.
* postAppSpecialize is after seccomp setup.
* So we unshare here to create a pseudo app mount namespace
*/
if (unshare(CLONE_NEWNS) == -1)
{
LOGE("unshare(CLONE_NEWNS) returned -1: %d (%s)", errno, strerror(errno));
// Don't unmount anything in global namespace
return;
}
/*
* Mount the pseudo app mount namespace's root as MS_SLAVE, so every mount/umount from
* Zygote shared pre-specialization mountspace is propagated to this one.
*/
if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1)
{
LOGE("mount(\"rootfs\", \"/\", NULL, (MS_SLAVE | MS_REC), NULL) returned -1");
}
}
do_unmount();
} }
void preServerSpecialize(ServerSpecializeArgs *args) void preServerSpecialize(ServerSpecializeArgs *args) override
{ {
api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY); api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY);
} }
@@ -40,7 +89,6 @@ public:
private: private:
Api *api; Api *api;
JNIEnv *env; JNIEnv *env;
}; };
REGISTER_ZYGISK_MODULE(ZygiskModule) REGISTER_ZYGISK_MODULE(ZygiskModule)

View File

@@ -0,0 +1,83 @@
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <mntent.h>
#include "mount_parser.hpp"
#include "logging.hpp"
mount_entry_t::mount_entry_t(::mntent *entry)
: fsname(entry->mnt_fsname), dir(entry->mnt_dir), type(entry->mnt_type), freq(entry->mnt_freq), passno(entry->mnt_passno)
{
parseMountOptions(entry->mnt_opts);
}
const std::string &mount_entry_t::getFsName() const
{
return fsname;
}
const std::string &mount_entry_t::getMountPoint() const
{
return dir;
}
const std::string &mount_entry_t::getType() const
{
return type;
}
const std::unordered_map<std::string, std::string> &mount_entry_t::getOptions() const
{
return opts_map;
}
int mount_entry_t::getDumpFrequency() const
{
return freq;
}
int mount_entry_t::getPassNumber() const
{
return passno;
}
void mount_entry_t::parseMountOptions(const std::string &input)
{
std::istringstream iss(input);
std::string token;
while (std::getline(iss, token, ','))
{
std::istringstream tokenStream(token);
std::string key, value;
if (std::getline(tokenStream, key, '='))
{
std::getline(tokenStream, value); // Put what's left in the stream to value, could be empty
opts_map[key] = value;
}
}
}
std::vector<mount_entry_t> parseMountsFromPath(const char *path)
{
std::vector<mount_entry_t> result;
FILE *file = setmntent(path, "r");
if (file == NULL)
{
LOGE("setmntent(\"%s\", \"r\") returned NULL: %d (%s)", path, errno, strerror(errno));
return result;
}
struct mntent *entry;
while ((entry = getmntent(file)) != NULL)
{
result.emplace_back(mount_entry_t(entry));
}
endmntent(file);
return result;
}

73
module/jni/unmount.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include <string>
#include <vector>
#include <array>
#include <sys/mount.h>
#include "zygisk.hpp"
#include "logging.hpp"
#include "mount_parser.hpp"
constexpr std::array<const char *, 4> fsname_list = {"KSU", "APatch", "magisk", "worker"};
static bool shouldUnmount(const mount_entry_t &info)
{
const auto &mountPoint = info.getMountPoint();
const auto &type = info.getType();
const auto &options = info.getOptions();
// Unmount everything mounted to /data/adb
if (mountPoint.rfind("/data/adb", 0) == 0)
return true;
// Unmount all module overlayfs and tmpfs
bool doesFsnameMatch = std::find(fsname_list.begin(), fsname_list.end(), info.getFsName()) != fsname_list.end();
if ((type == "overlay" || type == "tmpfs") && doesFsnameMatch)
return true;
// Unmount all overlayfs with lowerdir/upperdir/workdir starting with /data/adb
if (type == "overlay")
{
const auto &lowerdir = options.find("lowerdir");
const auto &upperdir = options.find("upperdir");
const auto &workdir = options.find("workdir");
if (lowerdir != options.end() && lowerdir->second.rfind("/data/adb", 0) == 0)
return true;
if (upperdir != options.end() && upperdir->second.rfind("/data/adb", 0) == 0)
return true;
if (workdir != options.end() && workdir->second.rfind("/data/adb", 0) == 0)
return true;
}
return false;
}
void do_unmount()
{
std::vector<std::string> mountPoints;
for (auto &info : parseMountsFromPath("/proc/self/mounts"))
{
if (shouldUnmount(info))
{
mountPoints.push_back(info.getMountPoint());
}
}
// Sort by string lengths, descending
std::sort(mountPoints.begin(), mountPoints.end(), [](const auto &lhs, const auto &rhs)
{ return lhs.size() > rhs.size(); });
for (const auto &mountPoint : mountPoints)
{
if (umount2(mountPoint.c_str(), MNT_DETACH) == 0)
{
LOGD("umount2(\"%s\", MNT_DETACH) returned 0", mountPoint.c_str());
}
else
{
LOGE("umount2(\"%s\", MNT_DETACH) returned -1: %d (%s)", mountPoint.c_str(), errno, strerror(errno));
}
}
}

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest/>

View File

@@ -2,5 +2,5 @@ id=${moduleId}
name=${moduleName} name=${moduleName}
version=${versionName} version=${versionName}
versionCode=${versionCode} versionCode=${versionCode}
author=snake-4 & yervant7 author=snake-4
description=DLCLOSE_MODULE_LIBRARY and FORCE_DENYLIST_UNMOUNT for non-root processes. description=Zygisk module to hide mounts.