manager | ksud: Add toggle for global mount namespace (#99)

* This is untested, if you facing any issues, open a new issue or comments at our group
* and also, this changes maybe reverted if didn't meet the target.

Taken from Apatch's implementations:
8de6b9d676
57d527a846
f093d6a633

Critics are welcome!

Signed-off-by: rsuntk <90097027+rsuntk@users.noreply.github.com>
This commit is contained in:
Alessandro Paluzzi
2025-05-24 15:52:45 +07:00
committed by Rifat Azad
parent a917314e84
commit c6b5440682
8 changed files with 58 additions and 3 deletions

View File

@@ -120,6 +120,9 @@ object Natives {
return version < MINIMAL_SUPPORTED_KERNEL return version < MINIMAL_SUPPORTED_KERNEL
} }
val KSU_WORK_DIR = "/data/adb/ksu/"
val GLOBAL_NAMESPACE_FILE = KSU_WORK_DIR + ".global_mnt"
@Immutable @Immutable
@Parcelize @Parcelize
@Keep @Keep

View File

@@ -88,6 +88,8 @@ import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.getBugreportFile import com.rifsxd.ksunext.ui.util.getBugreportFile
import com.rifsxd.ksunext.ui.util.* import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.isGlobalNamespaceEnabled
import com.rifsxd.ksunext.ui.util.setGlobalNamespaceEnabled
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@@ -101,6 +103,8 @@ import java.time.format.DateTimeFormatter
fun SettingScreen(navigator: DestinationsNavigator) { fun SettingScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current val snackBarHost = LocalSnackbarHost.current
var isGlobalNamespaceEnabled by rememberSaveable { mutableStateOf(false) }
isGlobalNamespaceEnabled = isGlobalNamespaceEnabled()
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null val ksuVersion = if (isManager) Natives.version else null
@@ -196,6 +200,23 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
} }
} }
SwitchItem(
icon = Icons.Filled.Engineering,
title = stringResource(id = R.string.settings_global_namespace_mode),
summary = stringResource(id = R.string.settings_global_namespace_mode_summary),
checked = isGlobalNamespaceEnabled,
onCheckedChange = {
setGlobalNamespaceEnabled(
if (isGlobalNamespaceEnabled) {
"0"
} else {
"1"
}
)
isGlobalNamespaceEnabled = it
}
)
} }
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)

View File

@@ -103,7 +103,10 @@ fun Uri.getFileName(context: Context): String? {
fun createRootShell(globalMnt: Boolean = false): Shell { fun createRootShell(globalMnt: Boolean = false): Shell {
Shell.enableVerboseLogging = BuildConfig.DEBUG Shell.enableVerboseLogging = BuildConfig.DEBUG
val builder = Shell.Builder.create() val builder = Shell.Builder.create().apply {
setFlags(Shell.FLAG_MOUNT_MASTER)
}
return try { return try {
if (globalMnt) { if (globalMnt) {
builder.build(ksuDaemonMagicPath(), "debug", "su", "-g") builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
@@ -403,6 +406,22 @@ fun hasMagisk(): Boolean {
return result.isSuccess return result.isSuccess
} }
fun isGlobalNamespaceEnabled(): Boolean {
val shell = getRootShell()
val result =
ShellUtils.fastCmd(shell, "nsenter --mount=/proc/1/ns/mnt cat ${Natives.GLOBAL_NAMESPACE_FILE}")
Log.i(TAG, "is global namespace enabled: $result")
return result == "1"
}
fun setGlobalNamespaceEnabled(value: String) {
getRootShell().newJob()
.add("nsenter --mount=/proc/1/ns/mnt echo $value > ${Natives.GLOBAL_NAMESPACE_FILE}")
.submit { result ->
Log.i(TAG, "setGlobalNamespaceEnabled result: ${result.isSuccess} [${result.out}]")
}
}
fun isSepolicyValid(rules: String?): Boolean { fun isSepolicyValid(rules: String?): Boolean {
if (rules == null) { if (rules == null) {
return true return true

View File

@@ -231,4 +231,6 @@
<string name="module_sort_enabled_first">Sort (Enabled first)</string> <string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="module_sort_action_first">Sort (Action first)</string> <string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_webui_first">Sort (WebUI first)</string> <string name="module_sort_webui_first">Sort (WebUI first)</string>
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
</resources> </resources>

View File

@@ -44,3 +44,5 @@ pub const NO_TMPFS_PATH: &str = concatcp!(WORKING_DIR, ".notmpfs");
pub const NO_MOUNT_PATH: &str = concatcp!(WORKING_DIR, ".nomount"); pub const NO_MOUNT_PATH: &str = concatcp!(WORKING_DIR, ".nomount");
pub const MOUNT_SYSTEM: &str = "Magic_Mount"; pub const MOUNT_SYSTEM: &str = "Magic_Mount";
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");

View File

@@ -261,7 +261,10 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace // switch to global mount namespace
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
if mount_master { let global_namespace_enable =
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE)
.unwrap_or("0".to_string());
if global_namespace_enable.trim() == "1" || mount_master {
let _ = utils::switch_mnt_ns(1); let _ = utils::switch_mnt_ns(1);
} }

View File

@@ -47,3 +47,5 @@ pub const KSU_BACKUP_FILE_PREFIX: &str = "ksu_backup_";
pub const BACKUP_FILENAME: &str = "stock_image.sha1"; pub const BACKUP_FILENAME: &str = "stock_image.sha1";
pub const MOUNT_SYSTEM: &str = "OverlayFS"; pub const MOUNT_SYSTEM: &str = "OverlayFS";
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");

View File

@@ -261,7 +261,10 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace // switch to global mount namespace
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
if mount_master { let global_namespace_enable =
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE)
.unwrap_or("0".to_string());
if global_namespace_enable.trim() == "1" || mount_master {
let _ = utils::switch_mnt_ns(1); let _ = utils::switch_mnt_ns(1);
} }