aboutsummaryrefslogtreecommitdiffstats
path: root/exec
diff options
context:
space:
mode:
authorPo Lu2024-01-27 10:36:30 +0800
committerPo Lu2024-01-27 10:36:30 +0800
commitc37b50ad417c6cb340f54ffe218f5d889345451a (patch)
treefc6b825b4e3489621d0d7738eb739fa74e56d059 /exec
parent55f0b3e561034a1ad4235770d1c0685439a64fe5 (diff)
downloademacs-c37b50ad417c6cb340f54ffe218f5d889345451a.tar.gz
emacs-c37b50ad417c6cb340f54ffe218f5d889345451a.zip
Intercept calls to `openat' under Android
* exec/configure.ac (OPEN_SYSCALL, OPENAT_SYSCALL): Define new macros. * exec/exec.h (struct exec_tracee): New field `sp'. * exec/trace.c (handle_openat): New function. (process_system_call): If handle_openat executes successfully, save the unmodified stack pointer within the tracee structure to be restored once the system call completes.
Diffstat (limited to 'exec')
-rw-r--r--exec/configure.ac13
-rw-r--r--exec/exec.h4
-rw-r--r--exec/trace.c135
3 files changed, 150 insertions, 2 deletions
diff --git a/exec/configure.ac b/exec/configure.ac
index 9008c84f6a6..d70dbea3477 100644
--- a/exec/configure.ac
+++ b/exec/configure.ac
@@ -131,6 +131,8 @@ AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.])
131AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.]) 131AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
132AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.]) 132AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.])
133AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.]) 133AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.])
134AH_TEMPLATE([OPEN_SYSCALL], [Define to number of the `open' system call.])
135AH_TEMPLATE([OPENAT_SYSCALL], [Define to number of the `openat' system call.])
134AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.]) 136AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.])
135 137
136AC_CANONICAL_HOST 138AC_CANONICAL_HOST
@@ -257,6 +259,8 @@ AS_CASE([$host], [x86_64-*linux*],
257 AC_DEFINE([CLONE_SYSCALL], [__NR_clone]) 259 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
258 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink]) 260 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
259 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat]) 261 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
262 AC_DEFINE([OPEN_SYSCALL], [__NR_open])
263 AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
260 exec_CHECK_LINUX_CLONE3 264 exec_CHECK_LINUX_CLONE3
261 # Make sure the loader doesn't conflict with other position 265 # Make sure the loader doesn't conflict with other position
262 # dependent code. 266 # dependent code.
@@ -285,6 +289,8 @@ AS_CASE([$host], [x86_64-*linux*],
285 AC_DEFINE([CLONE_SYSCALL], [__NR_clone]) 289 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
286 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink]) 290 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
287 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat]) 291 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
292 AC_DEFINE([OPEN_SYSCALL], [__NR_open])
293 AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
288 exec_CHECK_LINUX_CLONE3 294 exec_CHECK_LINUX_CLONE3
289 # Make sure the loader doesn't conflict with other position 295 # Make sure the loader doesn't conflict with other position
290 # dependent code. 296 # dependent code.
@@ -312,8 +318,9 @@ AS_CASE([$host], [x86_64-*linux*],
312 AC_DEFINE([INTERPRETER_BASE], [0x3f00000000]) 318 AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
313 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1]) 319 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
314 AC_DEFINE([CLONE_SYSCALL], [__NR_clone]) 320 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
315 # Note that aarch64 has no `readlink'. 321 # Note that aarch64 has neither `readlink' nor `open'.
316 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat]) 322 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
323 AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
317 exec_CHECK_LINUX_CLONE3 324 exec_CHECK_LINUX_CLONE3
318 # Make sure the loader doesn't conflict with other position 325 # Make sure the loader doesn't conflict with other position
319 # dependent code. ARM places rather significant restrictions on 326 # dependent code. ARM places rather significant restrictions on
@@ -343,6 +350,8 @@ AS_CASE([$host], [x86_64-*linux*],
343 AC_DEFINE([CLONE_SYSCALL], [__NR_clone]) 350 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
344 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink]) 351 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
345 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat]) 352 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
353 AC_DEFINE([OPEN_SYSCALL], [__NR_open])
354 AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
346 exec_CHECK_LINUX_CLONE3 355 exec_CHECK_LINUX_CLONE3
347 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000" 356 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
348 exec_loader=loader-armeabi.s], 357 exec_loader=loader-armeabi.s],
@@ -365,6 +374,8 @@ AS_CASE([$host], [x86_64-*linux*],
365 AC_DEFINE([CLONE_SYSCALL], [__NR_clone]) 374 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
366 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink]) 375 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
367 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat]) 376 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
377 AC_DEFINE([OPEN_SYSCALL], [__NR_open])
378 AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
368 exec_CHECK_LINUX_CLONE3 379 exec_CHECK_LINUX_CLONE3
369 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000" 380 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
370 exec_loader=loader-armeabi.s], 381 exec_loader=loader-armeabi.s],
diff --git a/exec/exec.h b/exec/exec.h
index bed5edc9bab..ad1b50276c8 100644
--- a/exec/exec.h
+++ b/exec/exec.h
@@ -148,6 +148,10 @@ struct exec_tracee
148 /* The next process being traced. */ 148 /* The next process being traced. */
149 struct exec_tracee *next; 149 struct exec_tracee *next;
150 150
151 /* Address of any stack pointer to restore after system call
152 completion. */
153 USER_WORD sp;
154
151 /* The thread ID of this process. */ 155 /* The thread ID of this process. */
152 pid_t pid; 156 pid_t pid;
153 157
diff --git a/exec/trace.c b/exec/trace.c
index 8e190c94f79..a7cbda54d68 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -961,7 +961,7 @@ handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs,
961 return 0; 961 return 0;
962 962
963 /* Copy over tracee->exec_file. Truncate it to PATH_MAX, length, or 963 /* Copy over tracee->exec_file. Truncate it to PATH_MAX, length, or
964 size, whichever is less. */ 964 size, whichever is smaller. */
965 965
966 length = strlen (tracee->exec_file); 966 length = strlen (tracee->exec_file);
967 length = MIN (size, MIN (PATH_MAX, length)); 967 length = MIN (size, MIN (PATH_MAX, length));
@@ -979,6 +979,98 @@ handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs,
979#endif /* REENTRANT */ 979#endif /* REENTRANT */
980} 980}
981 981
982/* Handle an `open' or `openat' system call.
983
984 CALLNO is the system call number, and REGS are the current user
985 registers of the TRACEE.
986
987 If the file name specified in such system call is `/proc/self/exe',
988 replace the file name with the executable loaded into the process
989 issuing this system call.
990
991 Value is 0 upon success and 1 upon failure. */
992
993static int
994handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs,
995 struct exec_tracee *tracee, USER_WORD *result)
996{
997#ifdef REENTRANT
998 /* readlinkat cannot be handled specially when the library is built
999 to be reentrant, as the file name information cannot be
1000 recorded. */
1001 return 0;
1002#else /* !REENTRANT */
1003 char buffer[PATH_MAX + 1];
1004 USER_WORD address;
1005 size_t length;
1006 USER_REGS_STRUCT original;
1007
1008 /* Read the file name. */
1009
1010#ifdef OPEN_SYSCALL
1011 if (callno == OPEN_SYSCALL)
1012 address = regs->SYSCALL_ARG_REG;
1013 else
1014#endif /* OPEN_SYSCALL */
1015 address = regs->SYSCALL_ARG1_REG;
1016
1017 /* Read the file name into the buffer and verify that it is NULL
1018 terminated. */
1019 read_memory (tracee, buffer, PATH_MAX, address);
1020
1021 if (!memchr (buffer, '\0', PATH_MAX))
1022 {
1023 errno = ENAMETOOLONG;
1024 return 1;
1025 }
1026
1027 /* Now check if the caller is looking for /proc/self/exe.
1028
1029 dirfd can be ignored, as for now only absolute file names are
1030 handled. FIXME. */
1031
1032 if (strcmp (buffer, "/proc/self/exe") || !tracee->exec_file)
1033 return 0;
1034
1035 /* Copy over tracee->exec_file. This doesn't correctly handle the
1036 scenario where tracee->exec_file is longer than PATH_MAX, but
1037 that has yet to be encountered in practice. */
1038
1039 original = *regs;
1040 length = strlen (tracee->exec_file);
1041 address = user_alloca (tracee, &original, regs, length + 1);
1042
1043 if (!address
1044 || user_copy (tracee, (unsigned char *) tracee->exec_file,
1045 address, length))
1046 goto fail;
1047
1048 /* Replace the file name buffer with ADDRESS. */
1049
1050#ifdef OPEN_SYSCALL
1051 if (callno == OPEN_SYSCALL)
1052 regs->SYSCALL_ARG_REG = address;
1053 else
1054#endif /* OPEN_SYSCALL */
1055 regs->SYSCALL_ARG1_REG = address;
1056
1057#ifdef __aarch64__
1058 if (aarch64_set_regs (tracee->pid, regs, false))
1059 goto fail;
1060#else /* !__aarch64__ */
1061 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
1062 goto fail;
1063#endif /* __aarch64__ */
1064
1065 /* Resume the system call. */
1066 return 0;
1067
1068 fail:
1069 errno = EIO;
1070 return 1;
1071#endif /* REENTRANT */
1072}
1073
982/* Process the system call at which TRACEE is stopped. If the system 1074/* Process the system call at which TRACEE is stopped. If the system
983 call is not known or not exec, send TRACEE on its way. Otherwise, 1075 call is not known or not exec, send TRACEE on its way. Otherwise,
984 rewrite it to load the loader and perform an appropriate action. */ 1076 rewrite it to load the loader and perform an appropriate action. */
@@ -1056,9 +1148,50 @@ process_system_call (struct exec_tracee *tracee)
1056 goto emulate_syscall; 1148 goto emulate_syscall;
1057 } 1149 }
1058 1150
1151 goto continue_syscall;
1152
1153#ifdef OPEN_SYSCALL
1154 case OPEN_SYSCALL:
1155#endif /* OPEN_SYSCALL */
1156 case OPENAT_SYSCALL:
1157
1158 /* This system call is already in progress if
1159 TRACEE->waiting_for_syscall is true. */
1160
1161 if (!tracee->waiting_for_syscall)
1162 {
1163 /* Handle this open system call. */
1164 rc = handle_openat (callno, &regs, tracee, &result);
1165
1166 /* rc means the same as in `handle_exec', except that `open'
1167 is never emulated. */
1168
1169 if (rc == 1)
1170 goto report_syscall_error;
1171
1172 /* The stack pointer must be restored after it was modified
1173 by `user_alloca'; record sp in TRACEE, which will be
1174 restored after this system call completes. */
1175 tracee->sp = sp;
1176 }
1177 else
1178 {
1179 /* Restore that stack pointer. */
1180 regs.STACK_POINTER = tracee->sp;
1181
1182#ifdef __aarch64__
1183 if (aarch64_set_regs (tracee->pid, &regs, true))
1184 return;
1185#else /* !__aarch64__ */
1186 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs))
1187 return;
1188#endif /* __aarch64__ */
1189 }
1190
1059 /* Fallthrough. */ 1191 /* Fallthrough. */
1060 1192
1061 default: 1193 default:
1194 continue_syscall:
1062 /* Don't wait for the system call to finish; instead, the system 1195 /* Don't wait for the system call to finish; instead, the system
1063 will DTRT upon the next call to PTRACE_SYSCALL after the 1196 will DTRT upon the next call to PTRACE_SYSCALL after the
1064 syscall-trap signal is delivered. */ 1197 syscall-trap signal is delivered. */