Search code examples
javaandroidandroid-studio

Permission denied when executing binary files on android targetSdkVersion>28


i have an application that creates a ssh connection tunnel for traffic forwarding. but it's working perfectly on targetSdkVersion 28 and below. but on atargetSdkVersion>28 when running(executing) the following commands(when running binary files), it raise error 126 OR Permission denied.

i don't know what exactly has changed in api version 29( permissions or /data/data/ or whatever). the error is unclear.

    protected static String BASE = "/data/data/com.staf621.ki4a/ki4a";
    protected static String BASE_BIN = "/bin";
    ssh_return_val = Util.runChainFireCommand(
                            ((key_switch && !enc_ssh_key) ? "" : BASE + BASE_BIN + "/sshpass -p \"" + password_text + "\" ")
                                    + BASE + BASE_BIN + "/ssh " + server_text + " -p " + port_number + " -l " + user_text
                                    + " -NT -g -D " + Util.localSocksPort + (dns_switch?" -L 127.0.0.1:8163:"+dns_server+":53":"")
                                    + forward_string
                                    + (key_switch ? " -i \"" + BASE + "/id_rsa\"" : "")
                                    + (compress ? " -C" : "")
                                    + " -o \"ProxyCommand " + BASE + BASE_BIN + "/korkscrew"
                                    + (iptables_switch ? "" : " --ancillaryfile " + BASE + "/sshfd_file")
                                    + (proxy ? " --proxyhost " + proxy_host
                                    + " --proxyport " + proxy_port + " --desthost %h --destport %p"
                                    + " --headerfile " + BASE + "/header_file" + "\""
                                    : " --directconnection --desthost %h --destport %p\"")
                                    + " -o \"KeepAlive yes\" -o \"ServerAliveInterval 15\""
                                    + " -o \"StrictHostKeyChecking=no\" -o \"GlobalKnownHostsFile=/dev/null\"", false, true);
                }

Logcat:

[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/sshpass: Permission denied
[libsuperuser][O][SH-] 126
[libsuperuser][C][SH%] END
[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/busybox: Permission denied
[libsuperuser][C][SH+] /data/data/com.staf621.ki4a/ki4a/bin/busybox killall -9 korkscrew;/data/data/com.staf621.ki4a/ki4a/bin/busybox killall -9 ssh;/data/data/com.staf621.ki4a/ki4a/bin/busybox killall -9 tun2socks/data/data/com.staf621.ki4a/ki4a/bin/busybox killall pdnsd
[libsuperuser][C][SH%] END
[libsuperuser][C][SH%] START
[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/busybox: Permission denied
[libsuperuser][C][SH+] /data/data/com.staf621.ki4a/ki4a/bin/busybox killall pdnsd; echo $?
[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/busybox: Permission denied
[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/busybox: Permission denied
[libsuperuser][C][SH%] END
[libsuperuser][O][SH*] sh: <stdin>[1]: /data/data/com.staf621.ki4a/ki4a/bin/busybox: Permission denied
[libsuperuser][O][SH-] 126

I have attached an image of /data/data/packagename/ files and contents and permissions of the binary files. See image

on targetSdkVersion<=28, it works perfectly, but on targetSdkVersion>28 it catches error 126 and Permission denied when running binary files


Solution

  • targetSdkVersion 28 is the last one before Android 10. https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission is what changed after that:

    Execution of files from the writable app home directory is a W^X violation. Apps should load only the binary code that's embedded within an app's APK file.

    Untrusted apps that target Android 10 cannot invoke execve() directly on files within the app's home directory.

    In addition, apps that target Android 10 cannot in-memory modify executable code from files which have been opened with dlopen() and expect those changes to be written through to disk, because the library cannot have been mapped PROT_EXEC through a writable file descriptor. This includes any shared object (.so) files with text relocations.

    And that's exactly what you're trying to do. This is the exact same problem that Termux ran into that stopped them from being able to publish any updates to the Play Store; see https://github.com/termux/termux-packages/wiki/Termux-and-Android-10 and https://github.com/termux-play-store for more about that.