mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-25 07:28:20 +00:00
Work around system restrictions regarding exec
* doc/emacs/android.texi (Android Environment): Document `android-use-exec-loader'. * exec/exec1.c (main): Set program group of child process. * src/android.c (android_rewrite_spawn_argv): New function. * src/android.h: Update prototypes. * src/androidfns.c (syms_of_androidfns): New variable `android_use_exec_loader'. * src/callproc.c (emacs_spawn): Rewrite the argument vector to use exec1 if necessary.
This commit is contained in:
parent
9a7c645dd4
commit
5550816f59
@ -252,10 +252,7 @@ Emacs, the system has an overwhelming number of users.
|
||||
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
|
||||
@ -277,6 +274,17 @@ However, the approach it takes was devised by reading Android source
|
||||
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
|
||||
|
@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include <config.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "exec.h"
|
||||
@ -41,10 +42,15 @@ main (int argc, char **argv)
|
||||
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. */
|
||||
|
@ -6514,6 +6514,89 @@ android_free_cursor (android_cursor cursor)
|
||||
android_destroy_handle (cursor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else /* ANDROID_STUBIFY */
|
||||
|
||||
/* X emulation functions for Android. */
|
||||
|
@ -190,6 +190,11 @@ extern void android_write_event (union android_event *);
|
||||
|
||||
extern unsigned int event_serial;
|
||||
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -3112,6 +3112,20 @@ Note that if you set this, you will no longer be able to quit Emacs
|
||||
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);
|
||||
|
@ -92,6 +92,10 @@ extern char **environ;
|
||||
#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;
|
||||
|
||||
@ -1437,6 +1441,18 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user