Asynch signal arriving in ni-syscall-ending block results in premature and duplicated pre-syscall-handler execution
If a signal arrives in a block that ends in a non-ignorable syscall, we'll unlink it, and when back in dispatch we check for the syscall before the signal. We do the pre-syscall handling, then try to run the syscall: but enter_fcache sees signals_pending and bails. We then go run the signal handler, but we never undo the pre-syscall handling. Once the handler returns we'll go execute the syscall for real, duplicating the pre-syscall handling.
Depending on the syscall, this may not matter, but some syscalls are hard to undo and premature execution and/or duplication might result in issues.
Exit from F91(0x0000ffff807775e0).0x0000aaaa75281e70 (shared)
(interrupted by delayable signal)
Entry into do_syscall to execute a non-ignorable system call
system call 98
Signal arrived in DR: aborting syscall enter; interrupted 0x0000ffff80777600
receive_pending_signal
receiving signal 27
<run handler>
receive_pending_signal
clearing signals_pending flag
d_r_dispatch: target = 0x0000aaaad5b4ac74
Entry into F241(0x0000aaaad5b4ac74).0x0000aaaa755acee0 (shared)
Exit from F298(0x0000aaaabe514750).0x0000aaaa755b2258 (shared)
(block ends with syscall)
Entry into do_syscall to execute a non-ignorable system call
system call 139
rt_sigreturn()
set next tag to 0x0000ffff80777600, sc->SC_XIP to 0x0000aaaa75276c80
for sigreturn, set sys_param1 to 0x0000aaaad6b4cd40
Exit from asynch event
post-sigreturn: setting xax/r0 to 0x0000aaaad6b4cd40, asynch_target=0x0000ffff80777600
post syscall: sysnum=0x000000000000008b, result=0x0000aaaad6b4cd40 (-692794048)
finished handling system call
d_r_dispatch: target = 0x0000ffff80777600
Entry into F1(0x0000ffff80777600).0x0000aaaa7527a00c (shared)
Exit from F1(0x0000ffff80777600).0x0000aaaa7527a0f4 (shared)
(block ends with syscall)
Entry into do_syscall to execute a non-ignorable system call
system call 98
Exit from system call
post syscall: sysnum=0x0000000000000062, result=0xffffffffffffff92 (-110)
finished handling system call
Confirming it's targeting the syscall via tail-dup, here's F91:
interp: start_pc = 0x0000ffff807775e0
0x0000ffff807775e0 d3407c08 ubfm %x0 $0x00 $0x1f -> %x8
0x0000ffff807775e4 aa0103e0 orr %xzr %x1 lsl $0x00 -> %x0
0x0000ffff807775e8 aa0203e1 orr %xzr %x2 lsl $0x00 -> %x1
0x0000ffff807775ec aa0303e2 orr %xzr %x3 lsl $0x00 -> %x2
0x0000ffff807775f0 aa0403e3 orr %xzr %x4 lsl $0x00 -> %x3
0x0000ffff807775f4 aa0503e4 orr %xzr %x5 lsl $0x00 -> %x4
0x0000ffff807775f8 aa0603e5 orr %xzr %x6 lsl $0x00 -> %x5
0x0000ffff807775fc aa0703e6 orr %xzr %x7 lsl $0x00 -> %x6
0x0000ffff80777600 d4000001 svc $0x0000
end_pc = 0x0000ffff80777604
Also xref https://github.com/DynamoRIO/dynamorio/issues/4878#issuecomment-827726462 involving similar code in dispatch where signal reasons are not checked early enough and we not only print the wrong reasons but try to add to the IBT when the target is not known to be missing: I'm likely going to lump that in here.