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/v/eu.chainfire/librootjava.svg)](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/v/eu.chainfire/librootjava.svg)](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' }