From d72c4237278de55162cdc1567bce864c29395a3a Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:17:19 +0800 Subject: [PATCH 1/6] Add opt-in PROOT_NO_SECCOMP compat switch to terminal environment Read the proot_no_seccomp_compat boolean from terminal_settings in buildEnvironment(). When enabled, inject PROOT_NO_SECCOMP=1 so that proot does not install its seccomp filter. This works around ENOSYS failures on chdir/getcwd/shebang/static execve seen on HarmonyOS NEXT (AAswordman/Operit#1128). Default remains off, no behavior change for other devices. --- .../terminal/provider/type/LocalTerminalProvider.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/ai/assistance/operit/terminal/provider/type/LocalTerminalProvider.kt b/src/main/java/com/ai/assistance/operit/terminal/provider/type/LocalTerminalProvider.kt index a38dd4f..72766bd 100644 --- a/src/main/java/com/ai/assistance/operit/terminal/provider/type/LocalTerminalProvider.kt +++ b/src/main/java/com/ai/assistance/operit/terminal/provider/type/LocalTerminalProvider.kt @@ -566,6 +566,16 @@ class LocalTerminalProvider( env["PROOT_TMP_DIR"] = File(filesDir, "tmp").absolutePath env["TERM"] = "xterm-256color" env["LANG"] = "en_US.UTF-8" + + // HarmonyOS NEXT proot compatibility: on some HarmonyOS devices proot's + // seccomp filter breaks chdir/getcwd/shebang/static execve with ENOSYS + // (see https://github.com/AAswordman/Operit/issues/1128). Injecting + // PROOT_NO_SECCOMP=1 makes proot skip installing the seccomp filter. + // Opt-in via settings, default off. + val settingsPrefs = context.getSharedPreferences("terminal_settings", Context.MODE_PRIVATE) + if (settingsPrefs.getBoolean("proot_no_seccomp_compat", false)) { + env["PROOT_NO_SECCOMP"] = "1" + } return env } } From a794e801738ef1e28e0e21e54cc45b586cad2223 Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:17:34 +0800 Subject: [PATCH 2/6] Add proot no-seccomp compat setting state to SettingsViewModel Mirror the existing chroot_enabled pattern: a boolean stored in the terminal_settings SharedPreferences plus a StateFlow for the UI. --- .../operit/terminal/ui/SettingsViewModel.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsViewModel.kt b/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsViewModel.kt index 8179c07..2d0ee70 100644 --- a/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsViewModel.kt +++ b/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsViewModel.kt @@ -89,6 +89,10 @@ class SettingsViewModel( private val _chrootEnabled = MutableStateFlow(false) val chrootEnabled = _chrootEnabled.asStateFlow() + // HarmonyOS proot compat (PROOT_NO_SECCOMP) setting state + private val _prootNoSeccompCompat = MutableStateFlow(false) + val prootNoSeccompCompat = _prootNoSeccompCompat.asStateFlow() + private val _chrootMountStatus = MutableStateFlow( application.getString(com.ai.assistance.operit.terminal.R.string.chroot_mount_status_idle) ) @@ -115,6 +119,7 @@ class SettingsViewModel( loadSSHEnabled() loadSharedTmpSetting() loadChrootSetting() + loadProotNoSeccompCompat() loadVirtualKeyboardLayout() } @@ -507,6 +512,19 @@ class SettingsViewModel( return prefs.getBoolean("chroot_enabled", false) } + private fun loadProotNoSeccompCompat() { + _prootNoSeccompCompat.value = prefs.getBoolean("proot_no_seccomp_compat", false) + } + + fun setProotNoSeccompCompat(enabled: Boolean) { + prefs.edit().putBoolean("proot_no_seccomp_compat", enabled).apply() + _prootNoSeccompCompat.value = enabled + } + + fun isProotNoSeccompCompat(): Boolean { + return prefs.getBoolean("proot_no_seccomp_compat", false) + } + private fun loadVirtualKeyboardLayout() { _virtualKeyboardLayout.value = virtualKeyboardConfigManager.loadLayout() } From 900306cc463f1cb25d8bbf3f69d9d4a07f56c854 Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:18:04 +0800 Subject: [PATCH 3/6] Add proot no-seccomp compat switch to terminal settings screen New settings card mirroring the chroot/shared_tmp switch style, placed next to the chroot mode card. --- .../operit/terminal/ui/SettingsScreen.kt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsScreen.kt b/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsScreen.kt index ff8b6c2..923bc01 100644 --- a/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsScreen.kt +++ b/src/main/java/com/ai/assistance/operit/terminal/ui/SettingsScreen.kt @@ -100,6 +100,7 @@ fun SettingsScreen( val sharedTmpEnabled by viewModel.sharedTmpEnabled.collectAsState() val chrootEnabled by viewModel.chrootEnabled.collectAsState() + val prootNoSeccompCompat by viewModel.prootNoSeccompCompat.collectAsState() val chrootMountStatus by viewModel.chrootMountStatus.collectAsState() val chrootMountDetails by viewModel.chrootMountDetails.collectAsState() val isInspectingChrootMounts by viewModel.isInspectingChrootMounts.collectAsState() @@ -634,6 +635,59 @@ fun SettingsScreen( } } + // HarmonyOS proot compat (PROOT_NO_SECCOMP) setting card + Card( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + colors = CardDefaults.cardColors(containerColor = SettingsTheme.surfaceColor) + ) { + Column(modifier = Modifier.padding(16.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = context.getString(com.ai.assistance.operit.terminal.R.string.proot_no_seccomp_compat_title), + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + color = SettingsTheme.onSurfaceColor + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = if (prootNoSeccompCompat) { + context.getString(com.ai.assistance.operit.terminal.R.string.proot_no_seccomp_compat_enabled_desc) + } else { + context.getString(com.ai.assistance.operit.terminal.R.string.proot_no_seccomp_compat_disabled_desc) + }, + fontSize = 14.sp, + color = SettingsTheme.onSurfaceVariant + ) + } + Switch( + checked = prootNoSeccompCompat, + onCheckedChange = { enabled -> + viewModel.setProotNoSeccompCompat(enabled) + }, + colors = SwitchDefaults.colors( + checkedThumbColor = SettingsTheme.primaryColor, + checkedTrackColor = SettingsTheme.primaryColor.copy(alpha = 0.5f) + ) + ) + } + + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = context.getString(com.ai.assistance.operit.terminal.R.string.proot_no_seccomp_compat_note), + fontSize = 12.sp, + color = SettingsTheme.onSurfaceVariant.copy(alpha = 0.8f), + lineHeight = 16.sp + ) + } + } + Card( modifier = Modifier .fillMaxWidth() From c12f23dec4ea0131b086614d048227ffb61a29b5 Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:18:21 +0800 Subject: [PATCH 4/6] Add Chinese strings for proot no-seccomp compat setting --- src/main/res/values/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 1d95974..7c47799 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -153,6 +153,10 @@ 已启用 - 使用 chroot 启动 Ubuntu(需要 Root) 已禁用 - 使用 proot 启动 Ubuntu 注意:chroot 模式会将 /proc、/sys、/dev(含 /dev/pts)挂载到 Ubuntu 环境中,请各位 Root 用户谨慎对待。并且该模式需要设备已 Root 且授予本应用 Root 权限,否则可能无法启动 + 鸿蒙 proot 兼容模式 + 已启用 - 启动 proot 时注入 PROOT_NO_SECCOMP=1 环境变量 + 已禁用 - 不注入额外环境变量 + 注意:仅适用于存在 proot seccomp 兼容问题的设备(如 HarmonyOS NEXT,表现为 chdir/getcwd/shebang 执行返回 ENOSYS、终端会话无法启动)。开启后 proot 将不再安装 seccomp 过滤器,可恢复正常。其他设备请保持关闭 检测挂载 解挂载 尚未检测 chroot 挂载 From 449ff1ba32379890ff5a80015e31e45fd182e13b Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:18:36 +0800 Subject: [PATCH 5/6] Add English strings for proot no-seccomp compat setting --- src/main/res/values-en/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/res/values-en/strings.xml b/src/main/res/values-en/strings.xml index 0ebf848..c18fd3a 100644 --- a/src/main/res/values-en/strings.xml +++ b/src/main/res/values-en/strings.xml @@ -153,6 +153,10 @@ Enabled - Start Ubuntu via chroot (Root required) Disabled - Start Ubuntu via proot Note: chroot mode mounts /proc, /sys, /dev (including /dev/pts) into the Ubuntu environment. Root users, please use with caution. This mode requires a rooted device and root permission granted to this app, otherwise startup may fail + HarmonyOS proot compat mode + Enabled - Inject PROOT_NO_SECCOMP=1 when starting proot + Disabled - No extra environment variable + Note: Only enable this on devices where proot's seccomp filter breaks the terminal (e.g. HarmonyOS NEXT, where chdir/getcwd/shebang return ENOSYS and terminal sessions fail to start). When enabled, proot runs without installing its seccomp filter. Keep it off on other devices Inspect Mounts Unmount chroot mounts have not been inspected yet From 611feeea7b86415afc5e01ade68aa4ba9ebf6978 Mon Sep 17 00:00:00 2001 From: lzmd66 Date: Fri, 11 Sep 2026 00:23:15 +0800 Subject: [PATCH 6/6] Fix unescaped apostrophe in compat note string (aapt2 build error) --- src/main/res/values-en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-en/strings.xml b/src/main/res/values-en/strings.xml index c18fd3a..b1f0c38 100644 --- a/src/main/res/values-en/strings.xml +++ b/src/main/res/values-en/strings.xml @@ -156,7 +156,7 @@ HarmonyOS proot compat mode Enabled - Inject PROOT_NO_SECCOMP=1 when starting proot Disabled - No extra environment variable - Note: Only enable this on devices where proot's seccomp filter breaks the terminal (e.g. HarmonyOS NEXT, where chdir/getcwd/shebang return ENOSYS and terminal sessions fail to start). When enabled, proot runs without installing its seccomp filter. Keep it off on other devices + Note: Only enable this on devices where the proot seccomp filter breaks the terminal (e.g. HarmonyOS NEXT, where chdir/getcwd/shebang return ENOSYS and terminal sessions fail to start). When enabled, proot runs without installing the seccomp filter. Keep it off on other devices Inspect Mounts Unmount chroot mounts have not been inspected yet