diff options
| author | Po Lu | 2023-05-01 09:31:58 +0800 |
|---|---|---|
| committer | Po Lu | 2023-05-01 09:31:58 +0800 |
| commit | 5550816f5962943abd81fbf68901dad575f18c06 (patch) | |
| tree | 9fcb1305b7a3e80a349a9fba6f192d8b348cf7a5 /src | |
| parent | 9a7c645dd4ef38b72787e932d444a61ed4e04c63 (diff) | |
| download | emacs-5550816f5962943abd81fbf68901dad575f18c06.tar.gz emacs-5550816f5962943abd81fbf68901dad575f18c06.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 83 | ||||
| -rw-r--r-- | src/android.h | 5 | ||||
| -rw-r--r-- | src/androidfns.c | 14 | ||||
| -rw-r--r-- | src/callproc.c | 16 |
4 files changed, 118 insertions, 0 deletions
diff --git a/src/android.c b/src/android.c index 3798758ff16..ce8f277e120 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -6514,6 +6514,89 @@ android_free_cursor (android_cursor cursor) | |||
| 6514 | android_destroy_handle (cursor); | 6514 | android_destroy_handle (cursor); |
| 6515 | } | 6515 | } |
| 6516 | 6516 | ||
| 6517 | |||
| 6518 | |||
| 6519 | /* Process execution. | ||
| 6520 | |||
| 6521 | Newer Android systems use SELinux to restrict user programs from | ||
| 6522 | executing programs installed in the application data directory for | ||
| 6523 | security reasons. Emacs uses a `loader' binary installed in the | ||
| 6524 | application data directory to manually load executables and replace | ||
| 6525 | the `execve' system call. */ | ||
| 6526 | |||
| 6527 | enum | ||
| 6528 | { | ||
| 6529 | /* Maximum number of arguments available. */ | ||
| 6530 | MAXARGS = 1024, | ||
| 6531 | }; | ||
| 6532 | |||
| 6533 | /* Rewrite the command line given in *ARGV to utilize the `exec1' | ||
| 6534 | bootstrap binary if necessary. | ||
| 6535 | |||
| 6536 | Value is 0 upon success, else 1. Set errno upon failure. | ||
| 6537 | |||
| 6538 | ARGV holds a pointer to a NULL-terminated array of arguments given | ||
| 6539 | to `emacs_spawn'. */ | ||
| 6540 | |||
| 6541 | int | ||
| 6542 | android_rewrite_spawn_argv (const char ***argv) | ||
| 6543 | { | ||
| 6544 | static const char *new_args[MAXARGS]; | ||
| 6545 | static char exec1_name[PATH_MAX], loader_name[PATH_MAX]; | ||
| 6546 | size_t i, nargs; | ||
| 6547 | |||
| 6548 | /* This isn't required on Android 9 or earlier. */ | ||
| 6549 | |||
| 6550 | if (android_api_level < 29 || !android_use_exec_loader) | ||
| 6551 | return 0; | ||
| 6552 | |||
| 6553 | /* Get argv[0]; this should never be NULL. | ||
| 6554 | Then, verify that it exists and is executable. */ | ||
| 6555 | |||
| 6556 | eassert (**argv); | ||
| 6557 | if (access (**argv, R_OK | X_OK)) | ||
| 6558 | return 1; | ||
| 6559 | |||
| 6560 | /* Count the number of arguments in *argv. */ | ||
| 6561 | |||
| 6562 | nargs = 0; | ||
| 6563 | while ((*argv)[nargs]) | ||
| 6564 | ++nargs; | ||
| 6565 | |||
| 6566 | /* nargs now holds the number of arguments in argv. If it's larger | ||
| 6567 | than MAXARGS, return failure. */ | ||
| 6568 | |||
| 6569 | if (nargs + 2 > MAXARGS) | ||
| 6570 | { | ||
| 6571 | errno = E2BIG; | ||
| 6572 | return 1; | ||
| 6573 | } | ||
| 6574 | |||
| 6575 | /* Fill in the name of `libexec1.so'. */ | ||
| 6576 | snprintf (exec1_name, PATH_MAX, "%s/libexec1.so", | ||
| 6577 | android_lib_dir); | ||
| 6578 | |||
| 6579 | /* And libloader.so. */ | ||
| 6580 | snprintf (loader_name, PATH_MAX, "%s/libloader.so", | ||
| 6581 | android_lib_dir); | ||
| 6582 | |||
| 6583 | /* Now fill in the first two arguments. */ | ||
| 6584 | new_args[0] = exec1_name; | ||
| 6585 | new_args[1] = loader_name; | ||
| 6586 | |||
| 6587 | /* And insert the rest. */ | ||
| 6588 | for (i = 0; i < nargs; ++i) | ||
| 6589 | new_args[i + 2] = (*argv)[i]; | ||
| 6590 | |||
| 6591 | /* Replace argv. */ | ||
| 6592 | *argv = new_args; | ||
| 6593 | |||
| 6594 | /* Return success. */ | ||
| 6595 | return 0; | ||
| 6596 | } | ||
| 6597 | |||
| 6598 | |||
| 6599 | |||
| 6517 | #else /* ANDROID_STUBIFY */ | 6600 | #else /* ANDROID_STUBIFY */ |
| 6518 | 6601 | ||
| 6519 | /* X emulation functions for Android. */ | 6602 | /* X emulation functions for Android. */ |
diff --git a/src/android.h b/src/android.h index 24666aaf989..62d420d4cce 100644 --- a/src/android.h +++ b/src/android.h | |||
| @@ -190,6 +190,11 @@ extern void android_write_event (union android_event *); | |||
| 190 | 190 | ||
| 191 | extern unsigned int event_serial; | 191 | extern unsigned int event_serial; |
| 192 | 192 | ||
| 193 | |||
| 194 | |||
| 195 | /* Process related functions. */ | ||
| 196 | extern int android_rewrite_spawn_argv (const char ***); | ||
| 197 | |||
| 193 | #endif | 198 | #endif |
| 194 | 199 | ||
| 195 | /* JNI functions should not be built when Emacs is stubbed out for the | 200 | /* JNI functions should not be built when Emacs is stubbed out for the |
diff --git a/src/androidfns.c b/src/androidfns.c index 3367ebdf755..3bd34edd5b9 100644 --- a/src/androidfns.c +++ b/src/androidfns.c | |||
| @@ -3112,6 +3112,20 @@ Note that if you set this, you will no longer be able to quit Emacs | |||
| 3112 | using the volume down button. */); | 3112 | using the volume down button. */); |
| 3113 | android_pass_multimedia_buttons_to_system = false; | 3113 | android_pass_multimedia_buttons_to_system = false; |
| 3114 | 3114 | ||
| 3115 | DEFVAR_BOOL ("android-use-exec-loader", android_use_exec_loader, | ||
| 3116 | doc: /* Whether or not to bypass system restrictions on program execution. | ||
| 3117 | |||
| 3118 | Android 10 and later prevent programs from executing files installed | ||
| 3119 | in writable directories, such as the application data directory. | ||
| 3120 | |||
| 3121 | When non-nil, Emacs will bypass this restriction by running such | ||
| 3122 | executables under system call tracing, and replacing the `execve' | ||
| 3123 | system call with a version which ignores the system's security | ||
| 3124 | restrictions. | ||
| 3125 | |||
| 3126 | This option has no effect on Android 9 and earlier. */); | ||
| 3127 | android_use_exec_loader = true; | ||
| 3128 | |||
| 3115 | /* Functions defined. */ | 3129 | /* Functions defined. */ |
| 3116 | defsubr (&Sx_create_frame); | 3130 | defsubr (&Sx_create_frame); |
| 3117 | defsubr (&Sxw_color_defined_p); | 3131 | defsubr (&Sxw_color_defined_p); |
diff --git a/src/callproc.c b/src/callproc.c index a1811a3bb23..015b52bc9bc 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -92,6 +92,10 @@ extern char **environ; | |||
| 92 | #include "pgtkterm.h" | 92 | #include "pgtkterm.h" |
| 93 | #endif | 93 | #endif |
| 94 | 94 | ||
| 95 | #ifdef HAVE_ANDROID | ||
| 96 | #include "android.h" | ||
| 97 | #endif /* HAVE_ANDROID */ | ||
| 98 | |||
| 95 | /* Pattern used by call-process-region to make temp files. */ | 99 | /* Pattern used by call-process-region to make temp files. */ |
| 96 | static Lisp_Object Vtemp_file_name_pattern; | 100 | static Lisp_Object Vtemp_file_name_pattern; |
| 97 | 101 | ||
| @@ -1437,6 +1441,18 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err, | |||
| 1437 | const char *pty_name, bool pty_in, bool pty_out, | 1441 | const char *pty_name, bool pty_in, bool pty_out, |
| 1438 | const sigset_t *oldset) | 1442 | const sigset_t *oldset) |
| 1439 | { | 1443 | { |
| 1444 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 1445 | /* Android 10 and later don't allow directly executing programs | ||
| 1446 | installed in the application data directory. Emacs provides a | ||
| 1447 | loader binary which replaces the `execve' system call for it and | ||
| 1448 | all its children. On these systems, rewrite the command line to | ||
| 1449 | call that loader binary instead. */ | ||
| 1450 | |||
| 1451 | if (android_rewrite_spawn_argv ((const char ***) &argv)) | ||
| 1452 | return 1; | ||
| 1453 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 1454 | |||
| 1455 | |||
| 1440 | #if USABLE_POSIX_SPAWN | 1456 | #if USABLE_POSIX_SPAWN |
| 1441 | /* Prefer the simpler `posix_spawn' if available. `posix_spawn' | 1457 | /* Prefer the simpler `posix_spawn' if available. `posix_spawn' |
| 1442 | doesn't yet support setting up pseudoterminals, so we fall back | 1458 | doesn't yet support setting up pseudoterminals, so we fall back |