From 359b09e85990be481a9063b793e4c7a927057711 Mon Sep 17 00:00:00 2001 From: Twaik Yont Date: Tue, 22 Oct 2024 07:24:46 +0300 Subject: [PATCH] fix(dalvikvm): bypass W^X restriction https://github.com/termux/termux-packages/issues/18557 --- configure.ac | 1 + scripts/dalvikvm.in | 1 + src/Makefile.am | 10 ++++++++++ src/termux_access.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 src/termux_access.c diff --git a/configure.ac b/configure.ac index 233fe92..fff2243 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ AM_INIT_AUTOMAKE([foreign]) AC_PROG_MAKE_SET AC_PROG_CC AC_LANG(C) +LT_INIT copyright="Copyright (C) 2022-2024 Termux." if test "${TERMUX_APP_PACKAGE+set}" = set; then diff --git a/scripts/dalvikvm.in b/scripts/dalvikvm.in index d36df55..86f4928 100644 --- a/scripts/dalvikvm.in +++ b/scripts/dalvikvm.in @@ -11,4 +11,5 @@ else fi unset LD_LIBRARY_PATH LD_PRELOAD +export LD_PRELOAD=@TERMUX_PREFIX@/lib/termux/libtermux-access.so exec "$DALVIKVM" -Xusejit:true -Xnoimage-dex2oat -Djava.io.tmpdir=@TERMUX_PREFIX@/tmp "$@" diff --git a/src/Makefile.am b/src/Makefile.am index d2b3d76..d6d6ed6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,3 +21,13 @@ AM_CFLAGS = -Wall -Wextra -pedantic bin_PROGRAMS = cmd cmd_SOURCES = cmd.c + +libdir = $(prefix)/lib/termux + +lib_LTLIBRARIES = libtermux-access.la + +libtermux_access_la_SOURCES = termux_access.c +libtermux_access_la_LDFLAGS = -shared -module -avoid-version -ldl + +clean-local: + rm -f libtermux-access.la diff --git a/src/termux_access.c b/src/termux_access.c new file mode 100644 index 0000000..8c0befa --- /dev/null +++ b/src/termux_access.c @@ -0,0 +1,37 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +// This library is needed to bypass W^X restriction in Dalvik code. +// https://cs.android.com/android/platform/superproject/+/dd6fde63193fda968440fc0a4cd9ccee5d282ab0:art/runtime/native/dalvik_system_DexFile.cc;l=381 + +static int stub_access(const char* __unused path, int __unused mode) { + return -1; +} + +// Function pointer for the original access function +static int (*orig_access)(const char *path, int mode) = stub_access; + +// Constructor to load the original access function +__attribute__((constructor, visibility("hidden"))) +static void load_orig_access(void) { + orig_access = (int (*)(const char *, int))dlsym(RTLD_NEXT, "access"); + if (orig_access == NULL) { + dprintf(2, "Error in `dlsym`: %s\n", dlerror()); + orig_access = stub_access; + } +} + +int access(const char *path, int mode) { + // Checking if path ends with ".apk", if ".apk" is an extension and if mode is W_OK + const char *apk = path == NULL ? NULL : strstr(path, ".apk"); + if (mode == W_OK && apk != NULL && !strcmp(apk, ".apk")) + return 1; + + // Call the original access function for other cases + return orig_access(path, mode); +} +