aboutsummaryrefslogtreecommitdiffstats
path: root/exec
diff options
context:
space:
mode:
authorPo Lu2023-05-04 09:12:26 +0800
committerPo Lu2023-05-04 09:12:26 +0800
commit339cdef28e6c78e71b310ade3ffd22333cbb0089 (patch)
tree913505b2a1091ca9e5ecf792f558876c859f5750 /exec
parent19210f8b771947ad10fdaaf27c4f2a177ece3631 (diff)
downloademacs-339cdef28e6c78e71b310ade3ffd22333cbb0089.tar.gz
emacs-339cdef28e6c78e71b310ade3ffd22333cbb0089.zip
Update Android port
* exec/trace.c (check_signal): New function. (handle_exec, process_system_call): Handle signal-delivery-stop while waiting synchronously for syscall completion.
Diffstat (limited to 'exec')
-rw-r--r--exec/trace.c118
1 files changed, 97 insertions, 21 deletions
diff --git a/exec/trace.c b/exec/trace.c
index 579a62f6c5e..f9dd4d419f4 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -451,6 +451,8 @@ handle_clone (pid_t pid)
451/* File name of the loader binary. */ 451/* File name of the loader binary. */
452static const char *loader_name; 452static const char *loader_name;
453 453
454
455
454/* Return whether or not the trap signal described by SIGNAL is 456/* Return whether or not the trap signal described by SIGNAL is
455 generated by a system call being attempted by a tracee. */ 457 generated by a system call being attempted by a tracee. */
456 458
@@ -463,6 +465,79 @@ syscall_trap_p (siginfo_t *signal)
463 || signal->si_code == (SIGTRAP | SI_KERNEL)); 465 || signal->si_code == (SIGTRAP | SI_KERNEL));
464} 466}
465 467
468/* Check if the wait status STATUS indicates a system call trap.
469 TRACEE is the process whose stop STATUS describes. If TRACEE exits
470 while this information is being determined, return -1; if STATUS
471 indicates some other kind of stop, return 1 after continuing
472 TRACEE. Value is 0 otherwise. */
473
474static int
475check_signal (struct exec_tracee *tracee, int status)
476{
477 siginfo_t siginfo;
478
479 switch ((status & 0xfff00) >> 8)
480 {
481 case SIGTRAP:
482 /* Now, use PTRACE_GETSIGINFO to determine whether or not the
483 signal was delivered in response to a system call. */
484
485 if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0, &siginfo))
486 return -1;
487
488 if (!syscall_trap_p (&siginfo))
489 {
490 if (siginfo.si_code < 0)
491 /* SIGTRAP delivered from userspace. Pass it on. */
492 ptrace (PTRACE_SYSCALL, tracee->pid, 0, SIGTRAP);
493 else
494 ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0);
495
496 return 1;
497 }
498
499 case SIGTRAP | 0x80: /* SIGTRAP | 0x80 specifically refers to
500 system call traps. */
501 break;
502
503#ifdef SIGSYS
504 case SIGSYS:
505 if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0, &siginfo))
506 return -1;
507
508 /* Continue the process until the next syscall, but don't
509 pass through the signal if an emulated syscall led to
510 it. */
511#ifdef HAVE_SIGINFO_T_SI_SYSCALL
512#ifndef __arm__
513 ptrace (PTRACE_SYSCALL, tracee->pid,
514 0, ((siginfo.si_code == SYS_SECCOMP
515 && siginfo.si_syscall == -1)
516 ? 0 : status));
517#else /* __arm__ */
518 ptrace (PTRACE_SYSCALL, tracee->pid,
519 0, ((siginfo.si_code == SYS_SECCOMP
520 && siginfo.si_syscall == 222)
521 ? 0 : status));
522#endif /* !__arm__ */
523#else /* !HAVE_SIGINFO_T_SI_SYSCALL */
524 /* Drop this signal, since what caused it is unknown. */
525 ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0);
526#endif /* HAVE_SIGINFO_T_SI_SYSCALL */
527 return 1;
528#endif /* SIGSYS */
529
530 default:
531 /* Continue the process until the next syscall. */
532 ptrace (PTRACE_SYSCALL, tracee->pid, 0, status);
533 return 1;
534 }
535
536 return 0;
537}
538
539
540
466/* Handle an `exec' system call from the given TRACEE. REGS are the 541/* Handle an `exec' system call from the given TRACEE. REGS are the
467 tracee's current user-mode registers. 542 tracee's current user-mode registers.
468 543
@@ -591,6 +666,15 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
591 return 2; 666 return 2;
592 else 667 else
593 { 668 {
669 /* Then, check if STATUS is not a syscall-stop, and try again if
670 it isn't. */
671 rc = check_signal (tracee, wstatus);
672
673 if (rc == -1)
674 return 2;
675 else if (rc)
676 goto again;
677
594 /* Retrieve the signal information and determine whether or not 678 /* Retrieve the signal information and determine whether or not
595 the system call has completed. */ 679 the system call has completed. */
596 680
@@ -777,9 +861,6 @@ process_system_call (struct exec_tracee *tracee)
777 USER_REGS_STRUCT regs; 861 USER_REGS_STRUCT regs;
778 int rc, wstatus, save_errno; 862 int rc, wstatus, save_errno;
779 USER_WORD callno, sp; 863 USER_WORD callno, sp;
780#ifdef __aarch64__
781 USER_WORD old_w1, old_w2;
782#endif /* __aarch64__ */
783 USER_WORD result; 864 USER_WORD result;
784 bool reporting_error; 865 bool reporting_error;
785 866
@@ -876,19 +957,7 @@ process_system_call (struct exec_tracee *tracee)
876 /* First, save errno; system calls below will clobber it. */ 957 /* First, save errno; system calls below will clobber it. */
877 save_errno = errno; 958 save_errno = errno;
878 959
879#ifndef __aarch64__
880 regs.SYSCALL_NUM_REG = -1; 960 regs.SYSCALL_NUM_REG = -1;
881#else /* __aarch64__ */
882 /* ARM also requires the system call number to be valid. However, I
883 can't find any unused system call, so use fcntl instead, with
884 invalid arguments. */
885 regs.SYSCALL_NUM_REG = 72;
886 old_w1 = regs.regs[1];
887 old_w2 = regs.regs[2];
888 regs.regs[0] = -1;
889 regs.regs[1] = -1;
890 regs.regs[2] = -1;
891#endif /* !__aarch64__ */
892 regs.STACK_POINTER = sp; 961 regs.STACK_POINTER = sp;
893 962
894#ifdef __aarch64__ 963#ifdef __aarch64__
@@ -924,6 +993,19 @@ process_system_call (struct exec_tracee *tracee)
924 if (rc == -1) 993 if (rc == -1)
925 return; 994 return;
926 995
996 /* If the process received a signal, see if the signal is SIGSYS and
997 from seccomp. If so, discard it. */
998
999 if (WIFSTOPPED (wstatus))
1000 {
1001 rc = check_signal (tracee, wstatus);
1002
1003 if (rc == -1)
1004 return;
1005 else if (rc)
1006 goto again1;
1007 }
1008
927 if (!WIFSTOPPED (wstatus)) 1009 if (!WIFSTOPPED (wstatus))
928 /* The process has been killed in response to a signal. In this 1010 /* The process has been killed in response to a signal. In this
929 case, simply unlink the tracee and return. */ 1011 case, simply unlink the tracee and return. */
@@ -940,9 +1022,6 @@ process_system_call (struct exec_tracee *tracee)
940 1022
941 /* Report errno. */ 1023 /* Report errno. */
942#ifdef __aarch64__ 1024#ifdef __aarch64__
943 /* Restore x1 and x2. x0 is clobbered by errno. */
944 regs.regs[1] = old_w1;
945 regs.regs[2] = old_w2;
946 aarch64_set_regs (tracee->pid, &regs, false); 1025 aarch64_set_regs (tracee->pid, &regs, false);
947#else /* !__aarch64__ */ 1026#else /* !__aarch64__ */
948 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs); 1027 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs);
@@ -966,9 +1045,6 @@ process_system_call (struct exec_tracee *tracee)
966 1045
967 /* Report errno. */ 1046 /* Report errno. */
968#ifdef __aarch64__ 1047#ifdef __aarch64__
969 /* Restore x1 and x2. x0 is clobbered by errno. */
970 regs.regs[1] = old_w1;
971 regs.regs[2] = old_w2;
972 aarch64_set_regs (tracee->pid, &regs, false); 1048 aarch64_set_regs (tracee->pid, &regs, false);
973#else /* !__aarch64__ */ 1049#else /* !__aarch64__ */
974 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs); 1050 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs);