Track main while pinning the initial release commit. Ship the matching upstream installer and Linux namespace sandbox backport, and launch the native user build prepared by Omarchy. Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>
80 lines
3.2 KiB
Diff
80 lines
3.2 KiB
Diff
--- a/hermes_cli/main.py
|
|
+++ b/hermes_cli/main.py
|
|
@@ -8146,6 +8146,44 @@
|
|
return False
|
|
|
|
|
|
+def _desktop_linux_userns_sandbox_available() -> bool:
|
|
+ """True when the unprivileged userns sandbox works (probed with ``unshare``, fails closed) — then
|
|
+ the setuid ``chrome-sandbox`` helper is never consulted and no sudo prompt is needed."""
|
|
+ if sys.platform != "linux":
|
|
+ return False
|
|
+ unshare = shutil.which("unshare")
|
|
+ if not unshare:
|
|
+ return False
|
|
+ try:
|
|
+ return (
|
|
+ subprocess.run(
|
|
+ [unshare, "--user", "--map-root-user", "true"],
|
|
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=5, check=False,
|
|
+ ).returncode
|
|
+ == 0)
|
|
+ except (OSError, subprocess.TimeoutExpired):
|
|
+ return False
|
|
+
|
|
+def _sandbox_helper_lstat(packaged_executable: Path) -> tuple[Path, Optional[os.stat_result]]:
|
|
+ """``(chrome-sandbox path, lstat or None)`` — lstat so a symlink is inspected, not followed."""
|
|
+ sandbox = packaged_executable.parent / "chrome-sandbox"
|
|
+ try:
|
|
+ return sandbox, sandbox.lstat()
|
|
+ except OSError:
|
|
+ return sandbox, None
|
|
+
|
|
+def _sandbox_helper_is_setuid_root(st: os.stat_result) -> bool:
|
|
+ return st.st_uid == 0 and stat.S_IMODE(st.st_mode) == 0o4755
|
|
+
|
|
+def _desktop_linux_needs_disable_setuid_sandbox(packaged_executable: Path) -> bool:
|
|
+ """True when a present, non-setuid ``chrome-sandbox`` would make Chromium abort with
|
|
+ ``setuid_sandbox_host`` despite a working userns sandbox (call after the fixup's userns path)."""
|
|
+ if sys.platform != "linux":
|
|
+ return False
|
|
+ _sandbox, st = _sandbox_helper_lstat(packaged_executable)
|
|
+ return st is not None and stat.S_ISREG(st.st_mode) and not _sandbox_helper_is_setuid_root(st)
|
|
+
|
|
+
|
|
def _desktop_linux_sandbox_helper_is_regular_file(packaged_executable: Path) -> bool:
|
|
"""Return True when ``chrome-sandbox`` exists as a regular file."""
|
|
if sys.platform != "linux":
|
|
@@ -8182,6 +8220,10 @@
|
|
return False
|
|
|
|
if sandbox_lstat.st_uid == 0 and stat.S_IMODE(sandbox_lstat.st_mode) == 0o4755:
|
|
+ return True
|
|
+
|
|
+ if _desktop_linux_userns_sandbox_available():
|
|
+ print("✓ Using Chromium's user-namespace sandbox (setuid helper not needed).")
|
|
return True
|
|
|
|
sudo = shutil.which("sudo")
|
|
@@ -8591,6 +8633,9 @@
|
|
launch_command.append("--no-sandbox")
|
|
else:
|
|
sys.exit(1)
|
|
+
|
|
+ elif _desktop_linux_needs_disable_setuid_sandbox(packaged_executable):
|
|
+ launch_command.append("--disable-setuid-sandbox")
|
|
|
|
launch_command.extend(config_electron_flags)
|
|
print(f"→ Launching packaged Hermes Desktop: {' '.join(launch_command)}")
|
|
--- a/scripts/desktop-update/posix.sh
|
|
+++ b/scripts/desktop-update/posix.sh
|
|
@@ -317,6 +317,8 @@
|
|
if [ ! -e "$sb" ]; then GATE=relaunch; return; fi
|
|
if [ -u "$sb" ] && [ "$(stat -c %u "$sb" 2>/dev/null)" = "0" ]; then GATE=relaunch; return; fi
|
|
|
|
+ if unshare --user --map-root-user true 2>/dev/null; then GATE=relaunch; return; fi
|
|
+
|
|
case "${ELECTRON_DISABLE_SANDBOX:-}" in 1|true|TRUE|True) GATE=relaunch; return ;; esac
|
|
[ "$SANDBOX_FALLBACK" -eq 1 ] && { GATE=relaunch; return; }
|
|
for arg in ${RELAUNCH_ARGS[@]+"${RELAUNCH_ARGS[@]}"}; do
|