You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
source: removed all SuSFS code
This commit is contained in:
34
.github/workflows/susfsd.yml
vendored
34
.github/workflows/susfsd.yml
vendored
@@ -1,34 +0,0 @@
|
||||
name: Build susfsd
|
||||
on:
|
||||
push:
|
||||
branches: [ "next" ]
|
||||
paths:
|
||||
- '.github/workflows/susfsd.yml'
|
||||
- 'userspace/susfsd/**'
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
target:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-latest
|
||||
jobs:
|
||||
build-susfs:
|
||||
name: Build userspace susfsd
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build susfsd
|
||||
working-directory: ./userspace/susfsd
|
||||
run: $ANDROID_NDK/ndk-build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: susfsd-aarch64-linux-android
|
||||
path: ./userspace/susfsd/libs
|
||||
|
||||
@@ -59,13 +59,17 @@
|
||||
<section class="py-5">
|
||||
<div class="container">
|
||||
<h2 class="fs-2 fw-bold text-start" style="color: rgb(255,192,192);">Installation</h2>
|
||||
<p style="color: rgb(255,192,192);">Copy and paste the commands below to install KernelSU Next.</p>
|
||||
<p style="color: rgb(255,192,192);">Copy and paste the commands below to install KernelSU Next. Latest tag (stable)</p>
|
||||
<div>
|
||||
<pre><code style="color: rgb(255,118,118);">curl -LSs "https://raw.githubusercontent.com/rifsxd/KernelSU-Next/next/kernel/setup.sh" | bash -</code><button class="btn" style="color: rgb(255,192,192); padding: 5px 10px; font-size: 12px;" onclick="copyToClipboard(this)">Copy to Clipboard!</button></pre>
|
||||
</div>
|
||||
<p style="color: rgb(255,192,192);">For SuSFS implementation, the commands should be the dedicated branches for your kernel. (For example - next-susfs-a13-5.15)</p>
|
||||
<p style="color: rgb(255,192,192);">Copy and paste the commands below to install KernelSU Next. Next branch (development bleeding edge).</p>
|
||||
<div>
|
||||
<pre><code style="color: rgb(255,118,118);">curl -LSs "https://raw.githubusercontent.com/rifsxd/KernelSU-Next/next/kernel/setup.sh" | bash -s next-susfs-a13-5.15</code><button class="btn" style="color: rgb(255,192,192); padding: 5px 10px; font-size: 12px;" onclick="copyToClipboard(this)">Copy to Clipboard!</button></pre>
|
||||
<pre><code style="color: rgb(255,118,118);">curl -LSs "https://raw.githubusercontent.com/rifsxd/KernelSU-Next/next/kernel/setup.sh" | bash -s next</code><button class="btn" style="color: rgb(255,192,192); padding: 5px 10px; font-size: 12px;" onclick="copyToClipboard(this)">Copy to Clipboard!</button></pre>
|
||||
</div>
|
||||
<p style="color: rgb(255,192,192);">Copy and paste the commands below to install KernelSU Next. Select tag (such as v1.0.2-R14).</p>
|
||||
<div>
|
||||
<pre><code style="color: rgb(255,118,118);">curl -LSs "https://raw.githubusercontent.com/rifsxd/KernelSU-Next/next/kernel/setup.sh" | bash -s v1.0.2-R14</code><button class="btn" style="color: rgb(255,192,192); padding: 5px 10px; font-size: 12px;" onclick="copyToClipboard(this)">Copy to Clipboard!</button></pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -69,17 +69,6 @@ class MainActivity : ComponentActivity() {
|
||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||
if (isManager) install()
|
||||
|
||||
// val prefs = getSharedPreferences("settings", MODE_PRIVATE)
|
||||
|
||||
// val isSUS_SU = getSuSFSFeatures()
|
||||
// if (isSUS_SU == "CONFIG_KSU_SUSFS_SUS_SU") {
|
||||
// if (prefs.getBoolean("enable_sus_su", false)) {
|
||||
// if (susfsSUS_SU_Mode() != "2") {
|
||||
// susfsSUS_SU_2()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
setContent {
|
||||
KernelSUTheme {
|
||||
val navController = rememberNavController()
|
||||
|
||||
@@ -268,14 +268,6 @@ private fun StatusCard(
|
||||
text = stringResource(R.string.home_module_count, getModuleCount()),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
// Spacer(Modifier.height(4.dp))
|
||||
// val suSFS = getSuSFS()
|
||||
// if (suSFS == "Supported") {
|
||||
// Text(
|
||||
// text = stringResource(R.string.home_susfs, getSuSFS()),
|
||||
// style = MaterialTheme.typography.bodyMedium
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,19 +408,6 @@ private fun InfoCard() {
|
||||
content = stringResource(R.string.home_magic_mount),
|
||||
icon = Icons.Filled.SettingsSuggest,
|
||||
)
|
||||
|
||||
// Spacer(Modifier.height(16.dp))
|
||||
// val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
|
||||
// val suSFS = getSuSFS()
|
||||
|
||||
// if (suSFS == "Supported") {
|
||||
// val susSUMode = if (isSUS_SU) "| SuS SU mode: ${susfsSUS_SU_Mode()}" else ""
|
||||
// InfoCardItem(
|
||||
// label = stringResource(R.string.home_susfs_version),
|
||||
// content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
|
||||
// icon = painterResource(R.drawable.ic_sus),
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,32 +160,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
// val isSUS_SU = getSuSFSFeatures()
|
||||
// if (isSUS_SU == "CONFIG_KSU_SUSFS_SUS_SU") {
|
||||
// var isEnabled by rememberSaveable {
|
||||
// mutableStateOf(susfsSUS_SU_Mode() == "2")
|
||||
// }
|
||||
|
||||
// LaunchedEffect(Unit) {
|
||||
// isEnabled = susfsSUS_SU_Mode() == "2"
|
||||
// }
|
||||
|
||||
// SwitchItem(
|
||||
// icon = Icons.Filled.VisibilityOff,
|
||||
// title = stringResource(id = R.string.settings_susfs_toggle),
|
||||
// summary = stringResource(id = R.string.settings_susfs_toggle_summary),
|
||||
// checked = isEnabled
|
||||
// ) {
|
||||
// if (it) {
|
||||
// susfsSUS_SU_2()
|
||||
// } else {
|
||||
// susfsSUS_SU_0()
|
||||
// }
|
||||
// prefs.edit().putBoolean("enable_sus_su", it).apply()
|
||||
// isEnabled = it
|
||||
// }
|
||||
// }
|
||||
|
||||
var checkUpdate by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("check_update", true)
|
||||
|
||||
@@ -120,51 +120,6 @@ fun getModuleCount(): Int {
|
||||
}.getOrElse { return 0 }
|
||||
}
|
||||
|
||||
// private fun getSuSFSDaemonPath(): String {
|
||||
// return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libsusfsd.so"
|
||||
// }
|
||||
|
||||
// fun getSuSFS(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} support")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// fun getSuSFSVersion(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} version")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// fun getSuSFSVariant(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} variant")
|
||||
// return result
|
||||
// }
|
||||
// fun getSuSFSFeatures(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// fun susfsSUS_SU_0(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su 0")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// fun susfsSUS_SU_2(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su 2")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// fun susfsSUS_SU_Mode(): String {
|
||||
// val shell = getRootShell()
|
||||
// val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su mode")
|
||||
// return result
|
||||
// }
|
||||
|
||||
fun getSuperuserCount(): Int {
|
||||
return Natives.allowList.size
|
||||
}
|
||||
|
||||
1
manager/app/src/main/jniLibs/.gitignore
vendored
1
manager/app/src/main/jniLibs/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
libksud.so
|
||||
libsusfs.so
|
||||
@@ -19,8 +19,6 @@
|
||||
<string name="home_failure">Tandatangan KernelSU Next v2 tidak ditemukan pada kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Mohon agar para pengembang kernel anda mengintegrasikan KernelSU Next!</string>
|
||||
<string name="home_kernel">Kernel</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">SuSFS</string>
|
||||
<string name="home_android">Versi Android</string>
|
||||
<string name="home_manager_version">Versi Manager</string>
|
||||
<string name="home_selinux_status">Status SELinux</string>
|
||||
@@ -92,8 +90,6 @@
|
||||
<string name="require_kernel_version">Versi KernelSU-Next %d terlalu rendah agar manajer berfungsi normal. Harap membarui ke versi %d atau di atasnya!</string>
|
||||
<string name="settings_umount_modules_default">Melepas Modul secara bawaan</string>
|
||||
<string name="settings_umount_modules_default_summary">Menggunakan \"Umount Modul\" secara universal pada Profil Aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set profil.</string>
|
||||
<string name="settings_susfs_toggle">Sembunyikan kait su yang mencurigakan</string>
|
||||
<string name="settings_susfs_toggle_summary">Ini menonaktifkan hook kprobe yang dibuat oleh ksu, dan sebagai gantinya hook inline non-kprobe akan diaktifkan, sama seperti implementasi yang sama untuk kernel non-gki tanpa dukungan kprobe.</string>
|
||||
<string name="profile_umount_modules_summary">Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini.</string>
|
||||
<string name="profile_selinux_domain">Domain</string>
|
||||
<string name="profile_selinux_rules">Aturan</string>
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
<string name="home_failure">内核中未找到 KernelSU Next v2 签名! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next!</string>
|
||||
<string name="home_kernel">内核版本</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">SuSFS</string>
|
||||
<string name="home_android">安卓版本</string>
|
||||
<string name="home_manager_version">管理器版本</string>
|
||||
<string name="home_selinux_status">SELinux 状态</string>
|
||||
@@ -94,8 +92,6 @@
|
||||
<string name="require_kernel_version">当前 KernelSU-Next 版本 %d 过低,管理器无法正常工作,请升级内核 KernelSU-Next 版本至 %d 或以上!</string>
|
||||
<string name="settings_umount_modules_default">默认卸载模块</string>
|
||||
<string name="settings_umount_modules_default_summary">App Profile 中\"卸载模块\"的全局默认值,如果启用,将会为没有设置 Profile 的应用移除所有模块针对系统的修改。</string>
|
||||
<string name="settings_susfs_toggle">使用 SuSFS 隐藏可疑的 su</string>
|
||||
<string name="settings_susfs_toggle_summary">它会禁用由 ksu 创建的 kprobe 钩子,并启用非 kprobe 的内联钩子,与不支持 kprobe 的非 gki 内核具有相同的实现。</string>
|
||||
<string name="profile_umount_modules_summary">启用后将允许 KernelSU-Next 为本应用还原被模块修改过的文件。</string>
|
||||
<string name="profile_selinux_domain">域</string>
|
||||
<string name="profile_selinux_rules">规则</string>
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
<string name="home_failure">KernelSU Next v2 signature not found in kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Ask your kernel developer to integrate KernelSU Next!</string>
|
||||
<string name="home_kernel">Kernel Version</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Android Version</string>
|
||||
<string name="home_manager_version">Manager Version</string>
|
||||
<string name="home_selinux_status">SELinux Mode</string>
|
||||
@@ -95,8 +92,6 @@
|
||||
<string name="require_kernel_version">The current KernelSU-Next version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string>
|
||||
<string name="settings_umount_modules_default">Umount modules by default</string>
|
||||
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
|
||||
<string name="settings_susfs_toggle">Hide suspecious su hooks</string>
|
||||
<string name="settings_susfs_toggle_summary">It disables kprobe hooks made by ksu, and instead the non-kprobe inline hooks will be enabled, just the same implementation for non-gki kernel without kprobe supported.</string>
|
||||
<string name="profile_umount_modules_summary">Enabling this option will allow KernelSU-Next to restore any modified files by the modules for this app.</string>
|
||||
<string name="profile_selinux_domain">Domain</string>
|
||||
<string name="profile_selinux_rules">Rules</string>
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
use anyhow::{anyhow, bail, Ok, Result};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use anyhow::Context;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use rustix::{fd::AsFd, fs::CWD, mount::*};
|
||||
|
||||
use crate::defs::KSU_OVERLAY_SOURCE;
|
||||
use log::{info, warn};
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use procfs::process::Process;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct AutoMountExt4 {
|
||||
target: String,
|
||||
auto_umount: bool,
|
||||
}
|
||||
|
||||
impl AutoMountExt4 {
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn try_new(source: &str, target: &str, auto_umount: bool) -> Result<Self> {
|
||||
mount_ext4(source, target)?;
|
||||
Ok(Self {
|
||||
target: target.to_string(),
|
||||
auto_umount,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn try_new(_src: &str, _mnt: &str, _auto_umount: bool) -> Result<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn umount(&self) -> Result<()> {
|
||||
unmount(self.target.as_str(), UnmountFlags::DETACH)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
impl Drop for AutoMountExt4 {
|
||||
fn drop(&mut self) {
|
||||
log::info!(
|
||||
"AutoMountExt4 drop: {}, auto_umount: {}",
|
||||
self.target,
|
||||
self.auto_umount
|
||||
);
|
||||
if self.auto_umount {
|
||||
let _ = self.umount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn mount_ext4(source: impl AsRef<Path>, target: impl AsRef<Path>) -> Result<()> {
|
||||
let new_loopback = loopdev::LoopControl::open()?
|
||||
.next_free()
|
||||
.with_context(|| "Failed to alloc loop")?;
|
||||
new_loopback
|
||||
.with()
|
||||
.attach(source)
|
||||
.with_context(|| "Failed to attach loop")?;
|
||||
let lo = new_loopback.path().ok_or(anyhow!("no loop"))?;
|
||||
if let Result::Ok(fs) = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC) {
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "source", lo)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
target.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
} else {
|
||||
mount(lo, target.as_ref(), "ext4", MountFlags::empty(), "")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn umount_dir(src: impl AsRef<Path>) -> Result<()> {
|
||||
unmount(src.as_ref(), UnmountFlags::empty())
|
||||
.with_context(|| format!("Failed to umount {}", src.as_ref().display()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn mount_overlayfs(
|
||||
lower_dirs: &[String],
|
||||
lowest: &str,
|
||||
upperdir: Option<PathBuf>,
|
||||
workdir: Option<PathBuf>,
|
||||
dest: impl AsRef<Path>,
|
||||
) -> Result<()> {
|
||||
let lowerdir_config = lower_dirs
|
||||
.iter()
|
||||
.map(|s| s.as_ref())
|
||||
.chain(std::iter::once(lowest))
|
||||
.collect::<Vec<_>>()
|
||||
.join(":");
|
||||
info!(
|
||||
"mount overlayfs on {:?}, lowerdir={}, upperdir={:?}, workdir={:?}",
|
||||
dest.as_ref(),
|
||||
lowerdir_config,
|
||||
upperdir,
|
||||
workdir
|
||||
);
|
||||
|
||||
let upperdir = upperdir
|
||||
.filter(|up| up.exists())
|
||||
.map(|e| e.display().to_string());
|
||||
let workdir = workdir
|
||||
.filter(|wd| wd.exists())
|
||||
.map(|e| e.display().to_string());
|
||||
|
||||
let result = (|| {
|
||||
let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?;
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "lowerdir", &lowerdir_config)?;
|
||||
if let (Some(upperdir), Some(workdir)) = (&upperdir, &workdir) {
|
||||
fsconfig_set_string(fs, "upperdir", upperdir)?;
|
||||
fsconfig_set_string(fs, "workdir", workdir)?;
|
||||
}
|
||||
fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
dest.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)
|
||||
})();
|
||||
|
||||
if let Err(e) = result {
|
||||
warn!("fsopen mount failed: {:#}, fallback to mount", e);
|
||||
let mut data = format!("lowerdir={lowerdir_config}");
|
||||
if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) {
|
||||
data = format!("{data},upperdir={upperdir},workdir={workdir}");
|
||||
}
|
||||
mount(
|
||||
KSU_OVERLAY_SOURCE,
|
||||
dest.as_ref(),
|
||||
"overlay",
|
||||
MountFlags::empty(),
|
||||
data,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn mount_tmpfs(dest: impl AsRef<Path>) -> Result<()> {
|
||||
info!("mount tmpfs on {}", dest.as_ref().display());
|
||||
if let Result::Ok(fs) = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC) {
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
dest.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
} else {
|
||||
mount(
|
||||
KSU_OVERLAY_SOURCE,
|
||||
dest.as_ref(),
|
||||
"tmpfs",
|
||||
MountFlags::empty(),
|
||||
"",
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn bind_mount(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
|
||||
info!(
|
||||
"bind mount {} -> {}",
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display()
|
||||
);
|
||||
if let Result::Ok(tree) = open_tree(
|
||||
CWD,
|
||||
from.as_ref(),
|
||||
OpenTreeFlags::OPEN_TREE_CLOEXEC
|
||||
| OpenTreeFlags::OPEN_TREE_CLONE
|
||||
| OpenTreeFlags::AT_RECURSIVE,
|
||||
) {
|
||||
move_mount(
|
||||
tree.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
to.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
} else {
|
||||
mount(
|
||||
from.as_ref(),
|
||||
to.as_ref(),
|
||||
"",
|
||||
MountFlags::BIND | MountFlags::REC,
|
||||
"",
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn mount_overlay_child(
|
||||
mount_point: &str,
|
||||
relative: &String,
|
||||
module_roots: &Vec<String>,
|
||||
stock_root: &String,
|
||||
) -> Result<()> {
|
||||
if !module_roots
|
||||
.iter()
|
||||
.any(|lower| Path::new(&format!("{lower}{relative}")).exists())
|
||||
{
|
||||
return bind_mount(stock_root, mount_point);
|
||||
}
|
||||
if !Path::new(&stock_root).is_dir() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut lower_dirs: Vec<String> = vec![];
|
||||
for lower in module_roots {
|
||||
let lower_dir = format!("{lower}{relative}");
|
||||
let path = Path::new(&lower_dir);
|
||||
if path.is_dir() {
|
||||
lower_dirs.push(lower_dir);
|
||||
} else if path.exists() {
|
||||
// stock root has been blocked by this file
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
if lower_dirs.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
// merge modules and stock
|
||||
if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) {
|
||||
warn!("failed: {:#}, fallback to bind mount", e);
|
||||
bind_mount(stock_root, mount_point)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn mount_overlay(
|
||||
root: &String,
|
||||
module_roots: &Vec<String>,
|
||||
workdir: Option<PathBuf>,
|
||||
upperdir: Option<PathBuf>,
|
||||
) -> Result<()> {
|
||||
info!("mount overlay for {}", root);
|
||||
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
|
||||
let stock_root = ".";
|
||||
|
||||
// collect child mounts before mounting the root
|
||||
let mounts = Process::myself()?
|
||||
.mountinfo()
|
||||
.with_context(|| "get mountinfo")?;
|
||||
let mut mount_seq = mounts
|
||||
.0
|
||||
.iter()
|
||||
.filter(|m| {
|
||||
m.mount_point.starts_with(root) && !Path::new(&root).starts_with(&m.mount_point)
|
||||
})
|
||||
.map(|m| m.mount_point.to_str())
|
||||
.collect::<Vec<_>>();
|
||||
mount_seq.sort();
|
||||
mount_seq.dedup();
|
||||
|
||||
mount_overlayfs(module_roots, root, upperdir, workdir, root)
|
||||
.with_context(|| "mount overlayfs for root failed")?;
|
||||
for mount_point in mount_seq.iter() {
|
||||
let Some(mount_point) = mount_point else {
|
||||
continue;
|
||||
};
|
||||
let relative = mount_point.replacen(root, "", 1);
|
||||
let stock_root: String = format!("{stock_root}{relative}");
|
||||
if !Path::new(&stock_root).exists() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = mount_overlay_child(mount_point, &relative, module_roots, &stock_root) {
|
||||
warn!(
|
||||
"failed to mount overlay for child {}: {:#}, revert",
|
||||
mount_point, e
|
||||
);
|
||||
umount_dir(root).with_context(|| format!("failed to revert {root}"))?;
|
||||
bail!(e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn mount_ext4(_src: &str, _target: &str, _autodrop: bool) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn umount_dir(_src: &str) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn mount_overlay(
|
||||
_root: &String,
|
||||
_module_roots: &Vec<String>,
|
||||
_workdir: Option<PathBuf>,
|
||||
_upperdir: Option<PathBuf>,
|
||||
) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn mount_tmpfs(_dest: impl AsRef<Path>) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
2
userspace/susfsd/.gitignore
vendored
2
userspace/susfsd/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/obj
|
||||
/libs
|
||||
@@ -1,6 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := susfsd
|
||||
LOCAL_SRC_FILES := susfsd.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -1,3 +0,0 @@
|
||||
APP_ABI := arm64-v8a
|
||||
APP_PLATFORM := android-24
|
||||
APP_STL := none
|
||||
@@ -1,239 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||
|
||||
#define CMD_SUSFS_SHOW_VERSION 0x555e1
|
||||
#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2
|
||||
#define CMD_SUSFS_SHOW_VARIANT 0x555e3
|
||||
#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4
|
||||
#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0
|
||||
#define CMD_SUSFS_SUS_SU 0x60000
|
||||
|
||||
#define SUS_SU_DISABLED 0
|
||||
#define SUS_SU_WITH_HOOKS 2
|
||||
|
||||
struct st_sus_su {
|
||||
int mode;
|
||||
};
|
||||
|
||||
int enable_sus_su(int last_working_mode, int target_working_mode) {
|
||||
struct st_sus_su info;
|
||||
int error = -1;
|
||||
|
||||
if (target_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
info.mode = SUS_SU_WITH_HOOKS;
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error);
|
||||
if (error) {
|
||||
if (error == 1) {
|
||||
} else if (error == 2) {
|
||||
}
|
||||
return error;
|
||||
}
|
||||
printf("[+] sus_su mode 2 is enabled\n");
|
||||
} else if (target_working_mode == SUS_SU_DISABLED) {
|
||||
info.mode = SUS_SU_DISABLED;
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error);
|
||||
if (error) {
|
||||
if (error == 1) {
|
||||
}
|
||||
return error;
|
||||
}
|
||||
printf("[+] sus_su mode 0 is enabled\n");
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int error = -1;
|
||||
char support[16];
|
||||
char version[16];
|
||||
char variant[16];
|
||||
|
||||
|
||||
|
||||
// Check for arguments
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <support|version|variant|features|sus_su <0|2|mode>|>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "version") == 0) {
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VERSION, version, NULL, &error);
|
||||
if (!error) {
|
||||
printf("%s\n", version);
|
||||
} else {
|
||||
printf("Invalid\n");
|
||||
}
|
||||
} else if (strcmp(argv[1], "variant") == 0) {
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VARIANT, variant, NULL, &error);
|
||||
if (!error) {
|
||||
printf("%s\n", variant);
|
||||
} else {
|
||||
printf("Invalid\n");
|
||||
}
|
||||
} else if (strcmp(argv[1], "features") == 0) {
|
||||
char *enabled_features_buf = malloc(getpagesize() * 2);
|
||||
char *ptr_buf;
|
||||
unsigned long enabled_features;
|
||||
int str_len;
|
||||
|
||||
if (!enabled_features_buf) {
|
||||
perror("malloc");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ptr_buf = enabled_features_buf;
|
||||
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error);
|
||||
if (!error) {
|
||||
if (enabled_features & (1 << 0)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SUS_PATH\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_PATH\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 1)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SUS_MOUNT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_MOUNT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 2)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 3)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 4)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SUS_KSTAT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_KSTAT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 5)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 6)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_TRY_UMOUNT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_TRY_UMOUNT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 7)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 8)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_UNAME\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_UNAME\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 9)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_ENABLE_LOG\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_ENABLE_LOG\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 10)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 11)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 12)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_OPEN_REDIRECT\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_OPEN_REDIRECT\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
if (enabled_features & (1 << 13)) {
|
||||
str_len = strlen("CONFIG_KSU_SUSFS_SUS_SU\n");
|
||||
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_SU\n", str_len);
|
||||
ptr_buf += str_len;
|
||||
}
|
||||
printf("%s", enabled_features_buf);
|
||||
free(enabled_features_buf);
|
||||
} else {
|
||||
printf("Invalid\n");
|
||||
}
|
||||
} else if (strcmp(argv[1], "support") == 0) {
|
||||
unsigned long enabled_features;
|
||||
int any_feature_enabled = 0;
|
||||
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error);
|
||||
if (!error) {
|
||||
if (enabled_features & ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
|
||||
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) |
|
||||
(1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) |
|
||||
(1 << 12) | (1 << 13))) {
|
||||
any_feature_enabled = 1;
|
||||
}
|
||||
if (any_feature_enabled) {
|
||||
printf("Supported\n");
|
||||
} else {
|
||||
printf("Unsupported\n");
|
||||
}
|
||||
} else {
|
||||
printf("Unsupported\n");
|
||||
}
|
||||
} else if (argc == 3 && !strcmp(argv[1], "sus_su")) {
|
||||
int last_working_mode = 0;
|
||||
int target_working_mode;
|
||||
char* endptr;
|
||||
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!strcmp(argv[2], "mode")) {
|
||||
printf("%d\n", last_working_mode);
|
||||
return 0;
|
||||
}
|
||||
target_working_mode = strtol(argv[2], &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
return 1;
|
||||
}
|
||||
if (target_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
bool is_sus_su_ready;
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!is_sus_su_ready) {
|
||||
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
|
||||
return 1;
|
||||
}
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
} else {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
if (!error)
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
}
|
||||
} else if (target_working_mode == SUS_SU_DISABLED) {
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
}
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user