Skip to content

Commit e7ea8c2

Browse files
committed
Q Preview 1 compatiblity
On several older Android versions we needed to relocate app_process to prevent it from being executed in a restricted SELinux context, but this causes the "Error finding namespace of apex: no namespace called runtime" linker error on Q Preview 1. Running app_process straight from /system/bin (and daemonizer from /data/.../lib) works fine however on QP1, so we just skip relocating altogher for now. Closes Chainfire#4
1 parent 7863f45 commit e7ea8c2

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

librootjava/src/main/java/eu/chainfire/librootjava/AppProcess.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,37 @@ public static boolean guessIfAppProcessIs64Bits(String app_process) {
283283
return !isRunningAs32BitOn64BitArch();
284284
}
285285

286+
/**
287+
* Should app_process be relocated ?<br>
288+
* <br>
289+
* On older Android versions we must relocate the app_process binary to prevent it from
290+
* running in a restricted SELinux context. On Q this presents us with the linker error:
291+
* "<i>Error finding namespace of apex: no namespace called runtime</i>". However, at least
292+
* on the first preview release of Q, running straight from /system/bin works and does
293+
* <i>not</i> give us a restricted SELinux context, so we skip relocation.
294+
*
295+
* TODO: Revisit on new Q preview and production releases. Maybe spend some time figuring out what causes the namespace error and if we can fix it.
296+
*
297+
* @see #getAppProcessRelocate(Context, String, List, List, String)
298+
*
299+
* @return should app_process be relocated ?
300+
*/
301+
@TargetApi(Build.VERSION_CODES.M)
302+
public static boolean shouldAppProcessBeRelocated() {
303+
return !(
304+
(Build.VERSION.SDK_INT >= 29) ||
305+
((Build.VERSION.SDK_INT == 28) && (Build.VERSION.PREVIEW_SDK_INT != 0))
306+
);
307+
}
308+
286309
/**
287310
* Create script to relocate specified app_process binary to a different location.<br>
288311
* <br>
289312
* On many Android versions and roots, executing app_process directly will force an
290313
* SELinux context that we do not want. Relocating it bypasses that.<br>
291314
*
292315
* @see #getAppProcess()
316+
* @see #shouldAppProcessBeRelocated()
293317
*
294318
* @param context Application or activity context
295319
* @param appProcessBase Path to original app_process or null for default
@@ -301,6 +325,10 @@ public static boolean guessIfAppProcessIs64Bits(String app_process) {
301325
public static String getAppProcessRelocate(Context context, String appProcessBase, List<String> preLaunch, List<String> postExecution, String path) {
302326
if (appProcessBase == null) appProcessBase = getAppProcess();
303327
if (path == null) {
328+
if (!shouldAppProcessBeRelocated()) {
329+
return appProcessBase;
330+
}
331+
304332
path = "/dev";
305333
if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
306334
File cacheDir = context.getCacheDir();

librootjavadaemon/src/main/java/eu/chainfire/librootjavadaemon/RootDaemon.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,27 @@ public static List<String> patchLaunchScript(Context context, List<String> scrip
7373
// patch the main script line
7474
String app_process_path = app_process.substring(0, app_process.lastIndexOf('/'));
7575

76-
// copy our executable
77-
String libSrc = RootJava.getLibraryPath(context, "daemonize");
78-
String libDest = app_process_path + "/.daemonize_" + AppProcess.UUID;
79-
boolean onData = libDest.startsWith("/data/");
76+
// our executable
77+
String libSource = RootJava.getLibraryPath(context, "daemonize");
78+
String libExec;
79+
80+
if (app_process_path.startsWith("/system/bin")) {
81+
// app_process was not relocated, assume caller knows what he's doing, and
82+
// run our executable from its library location
83+
libExec = libSource;
84+
} else {
85+
// copy our executable
86+
libExec = app_process_path + "/.daemonize_" + AppProcess.UUID;
87+
boolean onData = libExec.startsWith("/data/");
8088

81-
ret.add(String.format(Locale.ENGLISH, "%s cp %s %s >/dev/null 2>/dev/null", AppProcess.BOX, libSrc, libDest));
82-
ret.add(String.format(Locale.ENGLISH, "%s chmod %s %s >/dev/null 2>/dev/null", AppProcess.BOX, onData ? "0766" : "0700", libDest));
83-
if (onData) ret.add(String.format(Locale.ENGLISH, "restorecon %s >/dev/null 2>/dev/null", libDest));
89+
ret.add(String.format(Locale.ENGLISH, "%s cp %s %s >/dev/null 2>/dev/null", AppProcess.BOX, libSource, libExec));
90+
ret.add(String.format(Locale.ENGLISH, "%s chmod %s %s >/dev/null 2>/dev/null", AppProcess.BOX, onData ? "0766" : "0700", libExec));
91+
if (onData) ret.add(String.format(Locale.ENGLISH, "restorecon %s >/dev/null 2>/dev/null", libExec));
92+
}
8493

8594
// inject executable into command
8695
int idx = line.indexOf(app_process);
87-
ret.add(line.substring(0, idx) + libDest + " " + line.substring(idx));
96+
ret.add(line.substring(0, idx) + libExec + " " + line.substring(idx));
8897

8998
in_post = true;
9099
} else if (in_post && line.contains("box rm")) {

0 commit comments

Comments
 (0)