aboutsummaryrefslogtreecommitdiffstats
path: root/exec
diff options
context:
space:
mode:
authorPo Lu2025-02-09 12:06:52 +0800
committerPo Lu2025-02-09 12:06:52 +0800
commit563efd6838c1b62c8962385911b5fd5c5637ab96 (patch)
treeec0a6294ad51fcdd9b916241959115aade90759a /exec
parented9dd4705c7299c12c18d566bd8db4183b1c57f3 (diff)
downloademacs-563efd6838c1b62c8962385911b5fd5c5637ab96.tar.gz
emacs-563efd6838c1b62c8962385911b5fd5c5637ab96.zip
Fix program execution on Android 15 QPR2 Beta
* exec/trace.c (process_vm_readv, process_vm_writev): New function pointers. Attempt to load them on recent Android systems when `exec' was not linked with a sufficiently up-to-date libc. (read_memory, user_copy): Always use process_vm_readv and process_vm_writev if available. (handle_openat): Write trailing NULL byte of filename to user buffer. (exec_init): Attempt to dlsym process_vm_readv and process_vm_writev.
Diffstat (limited to 'exec')
-rw-r--r--exec/trace.c58
1 files changed, 44 insertions, 14 deletions
diff --git a/exec/trace.c b/exec/trace.c
index 1b4297e08ab..ee163327313 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
@@ -70,6 +73,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
70/* Number of tracees children are allowed to create. */ 73/* Number of tracees children are allowed to create. */
71#define MAX_TRACEES 4096 74#define MAX_TRACEES 4096
72 75
76#if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM
77
78/* Load have_process_vm dynamically if possible to avoid PTRACE_PEEKDATA
79 restrictions on Android 15 QPR2+. */
80
81static ssize_t (*process_vm_readv) (pid_t, const struct iovec *,
82 unsigned long,
83 const struct iovec *,
84 unsigned long, unsigned long);
85static ssize_t (*process_vm_writev) (pid_t, const struct iovec *,
86 unsigned long,
87 const struct iovec *,
88 unsigned long, unsigned long);
89
90#endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */
91
73#ifdef __aarch64__ 92#ifdef __aarch64__
74 93
75/* Place PID's registers into *REGS. Return 1 upon failure, else 94/* Place PID's registers into *REGS. Return 1 upon failure, else
@@ -138,7 +157,7 @@ static struct exec_tracee *tracing_processes;
138 ADDRESS. Return its contents in BUFFER. 157 ADDRESS. Return its contents in BUFFER.
139 158
140 If there are unreadable pages within ADDRESS + N, the contents of 159 If there are unreadable pages within ADDRESS + N, the contents of
141 BUFFER after the first such page becomes undefined. */ 160 BUFFER after the first such page become undefined. */
142 161
143static void 162static void
144read_memory (struct exec_tracee *tracee, char *buffer, 163read_memory (struct exec_tracee *tracee, char *buffer,
@@ -146,7 +165,7 @@ read_memory (struct exec_tracee *tracee, char *buffer,
146{ 165{
147 USER_WORD word, n_words, n_bytes, i; 166 USER_WORD word, n_words, n_bytes, i;
148 long rc; 167 long rc;
149#ifdef HAVE_PROCESS_VM 168#ifdef HAVE_SYS_UIO_H
150 struct iovec iov, remote; 169 struct iovec iov, remote;
151 170
152 /* If `process_vm_readv' is available, use it instead. */ 171 /* If `process_vm_readv' is available, use it instead. */
@@ -160,11 +179,14 @@ read_memory (struct exec_tracee *tracee, char *buffer,
160 read, consider the read to have been a success. */ 179 read, consider the read to have been a success. */
161 180
162 if (n <= SSIZE_MAX 181 if (n <= SSIZE_MAX
163 && ((size_t) process_vm_readv (tracee->pid, &iov, 1, 182#ifndef HAVE_PROCESS_VM
164 &remote, 1, 0) != -1)) 183 && process_vm_readv
184#endif /* !HAVE_PROCESS_VM */
185 && (process_vm_readv (tracee->pid, &iov, 1,
186 &remote, 1, 0) != -1))
165 return; 187 return;
166 188
167#endif /* HAVE_PROCESS_VM */ 189#endif /* !HAVE_SYS_UIO_H */
168 190
169 /* First, read entire words from the tracee. */ 191 /* First, read entire words from the tracee. */
170 n_words = n & ~(sizeof (USER_WORD) - 1); 192 n_words = n & ~(sizeof (USER_WORD) - 1);
@@ -283,7 +305,7 @@ user_copy (struct exec_tracee *tracee, const unsigned char *buffer,
283{ 305{
284 USER_WORD start, end, word; 306 USER_WORD start, end, word;
285 unsigned char *bytes; 307 unsigned char *bytes;
286#ifdef HAVE_PROCESS_VM 308#ifdef HAVE_SYS_UIO_H
287 struct iovec iov, remote; 309 struct iovec iov, remote;
288 310
289 /* Try to use `process_vm_writev' if possible, but fall back to 311 /* Try to use `process_vm_writev' if possible, but fall back to
@@ -295,10 +317,13 @@ user_copy (struct exec_tracee *tracee, const unsigned char *buffer,
295 remote.iov_len = n; 317 remote.iov_len = n;
296 318
297 if (n <= SSIZE_MAX 319 if (n <= SSIZE_MAX
298 && ((size_t) process_vm_writev (tracee->pid, &iov, 1, 320#ifndef HAVE_PROCESS_VM
299 &remote, 1, 0) == n)) 321 && process_vm_writev
322#endif /* !HAVE_PROCESS_VM */
323 && (process_vm_writev (tracee->pid, &iov, 1,
324 &remote, 1, 0) == n))
300 return 0; 325 return 0;
301#endif /* HAVE_PROCESS_VM */ 326#endif /* HAVE_SYS_UIO_H */
302 327
303 /* Calculate the start and end positions for the write. */ 328 /* Calculate the start and end positions for the write. */
304 329
@@ -1149,10 +1174,7 @@ handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs,
1149 return 0; 1174 return 0;
1150 1175
1151 /* Now check if the caller is looking for /proc/self/exe or its 1176 /* Now check if the caller is looking for /proc/self/exe or its
1152 equivalent with the PID made explicit. 1177 equivalent with the PID made explicit. */
1153
1154 dirfd can be ignored, as for now only absolute file names are
1155 handled. FIXME. */
1156 1178
1157 p = stpcpy (proc_pid_exe, "/proc/"); 1179 p = stpcpy (proc_pid_exe, "/proc/");
1158 p = format_pid (p, tracee->pid); 1180 p = format_pid (p, tracee->pid);
@@ -1173,7 +1195,7 @@ handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs,
1173 1195
1174 if (!address 1196 if (!address
1175 || user_copy (tracee, (unsigned char *) tracee->exec_file, 1197 || user_copy (tracee, (unsigned char *) tracee->exec_file,
1176 address, length)) 1198 address, length + 1))
1177 goto fail; 1199 goto fail;
1178 1200
1179 /* Replace the file name buffer with ADDRESS. */ 1201 /* Replace the file name buffer with ADDRESS. */
@@ -1699,4 +1721,12 @@ void
1699exec_init (const char *loader) 1721exec_init (const char *loader)
1700{ 1722{
1701 loader_name = loader; 1723 loader_name = loader;
1724#if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM
1725 {
1726 *(void **) (&process_vm_readv)
1727 = dlsym (RTLD_DEFAULT, "process_vm_readv");
1728 *(void **) (&process_vm_writev)
1729 = dlsym (RTLD_DEFAULT, "process_vm_writev");
1730 }
1731#endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */
1702} 1732}