You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In particular, sc_su() is documented as substituting the user of the current thread, and sc_su_task() as substituting the user of a specified TID. The comments also say that if the SELinux context is invalid or illegal, all SELinux permission checks will bypass via hook.
I think this is the wrong abstraction to expose to app developers.
A rooted thread inside a normal app process is not a meaningful security boundary. The process still shares address space, heap, global state, file descriptors, native libraries, Binder callbacks, signal state, runtime state, and third-party SDKs. Most apps contain and run far more code than the developer can fully audit. Even if only one kernel task has root credentials, the rest of the process can still influence that privileged task through shared memory, callbacks, races, object corruption, confused-deputy paths, or ordinary application bugs.
This design removes exactly the boundary that makes traditional root APIs somewhat containable: a separate privileged process with an explicit IPC/RPC interface.
The “no libsu and no IPC” framing treats IPC as overhead. But from a security perspective, IPC is a feature. It is the line where the developer can validate requests, narrow the command surface, separate privileged code from UI/app code, and avoid putting root into an arbitrary APK runtime.
I do not think this should be recommended, normalized, or kept as a general developer-facing API. Warnings are not enough, because the existence and convenience of the API will push developers toward using it.
My recommendation:
Remove sc_su() and sc_su_task() from syscall.
Do not encourage rooting app threads in-place.
Keep any equivalent mechanism private/internal if APatch itself truly needs it.
Recommend a separate root process/service model instead.
Encourage narrow Binder/socket/RPC interfaces over in-process privileged execution.
Treat SELinux bypass as a last-resort internal implementation detail, not a normal application development path.
This does not mean root developer ergonomics have to be bad. The safer direction is to make out-of-process root services easier to write, not to erase the process boundary.
This library makes it easy to write rooted idiomatic Kotlin while still using a separate root process and Binder-based IPC. It supports coroutines, Parcelize, Flow APIs, cancellation-aware behavior, persistent root sessions that can close on inactivity, and a narrower one-client-to-one-server model. Good developer ergonomics do not require rooting an app thread in-place.
In-process SuperCall is attractive because it is convenient. That is exactly why I think it is dangerous. It makes the unsafe path the easy path.
APatch should steer app developers toward explicit privilege separation, not provide a primitive that turns an arbitrary app thread into root and potentially bypasses SELinux checks inside the app’s existing context.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
I think SuperCall, at least in its current public app-facing form, should be removed.
My concern is that the API encourages a fundamentally unsafe application architecture: rooting an existing thread inside a normal Android app process.
The FAQ describes one of APatch’s differences as optionally not modifying SELinux, allowing an app thread to be rooted without
libsuand IPC:https://apatch.dev/faq.html#how-is-selinux-processed
The header exposes this directly:
APatch/app/src/main/cpp/supercall.h
Lines 108 to 122 in 4c113e9
In particular,
sc_su()is documented as substituting the user of the current thread, andsc_su_task()as substituting the user of a specified TID. The comments also say that if the SELinux context is invalid or illegal, all SELinux permission checks will bypass via hook.I think this is the wrong abstraction to expose to app developers.
A rooted thread inside a normal app process is not a meaningful security boundary. The process still shares address space, heap, global state, file descriptors, native libraries, Binder callbacks, signal state, runtime state, and third-party SDKs. Most apps contain and run far more code than the developer can fully audit. Even if only one kernel task has root credentials, the rest of the process can still influence that privileged task through shared memory, callbacks, races, object corruption, confused-deputy paths, or ordinary application bugs.
This design removes exactly the boundary that makes traditional root APIs somewhat containable: a separate privileged process with an explicit IPC/RPC interface.
The “no libsu and no IPC” framing treats IPC as overhead. But from a security perspective, IPC is a feature. It is the line where the developer can validate requests, narrow the command surface, separate privileged code from UI/app code, and avoid putting root into an arbitrary APK runtime.
I do not think this should be recommended, normalized, or kept as a general developer-facing API. Warnings are not enough, because the existence and convenience of the API will push developers toward using it.
My recommendation:
sc_su()andsc_su_task()from syscall.This does not mean root developer ergonomics have to be bad. The safer direction is to make out-of-process root services easier to write, not to erase the process boundary.
For disclosure, I maintain
librootkotlinx: https://github.com/Mygod/librootkotlinxThis library makes it easy to write rooted idiomatic Kotlin while still using a separate root process and Binder-based IPC. It supports coroutines,
Parcelize,FlowAPIs, cancellation-aware behavior, persistent root sessions that can close on inactivity, and a narrower one-client-to-one-server model. Good developer ergonomics do not require rooting an app thread in-place.In-process SuperCall is attractive because it is convenient. That is exactly why I think it is dangerous. It makes the unsafe path the easy path.
APatch should steer app developers toward explicit privilege separation, not provide a primitive that turns an arbitrary app thread into root and potentially bypasses SELinux checks inside the app’s existing context.
Beta Was this translation helpful? Give feedback.
All reactions