diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..baee9c7
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,13 @@
+name: ci
+on: [push, pull_request]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 1.8
+ - uses: gradle/wrapper-validation-action@v1
+ - run: ./gradlew :librootjava:build
+
diff --git a/build.gradle b/build.gradle
index 9a78710..d168446 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,19 +1,19 @@
buildscript {
repositories {
google()
- jcenter()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
- classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
}
}
allprojects {
repositories {
google()
- jcenter()
+ maven { url 'https://jitpack.io' }
+ mavenCentral()
mavenLocal()
}
}
diff --git a/gradle.properties b/gradle.properties
index 1d3591c..9c36dce 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,18 +1,15 @@
-# Project-wide Gradle settings.
-
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-
-# For more details on how to configure your build environment visit
+## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
-
+#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
-
+#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
\ No newline at end of file
+# org.gradle.parallel=true
+#Sat Feb 05 12:08:52 CET 2022
+#android.enableJetifier=true
+android.useAndroidX=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 48effd2..44d10f7 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Nov 09 13:15:43 CET 2018
+#Sat Feb 05 12:08:34 CET 2022
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/jitpack.yml b/jitpack.yml
new file mode 100644
index 0000000..d1e6c1e
--- /dev/null
+++ b/jitpack.yml
@@ -0,0 +1,2 @@
+install:
+ - ./gradlew clean :librootjava:install :librootjavadaemon:install
diff --git a/librootjava/README.md b/librootjava/README.md
index dc817d3..b866116 100644
--- a/librootjava/README.md
+++ b/librootjava/README.md
@@ -1,5 +1,7 @@
# libRootJava
+[![ci][1]][2] [](https://jitpack.io/#eu.chainfire/librootjava)
+
Run Java (and Kotlin) code as root!
- Runs code directly from your APK
@@ -20,6 +22,18 @@ crediting me is appreciated.
If you modify the library itself when you use it in your projects,
you are kindly requested to share the sources of those modifications.
+## Deprecated
+
+This library is not under active development right now, as I've mostly
+moved away from the Android world. While I believe it still works great,
+if it breaks due to changes on new Android versions or root solutions,
+fixes may be slow to appear.
+
+If you're writing a new app, you might consider using
+[TopJohnWu's libsu](https://github.com/topjohnwu/libsu) instead. Barring
+some edge-cases (that I personally seem to be the biggest user of) the
+capabilities should be similar, but it's likely to be better maintained.
+
## Spaghetti Sauce Project
This library is part of the [Spaghetti Sauce Project](https://github.com/Chainfire/spaghetti_sauce_project).
@@ -430,12 +444,30 @@ an Android 10 preview comes out!
## Gradle
+Root `build.gradle`:
+
```
-implementation 'eu.chainfire:librootjava:1.2.0'
+allprojects {
+ repositories {
+ ...
+ maven { url 'https://jitpack.io' }
+ }
+}
+```
+
+Module `build.gradle`:
+
+```
+dependencies {
+ implementation 'eu.chainfire:librootjava:1.3.3'
+}
```
## Notes
This library includes its own Logger class that is used
throughout, which should probably have been refactored out.
-It wasn't.
\ No newline at end of file
+It wasn't.
+
+[1]: https://github.com/Chainfire/librootjava/workflows/ci/badge.svg
+[2]: https://github.com/Chainfire/librootjava/actions
diff --git a/librootjava/build.gradle b/librootjava/build.gradle
index ebd8b67..5ff11ec 100644
--- a/librootjava/build.gradle
+++ b/librootjava/build.gradle
@@ -1,10 +1,9 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
-apply plugin: 'com.jfrog.bintray'
android {
- compileSdkVersion 26
- buildToolsVersion '28.0.3'
+ compileSdkVersion 30
+ buildToolsVersion '30.0.3'
defaultConfig {
minSdkVersion 21 /* was 14 pre-Binder/AIDL */
targetSdkVersion 26
@@ -51,7 +50,7 @@ ext {
gitUrl = 'https://github.com/Chainfire/librootjava.git'
issueTrackerUrl = 'https://github.com/Chainfire/librootjava/issues'
- libraryVersion = '1.2.0'
+ libraryVersion = '1.3.3'
developerId = 'Chainfire'
developerName = 'Jorrit Jongma'
@@ -60,9 +59,6 @@ ext {
licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
-
- bintrayRepo = 'maven'
- bintrayName = artifact
}
task installMavenLocal(type: Upload) {
@@ -77,37 +73,9 @@ task installMavenLocal(type: Upload) {
}
}
-// Workaround bintray bug ignoring these from pom and bintray settings
version = libraryVersion
group = publishedGroupId
-bintray {
- Properties properties = new Properties()
- properties.load(project.rootProject.file('local.properties').newDataInputStream())
- user = properties.getProperty('bintray.user')
- key = properties.getProperty('bintray.apikey')
-
- configurations = ['archives']
- dryRun = false
- publish = true
- pkg {
- repo = bintrayRepo
- name = libraryName
- desc = libraryDescription
- websiteUrl = siteUrl
- issueTrackerUrl = issueTrackerUrl // doesn't actually work?
- vcsUrl = gitUrl
- //githubRepo = gitUrl // some more bintray weirdness here, breaks upload
- //githubReleaseNotesFile = 'README.md'
- licenses = allLicenses
- publicDownloadNumbers = true
- version {
- name = libraryVersion
- released = new Date()
- }
- }
-}
-
install {
repositories.mavenInstaller {
pom.project {
@@ -138,5 +106,3 @@ install {
}
}
}
-
-bintrayUpload.dependsOn install
diff --git a/librootjava/src/main/java/eu/chainfire/librootjava/AppProcess.java b/librootjava/src/main/java/eu/chainfire/librootjava/AppProcess.java
index 7649f54..4698b13 100644
--- a/librootjava/src/main/java/eu/chainfire/librootjava/AppProcess.java
+++ b/librootjava/src/main/java/eu/chainfire/librootjava/AppProcess.java
@@ -283,6 +283,29 @@ public static boolean guessIfAppProcessIs64Bits(String app_process) {
return !isRunningAs32BitOn64BitArch();
}
+ /**
+ * Should app_process be relocated ?
+ *
+ * On older Android versions we must relocate the app_process binary to prevent it from
+ * running in a restricted SELinux context. On Q this presents us with the linker error:
+ * "Error finding namespace of apex: no namespace called runtime". However, at least
+ * on the first preview release of Q, running straight from /system/bin works and does
+ * not give us a restricted SELinux context, so we skip relocation.
+ *
+ * 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.
+ *
+ * @see #getAppProcessRelocate(Context, String, List, List, String)
+ *
+ * @return should app_process be relocated ?
+ */
+ @TargetApi(Build.VERSION_CODES.M)
+ public static boolean shouldAppProcessBeRelocated() {
+ return !(
+ (Build.VERSION.SDK_INT >= 29) ||
+ ((Build.VERSION.SDK_INT == 28) && (Build.VERSION.PREVIEW_SDK_INT != 0))
+ );
+ }
+
/**
* Create script to relocate specified app_process binary to a different location.
*
@@ -290,6 +313,7 @@ public static boolean guessIfAppProcessIs64Bits(String app_process) {
* SELinux context that we do not want. Relocating it bypasses that.
*
* @see #getAppProcess()
+ * @see #shouldAppProcessBeRelocated()
*
* @param context Application or activity context
* @param appProcessBase Path to original app_process or null for default
@@ -301,6 +325,10 @@ public static boolean guessIfAppProcessIs64Bits(String app_process) {
public static String getAppProcessRelocate(Context context, String appProcessBase, List preLaunch, List postExecution, String path) {
if (appProcessBase == null) appProcessBase = getAppProcess();
if (path == null) {
+ if (!shouldAppProcessBeRelocated()) {
+ return appProcessBase;
+ }
+
path = "/dev";
if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
File cacheDir = context.getCacheDir();
diff --git a/librootjava/src/main/java/eu/chainfire/librootjava/Logger.java b/librootjava/src/main/java/eu/chainfire/librootjava/Logger.java
index 5ad1ee0..b2f81f9 100644
--- a/librootjava/src/main/java/eu/chainfire/librootjava/Logger.java
+++ b/librootjava/src/main/java/eu/chainfire/librootjava/Logger.java
@@ -23,7 +23,7 @@
@SuppressWarnings({"unused", "WeakerAccess"})
public class Logger {
private static String getDefaultLogTag(){
- String tag = BuildConfig.APPLICATION_ID;
+ String tag = BuildConfig.LIBRARY_PACKAGE_NAME;
int p;
while ((p = tag.indexOf('.')) >= 0) {
tag = tag.substring(p + 1);
diff --git a/librootjava_example/build.gradle b/librootjava_example/build.gradle
index d3e3078..fdf499e 100644
--- a/librootjava_example/build.gradle
+++ b/librootjava_example/build.gradle
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 26
- buildToolsVersion '28.0.3'
+ buildToolsVersion '30.0.3'
defaultConfig {
applicationId "eu.chainfire.librootjava_example"
@@ -27,7 +27,7 @@ dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
- implementation 'eu.chainfire:libsuperuser:1.0.0.+'
+ implementation 'eu.chainfire:libsuperuser:1.1.1'
// --- librootjava dependency ---
@@ -35,8 +35,8 @@ dependencies {
//implementation project(':librootjava')
/* Use local Maven repository version, installed by installMavenLocal Gradle task */
- //implementation('eu.chainfire:librootjava:1.2.0-SNAPSHOT') { changing = true }
+ //implementation('eu.chainfire:librootjava:1.3.3-SNAPSHOT') { changing = true }
- /* Use bintray/jcenter version */
- implementation 'eu.chainfire:librootjava:1.2.0'
+ /* Use jitpack version */
+ implementation 'eu.chainfire:librootjava:1.3.3'
}
diff --git a/librootjavadaemon/README.md b/librootjavadaemon/README.md
index a9f14f4..c2f5496 100644
--- a/librootjavadaemon/README.md
+++ b/librootjavadaemon/README.md
@@ -1,5 +1,7 @@
# libRootJavaDaemon
+[](https://jitpack.io/#eu.chainfire/librootjava)
+
Add-on for [libRootJava](../librootjava) to run the root process as a
daemon.
@@ -150,8 +152,23 @@ on the Android site.
## Gradle
+Root `build.gradle`:
+
+```
+allprojects {
+ repositories {
+ ...
+ maven { url 'https://jitpack.io' }
+ }
+}
+```
+
+Module `build.gradle`:
+
```
-implementation 'eu.chainfire:librootjavadaemon:1.2.0'
+dependencies {
+ implementation 'eu.chainfire.librootjava:librootjavadaemon:1.3.3'
+}
```
You should update to the latest libRootJava and libRootJavaDaemon at the
diff --git a/librootjavadaemon/build.gradle b/librootjavadaemon/build.gradle
index 3bdb6ae..5e9a168 100644
--- a/librootjavadaemon/build.gradle
+++ b/librootjavadaemon/build.gradle
@@ -1,10 +1,9 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
-apply plugin: 'com.jfrog.bintray'
android {
- compileSdkVersion 26
- buildToolsVersion '28.0.3'
+ compileSdkVersion 30
+ buildToolsVersion '30.0.3'
defaultConfig {
minSdkVersion 21
targetSdkVersion 26
@@ -27,10 +26,10 @@ dependencies {
//implementation project(':librootjava')
/* Use local Maven repository version, installed by installMavenLocal Gradle task */
- //implementation('eu.chainfire:librootjava:1.2.0-SNAPSHOT') { changing = true }
+ //implementation('eu.chainfire:librootjava:1.3.3-SNAPSHOT') { changing = true }
- /* Use bintray/jcenter version */
- implementation 'eu.chainfire:librootjava:1.2.0'
+ /* Use jitpack version */
+ implementation 'eu.chainfire.librootjava:librootjava:1.3.3'
}
task sourcesJar(type: Jar) {
@@ -64,7 +63,7 @@ ext {
gitUrl = 'https://github.com/Chainfire/librootjava.git'
issueTrackerUrl = 'https://github.com/Chainfire/librootjava/issues'
- libraryVersion = '1.2.0'
+ libraryVersion = '1.3.3'
developerId = 'Chainfire'
developerName = 'Jorrit Jongma'
@@ -73,9 +72,6 @@ ext {
licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
-
- bintrayRepo = 'maven'
- bintrayName = artifact
}
task installMavenLocal(type: Upload) {
@@ -90,37 +86,9 @@ task installMavenLocal(type: Upload) {
}
}
-// Workaround bintray bug ignoring these from pom and bintray settings
version = libraryVersion
group = publishedGroupId
-bintray {
- Properties properties = new Properties()
- properties.load(project.rootProject.file('local.properties').newDataInputStream())
- user = properties.getProperty('bintray.user')
- key = properties.getProperty('bintray.apikey')
-
- configurations = ['archives']
- dryRun = false
- publish = true
- pkg {
- repo = bintrayRepo
- name = libraryName
- desc = libraryDescription
- websiteUrl = siteUrl
- issueTrackerUrl = issueTrackerUrl // doesn't actually work?
- vcsUrl = gitUrl
- //githubRepo = gitUrl // some more bintray weirdness here, breaks upload
- //githubReleaseNotesFile = 'README.md'
- licenses = allLicenses
- publicDownloadNumbers = true
- version {
- name = libraryVersion
- released = new Date()
- }
- }
-}
-
install {
repositories.mavenInstaller {
pom.project {
@@ -151,5 +119,3 @@ install {
}
}
}
-
-bintrayUpload.dependsOn install
diff --git a/librootjavadaemon/src/main/java/eu/chainfire/librootjavadaemon/RootDaemon.java b/librootjavadaemon/src/main/java/eu/chainfire/librootjavadaemon/RootDaemon.java
index fb63aad..f122409 100644
--- a/librootjavadaemon/src/main/java/eu/chainfire/librootjavadaemon/RootDaemon.java
+++ b/librootjavadaemon/src/main/java/eu/chainfire/librootjavadaemon/RootDaemon.java
@@ -73,18 +73,27 @@ public static List patchLaunchScript(Context context, List scrip
// patch the main script line
String app_process_path = app_process.substring(0, app_process.lastIndexOf('/'));
- // copy our executable
- String libSrc = RootJava.getLibraryPath(context, "daemonize");
- String libDest = app_process_path + "/.daemonize_" + AppProcess.UUID;
- boolean onData = libDest.startsWith("/data/");
+ // our executable
+ String libSource = RootJava.getLibraryPath(context, "daemonize");
+ String libExec;
+
+ if (app_process_path.startsWith("/system/bin")) {
+ // app_process was not relocated, assume caller knows what he's doing, and
+ // run our executable from its library location
+ libExec = libSource;
+ } else {
+ // copy our executable
+ libExec = app_process_path + "/.daemonize_" + AppProcess.UUID;
+ boolean onData = libExec.startsWith("/data/");
- ret.add(String.format(Locale.ENGLISH, "%s cp %s %s >/dev/null 2>/dev/null", AppProcess.BOX, libSrc, libDest));
- ret.add(String.format(Locale.ENGLISH, "%s chmod %s %s >/dev/null 2>/dev/null", AppProcess.BOX, onData ? "0766" : "0700", libDest));
- if (onData) ret.add(String.format(Locale.ENGLISH, "restorecon %s >/dev/null 2>/dev/null", libDest));
+ ret.add(String.format(Locale.ENGLISH, "%s cp %s %s >/dev/null 2>/dev/null", AppProcess.BOX, libSource, libExec));
+ ret.add(String.format(Locale.ENGLISH, "%s chmod %s %s >/dev/null 2>/dev/null", AppProcess.BOX, onData ? "0766" : "0700", libExec));
+ if (onData) ret.add(String.format(Locale.ENGLISH, "restorecon %s >/dev/null 2>/dev/null", libExec));
+ }
// inject executable into command
int idx = line.indexOf(app_process);
- ret.add(line.substring(0, idx) + libDest + " " + line.substring(idx));
+ ret.add(line.substring(0, idx) + libExec + " " + line.substring(idx));
in_post = true;
} else if (in_post && line.contains("box rm")) {
@@ -175,7 +184,7 @@ public interface OnExitListener {
*/
@SuppressLint("PrivateApi")
public static void daemonize(String packageName, int code, boolean surviveFrameworkRestart, OnExitListener exitListener) {
- String id = packageName + "#" + String.valueOf(code) + "#daemonize";
+ String id = packageName + "_" + String.valueOf(code) + "_daemonize";
File apk = new File(System.getenv("CLASSPATH"));
final String version = String.format(Locale.ENGLISH, "%s:%d:%d", apk.getAbsolutePath(), apk.lastModified(), apk.length());
diff --git a/librootjavadaemon_example/build.gradle b/librootjavadaemon_example/build.gradle
index 0f22add..af9981a 100644
--- a/librootjavadaemon_example/build.gradle
+++ b/librootjavadaemon_example/build.gradle
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 26
- buildToolsVersion '28.0.3'
+ buildToolsVersion '30.0.3'
defaultConfig {
applicationId "eu.chainfire.librootjavadaemon_example"
@@ -27,7 +27,7 @@ dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
- implementation 'eu.chainfire:libsuperuser:1.0.0.+'
+ implementation 'eu.chainfire:libsuperuser:1.1.1'
// --- librootjava and librootjavadaemon dependencies ---
@@ -36,10 +36,10 @@ dependencies {
//implementation project(':librootjavadaemon')
/* Use local Maven repository version, installed by installMavenLocal Gradle task */
- //implementation('eu.chainfire:librootjava:1.2.0-SNAPSHOT') { changing = true }
- //implementation('eu.chainfire:librootjavadaemon:1.2.0-SNAPSHOT') { changing = true }
+ //implementation('eu.chainfire:librootjava:1.3.3-SNAPSHOT') { changing = true }
+ //implementation('eu.chainfire:librootjavadaemon:1.3.3-SNAPSHOT') { changing = true }
- /* Use bintray/jcenter version */
- implementation 'eu.chainfire:librootjava:1.2.0'
- implementation 'eu.chainfire:librootjavadaemon:1.2.0'
+ /* Use jitpack version */
+ implementation 'eu.chainfire:librootjava:1.3.3'
+ implementation 'eu.chainfire.librootjava:librootjavadaemon:1.3.3'
}