fix(root): exec-probe su, bypass Android 13+ SELinux stat denial#610
Conversation
There was a problem hiding this comment.
rainxchzed has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR replaces file-existence checks for root binary detection with active ChangesRoot Binary Detection Improvement
Sequence DiagramsequenceDiagram
participant RootServiceManager
participant locateSuBinary
participant probeSu
participant su as "su -c id"
RootServiceManager->>locateSuBinary: locate working su
locateSuBinary->>probeSu: probe each SU_PATH
probeSu->>su: execute with timeout
su-->>probeSu: stdout (uid=0 or non-zero)
probeSu-->>locateSuBinary: SuProbe(path, kind)
locateSuBinary-->>RootServiceManager: return first successful probe or null
RootServiceManager->>RootServiceManager: cache path, map to RootStatus
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@core/data/src/androidMain/kotlin/zed/rainxch/core/data/services/root/RootServiceManager.kt`:
- Around line 275-278: The loop currently returns the first non-null probe
result which can be NOT_ZERO (a non-root or dead su), causing a bad path to be
cached; change the logic in the SU_PATHS loop to only return when probeSu(path)
indicates a successful root (e.g., the ZERO/success variant), and otherwise
continue probing other paths (skip/ignore NOT_ZERO results) so that
SuProbe(path, kind) is only returned for a confirmed working su; refer to
probeSu(...) and SuProbe(...) when making this change and ensure cachedSuPath
only gets set from a confirmed-success probe.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fd20b84b-15bc-4985-94a1-898d226d0a17
📒 Files selected for processing (14)
core/data/src/androidMain/kotlin/zed/rainxch/core/data/services/root/RootServiceManager.ktcore/presentation/src/commonMain/composeResources/files/whatsnew/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/ar/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/bn/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/es/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/fr/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/hi/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/it/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/ja/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/ko/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/pl/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/ru/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/tr/18.jsoncore/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/18.json
There was a problem hiding this comment.
rainxchzed has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@core/data/src/androidMain/kotlin/zed/rainxch/core/data/services/root/RootServiceManager.kt`:
- Line 304: The BufferedReader/InputStreamReader wrapping proc.inputStream in
RootServiceManager (the assignment to output) is never closed; change the read
to use Kotlin's use{} (or try/finally) to close the reader, e.g. wrap the reader
creation (InputStreamReader/BufferedReader) with .use { it.readText().trim() }
so proc.inputStream is closed promptly and avoids file descriptor leaks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cb30be69-56db-4214-8c32-3ec101b53b77
📒 Files selected for processing (1)
core/data/src/androidMain/kotlin/zed/rainxch/core/data/services/root/RootServiceManager.kt
There was a problem hiding this comment.
rainxchzed has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
Closes #608. Magisk alpha 30700 on Android 16 (and most Android 13+ devices) install su at `/data/adb/magisk/su`, where `untrusted_app` SELinux profile blocks `File.exists()` from reading. Root detection always returned NOT_AVAILABLE even though Magisk is present and would grant.
Replace stat-based locator with exec-based probe. Magisk / KernelSU / APatch hook the exec syscall regardless of whether the app can stat the path, so direct `Runtime.exec(path, "-c", "id")` works where `File.exists()` doesn't.
Skip IOException silently (binary not at path), keep WARN log for unexpected failures.
Test plan
Source: issue #608.
Summary by CodeRabbit
Bug Fixes
Documentation