diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt b/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt
index 99fc4ddd..73ac13af 100644
--- a/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt
+++ b/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt
@@ -120,6 +120,9 @@ object Natives {
return version < MINIMAL_SUPPORTED_KERNEL
}
+ val KSU_WORK_DIR = "/data/adb/ksu/"
+ val GLOBAL_NAMESPACE_FILE = KSU_WORK_DIR + ".global_mnt"
+
@Immutable
@Parcelize
@Keep
diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt
index 4860dfb0..5ec1734d 100644
--- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt
+++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt
@@ -88,6 +88,8 @@ import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.getBugreportFile
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.format.DateTimeFormatter
@@ -101,6 +103,8 @@ import java.time.format.DateTimeFormatter
fun SettingScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
+ var isGlobalNamespaceEnabled by rememberSaveable { mutableStateOf(false) }
+ isGlobalNamespaceEnabled = isGlobalNamespaceEnabled()
val isManager = Natives.becomeManager(ksuApp.packageName)
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)
diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt
index 08b6e858..09fa951c 100644
--- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt
+++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt
@@ -103,7 +103,10 @@ fun Uri.getFileName(context: Context): String? {
fun createRootShell(globalMnt: Boolean = false): Shell {
Shell.enableVerboseLogging = BuildConfig.DEBUG
- val builder = Shell.Builder.create()
+ val builder = Shell.Builder.create().apply {
+ setFlags(Shell.FLAG_MOUNT_MASTER)
+ }
+
return try {
if (globalMnt) {
builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
@@ -403,6 +406,22 @@ fun hasMagisk(): Boolean {
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 {
if (rules == null) {
return true
diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml
index a31c71cb..47c885f1 100644
--- a/manager/app/src/main/res/values/strings.xml
+++ b/manager/app/src/main/res/values/strings.xml
@@ -231,4 +231,6 @@
Sort (Enabled first)
Sort (Action first)
Sort (WebUI first)
+ Global Namespace Mode
+ All root sessions use the global mount namespace
diff --git a/userspace/ksud_magic/src/defs.rs b/userspace/ksud_magic/src/defs.rs
index 95633257..33cf32dc 100644
--- a/userspace/ksud_magic/src/defs.rs
+++ b/userspace/ksud_magic/src/defs.rs
@@ -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 MOUNT_SYSTEM: &str = "Magic_Mount";
+
+pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");
\ No newline at end of file
diff --git a/userspace/ksud_magic/src/su.rs b/userspace/ksud_magic/src/su.rs
index f5d9e764..8d757dca 100644
--- a/userspace/ksud_magic/src/su.rs
+++ b/userspace/ksud_magic/src/su.rs
@@ -261,7 +261,10 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace
#[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);
}
diff --git a/userspace/ksud_overlayfs/src/defs.rs b/userspace/ksud_overlayfs/src/defs.rs
index 5d49c1c9..232ff8f1 100644
--- a/userspace/ksud_overlayfs/src/defs.rs
+++ b/userspace/ksud_overlayfs/src/defs.rs
@@ -47,3 +47,5 @@ pub const KSU_BACKUP_FILE_PREFIX: &str = "ksu_backup_";
pub const BACKUP_FILENAME: &str = "stock_image.sha1";
pub const MOUNT_SYSTEM: &str = "OverlayFS";
+
+pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");
diff --git a/userspace/ksud_overlayfs/src/su.rs b/userspace/ksud_overlayfs/src/su.rs
index 5f3abdd7..5a6876a4 100644
--- a/userspace/ksud_overlayfs/src/su.rs
+++ b/userspace/ksud_overlayfs/src/su.rs
@@ -261,7 +261,10 @@ pub fn root_shell() -> Result<()> {
// switch to global mount namespace
#[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);
}