v2.2.4: Bundle proot as native library - bypasses SELinux execute restriction

This commit is contained in:
admin
2026-05-19 20:52:33 +04:00
Unverified
parent b921102768
commit ce0cf20eaf
16 changed files with 91 additions and 26 deletions

View File

@@ -7,8 +7,8 @@ android {
applicationId "ai.z.chat"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 16
versionName "2.2.3"
versionCode 17
versionName "2.2.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'

View File

@@ -49,20 +49,41 @@ public class ShellPlugin extends Plugin {
}
private String prootPath = null;
private String prootLoaderPath = null;
private void refreshShell() {
File proot = new File(prefixDir + "/bin/proot");
if (proot.exists()) {
try { Os.chmod(proot.getAbsolutePath(), 0755); } catch (Exception e) {}
prootPath = proot.getAbsolutePath();
} else {
String nativeLibDir = getNativeLibDir();
if (nativeLibDir != null) {
File nativeProot = new File(nativeLibDir, "libproot.so");
if (nativeProot.exists()) {
prootPath = nativeProot.getAbsolutePath();
String nativeLibDir = getNativeLibDir();
File prootInPrefix = new File(prefixDir + "/bin/proot");
if (!prootInPrefix.exists() && nativeLibDir != null) {
File bundledProot = new File(nativeLibDir, "libproot.so");
File bundledLoader = new File(nativeLibDir, "libproot-loader.so");
if (bundledProot.exists()) {
try {
new File(prefixDir + "/bin").mkdirs();
new File(prefixDir + "/libexec").mkdirs();
new File(prefixDir + "/libexec/proot").mkdirs();
copyFile(bundledProot, new File(prefixDir + "/bin/proot"));
Os.chmod(prefixDir + "/bin/proot", 0755);
if (bundledLoader.exists()) {
copyFile(bundledLoader, new File(prefixDir + "/libexec/proot/loader"));
Os.chmod(prefixDir + "/libexec/proot/loader", 0755);
File loader32 = new File(nativeLibDir, "libproot-loader32.so");
if (loader32.exists()) {
copyFile(loader32, new File(prefixDir + "/libexec/proot/loader32"));
Os.chmod(prefixDir + "/libexec/proot/loader32", 0755);
}
}
prootPath = prefixDir + "/bin/proot";
prootLoaderPath = prefixDir + "/libexec/proot/loader";
Log.i(TAG, "Installed bundled proot from APK: " + prootPath);
} catch (Exception e) {
Log.w(TAG, "Failed to install bundled proot: " + e.getMessage());
}
}
} else if (prootInPrefix.exists()) {
try { Os.chmod(prootInPrefix.getAbsolutePath(), 0755); } catch (Exception e) {}
prootPath = prootInPrefix.getAbsolutePath();
}
File bash = new File(prefixDir + "/bin/bash");
@@ -77,6 +98,16 @@ public class ShellPlugin extends Plugin {
shellPath = "/system/bin/sh";
}
private void copyFile(File src, File dst) throws Exception {
java.io.FileInputStream fis = new java.io.FileInputStream(src);
java.io.FileOutputStream fos = new java.io.FileOutputStream(dst);
byte[] buf = new byte[8192];
int r;
while ((r = fis.read(buf)) > 0) fos.write(buf, 0, r);
fos.close();
fis.close();
}
private String getNativeLibDir() {
try {
return getContext().getApplicationInfo().nativeLibraryDir;
@@ -106,6 +137,8 @@ public class ShellPlugin extends Plugin {
if (useProot && prootPath != null) {
actualCommand = prootPath + " -0 -b /dev -b /proc -b /sys -r " + prefixDir + " /bin/sh -c " + bashEscape(command);
} else if (prootPath != null && isTermuxCommand(command)) {
actualCommand = prootPath + " -0 -b /dev -b /proc -b /sys -r " + prefixDir + " /bin/sh -c " + bashEscape(command);
}
ProcessBuilder pb = new ProcessBuilder(shell, "-c", actualCommand);
@@ -141,6 +174,11 @@ public class ShellPlugin extends Plugin {
return "'" + s.replace("'", "'\\''") + "'";
}
private boolean isTermuxCommand(String cmd) {
if (prefixDir == null) return false;
return cmd.contains(prefixDir + "/bin/") || cmd.contains("pkg ") || cmd.contains("apt ") || cmd.contains("dpkg ");
}
@PluginMethod
public void kill(PluginCall call) {
String processId = call.getString("pid", "");
@@ -334,6 +372,9 @@ public class ShellPlugin extends Plugin {
if (hasOurPrefix) {
envList.add("LD_LIBRARY_PATH=" + prefixDir + "/lib");
envList.add("BOOTSTRAP=zaichat");
if (prootLoaderPath != null) {
envList.add("PROOT_LOADER=" + prootLoaderPath);
}
}
if (hasTermux) {
envList.add("TERMUX_VERSION=" + getTermuxVersion());

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.