diff options
| author | Po Lu | 2025-02-09 12:08:27 +0800 |
|---|---|---|
| committer | Po Lu | 2025-02-09 12:08:27 +0800 |
| commit | d93342cf322fae0040b268dfaabfbc720ee12d98 (patch) | |
| tree | a688fc16820a80769c57d158506a528be9434369 /exec | |
| parent | 1294c5ed5fb9251c16c0b48293953e2a6ce06e96 (diff) | |
| parent | 563efd6838c1b62c8962385911b5fd5c5637ab96 (diff) | |
| download | emacs-d93342cf322fae0040b268dfaabfbc720ee12d98.tar.gz emacs-d93342cf322fae0040b268dfaabfbc720ee12d98.zip | |
Merge from savannah/emacs-30
563efd6838c Fix program execution on Android 15 QPR2 Beta
Diffstat (limited to 'exec')
| -rw-r--r-- | exec/trace.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/exec/trace.c b/exec/trace.c index e222f0fc21a..ff67ed5d941 100644 --- a/exec/trace.c +++ b/exec/trace.c | |||
| @@ -45,6 +45,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 45 | 45 | ||
| 46 | #ifdef HAVE_SYS_UIO_H | 46 | #ifdef HAVE_SYS_UIO_H |
| 47 | #include <sys/uio.h> /* for process_vm_readv */ | 47 | #include <sys/uio.h> /* for process_vm_readv */ |
| 48 | #ifndef HAVE_PROCESS_VM | ||
| 49 | #include <dlfcn.h> | ||
| 50 | #endif /* !HAVE_PROCESS_VM */ | ||
| 48 | #endif /* HAVE_SYS_UIO_H */ | 51 | #endif /* HAVE_SYS_UIO_H */ |
| 49 | 52 | ||
| 50 | #ifndef SYS_SECCOMP | 53 | #ifndef SYS_SECCOMP |
| @@ -80,6 +83,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 80 | /* Number of tracees children are allowed to create. */ | 83 | /* Number of tracees children are allowed to create. */ |
| 81 | #define MAX_TRACEES 4096 | 84 | #define MAX_TRACEES 4096 |
| 82 | 85 | ||
| 86 | #if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM | ||
| 87 | |||
| 88 | /* Load have_process_vm dynamically if possible to avoid PTRACE_PEEKDATA | ||
| 89 | restrictions on Android 15 QPR2+. */ | ||
| 90 | |||
| 91 | static ssize_t (*process_vm_readv) (pid_t, const struct iovec *, | ||
| 92 | unsigned long, | ||
| 93 | const struct iovec *, | ||
| 94 | unsigned long, unsigned long); | ||
| 95 | static ssize_t (*process_vm_writev) (pid_t, const struct iovec *, | ||
| 96 | unsigned long, | ||
| 97 | const struct iovec *, | ||
| 98 | unsigned long, unsigned long); | ||
| 99 | |||
| 100 | #endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */ | ||
| 101 | |||
| 83 | #ifdef HAVE_SECCOMP | 102 | #ifdef HAVE_SECCOMP |
| 84 | 103 | ||
| 85 | /* Whether to enable seccomp acceleration. */ | 104 | /* Whether to enable seccomp acceleration. */ |
| @@ -156,7 +175,7 @@ static struct exec_tracee *tracing_processes; | |||
| 156 | ADDRESS. Return its contents in BUFFER. | 175 | ADDRESS. Return its contents in BUFFER. |
| 157 | 176 | ||
| 158 | If there are unreadable pages within ADDRESS + N, the contents of | 177 | If there are unreadable pages within ADDRESS + N, the contents of |
| 159 | BUFFER after the first such page becomes undefined. */ | 178 | BUFFER after the first such page become undefined. */ |
| 160 | 179 | ||
| 161 | static void | 180 | static void |
| 162 | read_memory (struct exec_tracee *tracee, char *buffer, | 181 | read_memory (struct exec_tracee *tracee, char *buffer, |
| @@ -164,7 +183,7 @@ read_memory (struct exec_tracee *tracee, char *buffer, | |||
| 164 | { | 183 | { |
| 165 | USER_WORD word, n_words, n_bytes, i; | 184 | USER_WORD word, n_words, n_bytes, i; |
| 166 | long rc; | 185 | long rc; |
| 167 | #ifdef HAVE_PROCESS_VM | 186 | #ifdef HAVE_SYS_UIO_H |
| 168 | struct iovec iov, remote; | 187 | struct iovec iov, remote; |
| 169 | 188 | ||
| 170 | /* If `process_vm_readv' is available, use it instead. */ | 189 | /* If `process_vm_readv' is available, use it instead. */ |
| @@ -178,11 +197,14 @@ read_memory (struct exec_tracee *tracee, char *buffer, | |||
| 178 | read, consider the read to have been a success. */ | 197 | read, consider the read to have been a success. */ |
| 179 | 198 | ||
| 180 | if (n <= SSIZE_MAX | 199 | if (n <= SSIZE_MAX |
| 181 | && ((size_t) process_vm_readv (tracee->pid, &iov, 1, | 200 | #ifndef HAVE_PROCESS_VM |
| 182 | &remote, 1, 0) != -1)) | 201 | && process_vm_readv |
| 202 | #endif /* !HAVE_PROCESS_VM */ | ||
| 203 | && (process_vm_readv (tracee->pid, &iov, 1, | ||
| 204 | &remote, 1, 0) != -1)) | ||
| 183 | return; | 205 | return; |
| 184 | 206 | ||
| 185 | #endif /* HAVE_PROCESS_VM */ | 207 | #endif /* !HAVE_SYS_UIO_H */ |
| 186 | 208 | ||
| 187 | /* First, read entire words from the tracee. */ | 209 | /* First, read entire words from the tracee. */ |
| 188 | n_words = n & ~(sizeof (USER_WORD) - 1); | 210 | n_words = n & ~(sizeof (USER_WORD) - 1); |
| @@ -301,7 +323,7 @@ user_copy (struct exec_tracee *tracee, const unsigned char *buffer, | |||
| 301 | { | 323 | { |
| 302 | USER_WORD start, end, word; | 324 | USER_WORD start, end, word; |
| 303 | unsigned char *bytes; | 325 | unsigned char *bytes; |
| 304 | #ifdef HAVE_PROCESS_VM | 326 | #ifdef HAVE_SYS_UIO_H |
| 305 | struct iovec iov, remote; | 327 | struct iovec iov, remote; |
| 306 | 328 | ||
| 307 | /* Try to use `process_vm_writev' if possible, but fall back to | 329 | /* Try to use `process_vm_writev' if possible, but fall back to |
| @@ -313,10 +335,13 @@ user_copy (struct exec_tracee *tracee, const unsigned char *buffer, | |||
| 313 | remote.iov_len = n; | 335 | remote.iov_len = n; |
| 314 | 336 | ||
| 315 | if (n <= SSIZE_MAX | 337 | if (n <= SSIZE_MAX |
| 316 | && ((size_t) process_vm_writev (tracee->pid, &iov, 1, | 338 | #ifndef HAVE_PROCESS_VM |
| 317 | &remote, 1, 0) == n)) | 339 | && process_vm_writev |
| 340 | #endif /* !HAVE_PROCESS_VM */ | ||
| 341 | && (process_vm_writev (tracee->pid, &iov, 1, | ||
| 342 | &remote, 1, 0) == n)) | ||
| 318 | return 0; | 343 | return 0; |
| 319 | #endif /* HAVE_PROCESS_VM */ | 344 | #endif /* HAVE_SYS_UIO_H */ |
| 320 | 345 | ||
| 321 | /* Calculate the start and end positions for the write. */ | 346 | /* Calculate the start and end positions for the write. */ |
| 322 | 347 | ||
| @@ -1129,10 +1154,7 @@ handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs, | |||
| 1129 | return 0; | 1154 | return 0; |
| 1130 | 1155 | ||
| 1131 | /* Now check if the caller is looking for /proc/self/exe or its | 1156 | /* Now check if the caller is looking for /proc/self/exe or its |
| 1132 | equivalent with the PID made explicit. | 1157 | equivalent with the PID made explicit. */ |
| 1133 | |||
| 1134 | dirfd can be ignored, as for now only absolute file names are | ||
| 1135 | handled. FIXME. */ | ||
| 1136 | 1158 | ||
| 1137 | p = stpcpy (proc_pid_exe, "/proc/"); | 1159 | p = stpcpy (proc_pid_exe, "/proc/"); |
| 1138 | p = format_pid (p, tracee->pid); | 1160 | p = format_pid (p, tracee->pid); |
| @@ -1153,7 +1175,7 @@ handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs, | |||
| 1153 | 1175 | ||
| 1154 | if (!address | 1176 | if (!address |
| 1155 | || user_copy (tracee, (unsigned char *) tracee->exec_file, | 1177 | || user_copy (tracee, (unsigned char *) tracee->exec_file, |
| 1156 | address, length)) | 1178 | address, length + 1)) |
| 1157 | goto fail; | 1179 | goto fail; |
| 1158 | 1180 | ||
| 1159 | /* Replace the file name buffer with ADDRESS. */ | 1181 | /* Replace the file name buffer with ADDRESS. */ |
| @@ -2203,4 +2225,12 @@ exec_init (const char *loader) | |||
| 2203 | } | 2225 | } |
| 2204 | } | 2226 | } |
| 2205 | #endif /* HAVE_SECCOMP */ | 2227 | #endif /* HAVE_SECCOMP */ |
| 2228 | #if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM | ||
| 2229 | { | ||
| 2230 | *(void **) (&process_vm_readv) | ||
| 2231 | = dlsym (RTLD_DEFAULT, "process_vm_readv"); | ||
| 2232 | *(void **) (&process_vm_writev) | ||
| 2233 | = dlsym (RTLD_DEFAULT, "process_vm_writev"); | ||
| 2234 | } | ||
| 2235 | #endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */ | ||
| 2206 | } | 2236 | } |