Skip to content

Add opt-in HarmonyOS proot compat switch (PROOT_NO_SECCOMP=1), fix #1128 - #5

Draft
lzmd66 wants to merge 6 commits into
AAswordman:masterfrom
lzmd66:proot-no-seccomp-compat
Draft

Add opt-in HarmonyOS proot compat switch (PROOT_NO_SECCOMP=1), fix #1128#5
lzmd66 wants to merge 6 commits into
AAswordman:masterfrom
lzmd66:proot-no-seccomp-compat

Conversation

@lzmd66

@lzmd66 lzmd66 commented Sep 10, 2026

Copy link
Copy Markdown

Summary

Adds an opt-in, default-off setting that injects PROOT_NO_SECCOMP=1 into the terminal environment when enabled, fixing proot startup failures on HarmonyOS NEXT.

Fixes #1128 (tracked in AAswordman/Operit#1128)

Background

On HarmonyOS NEXT (hosted on Mate devices via HarmonyOS NEXT + 卓易通/Android compatibility layer), proot's seccomp filter causes commands to fail with ENOSYS (Errno 38) on chdir, getcwd, shebang execution and static ELF execve. Terminal sessions either fail to initialize or intermittently hang.

Verified workaround: injecting export PROOT_NO_SECCOMP=1 before proot starts. The only reliable injection point is the shell scripts sourced before exec proot (setup_fake_sysdata.sh / common.sh), because buildEnvironment() whitelists env vars and the Kotlin code overwrites these files on every init.

What this PR does

File Change
LocalTerminalProvider.kt buildEnvironment() reads proot_no_seccomp_compat from terminal_settings prefs and injects env["PROOT_NO_SECCOMP"] = "1" when enabled
SettingsViewModel.kt Setting state + load/save/getter, mirroring the existing chroot_enabled pattern
SettingsScreen.kt New settings card with a switch, mirroring the chroot/shared_tmp card style
values/strings.xml / values-en/strings.xml New strings (title / enabled desc / disabled desc / note)

Design notes:

  • Default off — zero behavior change for all existing users; only HarmonyOS users opt in
  • Follows existing project patterns exactly (chroot/shared_tmp settings model, Compose card + Switch UI)
  • Injecting via buildEnvironment() (rather than patching shell scripts) means the fix survives asset re-extraction and app updates — no persistence issue

Real-device verification (HarmonyOS NEXT, Mate 80 Pro / 卓易通)

Tested against both release v1.12.1 and nightly v1.12.1+6:

Test Without env var With PROOT_NO_SECCOMP=1
chdir / getcwd ENOSYS (Errno 38) ✅ normal
shebang script execution fails ✅ normal
static ELF execve fails ✅ normal
Python 3.12.3 in Ubuntu proot broken ✅ works

Reproduction data: the patched shell scripts were wiped by app updates 3 times (each Operit upgrade re-extracts assets and overwrites setup_fake_sysdata.sh), each time breaking the terminal again — which is exactly why this needs to live in app code rather than a user-side patch.

Merge readiness

I can't run the Gradle build locally (Android phone environment), so CI is the arbiter for compile correctness. Happy to adjust naming, wording, or the switch placement per maintainer preference. The issue reporter (me) is available for further real-device testing of any follow-up build.

cc @3316891527

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.
Mirror the existing chroot_enabled pattern: a boolean stored in the
terminal_settings SharedPreferences plus a StateFlow for the UI.
New settings card mirroring the chroot/shared_tmp switch style,
placed next to the chroot mode card.
@lzmd66

lzmd66 commented Sep 10, 2026

Copy link
Copy Markdown
Author

Correction to my earlier note: I said the PR would stay in draft "until CI confirms it compiles" — turns out this repo has no CI workflows configured, so there is nothing to wait for on that front.

What I did instead (static verification, since I have no local Gradle build on the phone):

  • Reviewed the full PR diff line by line; all new symbols (prootNoSeccompCompat, setProotNoSeccompCompat, loadProotNoSeccompCompat, the proot_no_seccomp_compat pref key) are defined/referenced consistently across the three Kotlin files
  • All Compose APIs used in the new card (Switch, Row, Arrangement.SpaceBetween, Alignment.CenterVertically, etc.) are already imported and used by the existing chroot/shared_tmp cards in the same file
  • Brace/paren balance checked against upstream baseline: deltas exactly match the added blocks, fully balanced
  • Both strings.xml files parse as valid XML; the 4 new resources exist in both locales
  • Found and fixed one real bug in review: an unescaped apostrophe (proot's) in the English note string would have failed aapt2 — reworded in commit 611feee

Keeping this as a draft anyway since a human compile run is still the real gate — will mark it ready once that happens (or feel free to flip it / squash-merge with review fixes). Also happy to attempt a full Gradle build on a PC side if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant