aboutsummaryrefslogtreecommitdiffstats
path: root/exec/trace.c
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/trace.c
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/trace.c')
-rw-r--r--exec/trace.c135
1 files changed, 134 insertions, 1 deletions
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. */