which is the app data directory (@pxref{Android File System}.)
Each application is also prohibited from accessing system
-directories, and the app data directories of other applications. In
-recent versions of Android, the system also prohibits, for security
-reasons, even Emacs itself from running executables inside the app
-data directory.
+directories, and the app data directories of other applications.
Emacs comes with several binaries. While being executable files,
they are packaged as libraries in the library directory, because
code, and is not sanctioned by the Android compatibility definition
documents, so your mileage may vary.
+@cindex call-process, Android
+@vindex android-use-exec-loader
+ Android 10 and later versions of the system also prohibit Emacs
+itself from running executables inside the app data directory. On
+these systems, Emacs normally applies a workaround; however, this
+workaround requires running all sub-processes in another subprocess,
+and applying process tracing to all executables, which may prove to be
+problematic for various different reasons. In that case, the
+workaround can be disabled by changing the variable
+@code{android-use-exec-loader} to @code{nil}.
+
@section Running Emacs in the background
@cindex emacs killed, android
@cindex emacs in the background, android
#include <config.h>
#include <unistd.h>
#include <stdlib.h>
+#include <stdio.h>
#include <sys/wait.h>
#include "exec.h"
extern char **environ;
int wstatus;
+ pid1 = getpid ();
pid = fork ();
if (!pid)
{
+ /* Set the process group used to the parent. */
+ if (setpgid (0, pid1))
+ perror ("setpgid");
+
tracing_execve (argv[2], argv + 2, environ);
/* An error occured. Exit with failure. */
android_destroy_handle (cursor);
}
+\f
+
+/* Process execution.
+
+ Newer Android systems use SELinux to restrict user programs from
+ executing programs installed in the application data directory for
+ security reasons. Emacs uses a `loader' binary installed in the
+ application data directory to manually load executables and replace
+ the `execve' system call. */
+
+enum
+ {
+ /* Maximum number of arguments available. */
+ MAXARGS = 1024,
+ };
+
+/* Rewrite the command line given in *ARGV to utilize the `exec1'
+ bootstrap binary if necessary.
+
+ Value is 0 upon success, else 1. Set errno upon failure.
+
+ ARGV holds a pointer to a NULL-terminated array of arguments given
+ to `emacs_spawn'. */
+
+int
+android_rewrite_spawn_argv (const char ***argv)
+{
+ static const char *new_args[MAXARGS];
+ static char exec1_name[PATH_MAX], loader_name[PATH_MAX];
+ size_t i, nargs;
+
+ /* This isn't required on Android 9 or earlier. */
+
+ if (android_api_level < 29 || !android_use_exec_loader)
+ return 0;
+
+ /* Get argv[0]; this should never be NULL.
+ Then, verify that it exists and is executable. */
+
+ eassert (**argv);
+ if (access (**argv, R_OK | X_OK))
+ return 1;
+
+ /* Count the number of arguments in *argv. */
+
+ nargs = 0;
+ while ((*argv)[nargs])
+ ++nargs;
+
+ /* nargs now holds the number of arguments in argv. If it's larger
+ than MAXARGS, return failure. */
+
+ if (nargs + 2 > MAXARGS)
+ {
+ errno = E2BIG;
+ return 1;
+ }
+
+ /* Fill in the name of `libexec1.so'. */
+ snprintf (exec1_name, PATH_MAX, "%s/libexec1.so",
+ android_lib_dir);
+
+ /* And libloader.so. */
+ snprintf (loader_name, PATH_MAX, "%s/libloader.so",
+ android_lib_dir);
+
+ /* Now fill in the first two arguments. */
+ new_args[0] = exec1_name;
+ new_args[1] = loader_name;
+
+ /* And insert the rest. */
+ for (i = 0; i < nargs; ++i)
+ new_args[i + 2] = (*argv)[i];
+
+ /* Replace argv. */
+ *argv = new_args;
+
+ /* Return success. */
+ return 0;
+}
+
+\f
+
#else /* ANDROID_STUBIFY */
/* X emulation functions for Android. */
extern unsigned int event_serial;
+\f
+
+/* Process related functions. */
+extern int android_rewrite_spawn_argv (const char ***);
+
#endif
/* JNI functions should not be built when Emacs is stubbed out for the
using the volume down button. */);
android_pass_multimedia_buttons_to_system = false;
+ DEFVAR_BOOL ("android-use-exec-loader", android_use_exec_loader,
+ doc: /* Whether or not to bypass system restrictions on program execution.
+
+Android 10 and later prevent programs from executing files installed
+in writable directories, such as the application data directory.
+
+When non-nil, Emacs will bypass this restriction by running such
+executables under system call tracing, and replacing the `execve'
+system call with a version which ignores the system's security
+restrictions.
+
+This option has no effect on Android 9 and earlier. */);
+ android_use_exec_loader = true;
+
/* Functions defined. */
defsubr (&Sx_create_frame);
defsubr (&Sxw_color_defined_p);
#include "pgtkterm.h"
#endif
+#ifdef HAVE_ANDROID
+#include "android.h"
+#endif /* HAVE_ANDROID */
+
/* Pattern used by call-process-region to make temp files. */
static Lisp_Object Vtemp_file_name_pattern;
const char *pty_name, bool pty_in, bool pty_out,
const sigset_t *oldset)
{
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+ /* Android 10 and later don't allow directly executing programs
+ installed in the application data directory. Emacs provides a
+ loader binary which replaces the `execve' system call for it and
+ all its children. On these systems, rewrite the command line to
+ call that loader binary instead. */
+
+ if (android_rewrite_spawn_argv ((const char ***) &argv))
+ return 1;
+#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
+
+
#if USABLE_POSIX_SPAWN
/* Prefer the simpler `posix_spawn' if available. `posix_spawn'
doesn't yet support setting up pseudoterminals, so we fall back