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); }