DynamoRIO / DynamoRIO/dynamorio
System call instruction presented to clients may not have an actual system call invocation until repeated
- Dominant language
- C
- Stars
- 3.2k
- Forks
- 629
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 31
Description
Documenting what we had to solve in drmemtrace in PR #6096 where we added a system call number marker record to our trace in the pre-syscall event and wanted it to always immediately follow the system call instruction which was recorded in basic block instrumentation.
The drmemtrace tool returns true for the filter syscall event, so all syscalls end blocks and we go back to dispatch to actually execute the syscall.
The problem is that if an asynchronous signal arrives during a syscall-ending block, DR will deliver the signal before executing the syscall (and before raising the pre-syscall handler).
In PR #6096 we solve this in post-processing by removing a syscall instruction that has no marker after it, calling it a "false syscall". Other tools though will have to do their own fixup.
Xref #6105
Xref #5790
I created the linux.signal_pre_syscall test to reliably hit this scenario. Here is what happens:
```
interp: start_pc = 0x00007f2d023fab29
0x00007f2d023fab29 d9 f3 fpatan %st0 %st1 -> %st0 %st1
<...>
0x00007f2d023fab7f d9 f3 fpatan %st0 %st1 -> %st0 %st1
0x00007f2d023fab81 b8 27 00 00 00 mov $0x00000027 -> %eax
0x00007f2d023fab86 0f 05 syscall -> %rcx %r11
end_pc = 0x00007f2d023fab88
Fragment 2407, tag 0x00007f2d023fab29, flags 0x1801030, shared, size 280, must end trace:
Exit from F2407(0x00007f2d023fab29).0x00007f2cc26419d3 (shared)
main_signal_handler: thread=1727199, sig=10, xsp=0x00007f2ac24bd378, retaddr=0x00007f2d066c0c0c
record_pending_signal(10) from DR at pc 0x00007f2d0672f5fc
execute_handler_from_dispatch for signal 10
set frame's eip to 0x00007f2d023fab86
Entry into F2408(0x00007f2d023fa74c).0x00007f2cc26419f1 (shared)
Exit from F2409(0x00007f2d05c38f90).0x00007f2cc2641c08 (shared)
(block ends with syscall)
Entry into do_syscall to execute a non-ignorable system call
system call 15
rt_sigreturn()
set next tag to 0x00007f2d023fab86, sc->SC_XIP to 0x00007f2cc246af40
interp: start_pc = 0x00007f2d023fab86
0x00007f2d023fab86 0f 05 syscall -> %rcx %r11
end_pc = 0x00007f2d023fab88
Fragment 2412, tag 0x00007f2d023fab86, flags 0x1801030, shared, size 169, must end trace:
Entry into F2410(0x00007f2d023fab88).0x00007f2cc2641c2c (shared)
main_signal_handler: thread=1727199, sig=10, xsp=0x00007f2ac24bd378, retaddr=0x00007f2d066c0c0c
record_pending_signal(10) from cache pc 0x00007f2cc2641913
delaying until exit F2407
execute_handler_from_dispatch for signal 10
set frame's eip to 0x00007f2d023fab86
Entry into F2408(0x00007f2d023fa74c).0x00007f2cc26419f1 (shared)
Exit from F2409(0x00007f2d05c38f90).0x00007f2cc2641c08 (shared)
(block ends with syscall)
Entry into do_syscall to execute a non-ignorable system call
system call 15
rt_sigreturn()
set next tag to 0x00007f2d023fab86, sc->SC_XIP to 0x00007f2cc246af40
Entry into F2412(0x00007f2d023fab86).0x00007f2cc2641e14 (shared)
```
And in the trace we see a syscall instr with no marker interrupted for a signal handler, followed by a repeat syscall instr with a marker:
```
193666 149617: 1727199 ifetch 2 byte(s) @ 0x00007f2d023fab7d d9 f3 fpatan
193667 149618: 1727199 ifetch 2 byte(s) @ 0x00007f2d023fab7f d9 f3 fpatan
193668 149619: 1727199 ifetch 5 byte(s) @ 0x00007f2d023fab81 b8 27 00 00 00 mov $0x00000027, %eax
193669 149620: 1727199 ifetch 2 byte(s) @ 0x00007f2d023fab86 0f 05 syscall
193670 149620: 1727199
193671 149620: 1727199
193672 149620: 1727199
193673 149621: 1727199 ifetch 1 byte(s) @ 0x00007f2d023fa74c 55 push %rbp
193674 149621: 1727199 write 8 byte(s) @ 0x00007ffd5332f920 by PC 0x00007f2d023fa74c
193675 149622: 1727199 ifetch 3 byte(s) @ 0x00007f2d023fa74d 48 89 e5 mov %rsp, %rbp
193676 149623: 1727199 ifetch 3 byte(s) @ 0x00007f2d023fa750 89 7d ec mov %edi, -0x14(%rbp)
193677 149623: 1727199 write 4 byte(s) @ 0x00007ffd5332f90c by PC 0x00007f2d023fa750
193678 149624: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa753 48 89 75 e0 mov %rsi, -0x20(%rbp)
193679 149624: 1727199 write 8 byte(s) @ 0x00007ffd5332f900 by PC 0x00007f2d023fa753
193680 149625: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa757 48 89 55 d8 mov %rdx, -0x28(%rbp)
193681 149625: 1727199 write 8 byte(s) @ 0x00007ffd5332f8f8 by PC 0x00007f2d023fa757
193682 149626: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa75b 48 8b 45 d8 mov -0x28(%rbp), %rax
193683 149626: 1727199 read 8 byte(s) @ 0x00007ffd5332f8f8 by PC 0x00007f2d023fa75b
193684 149627: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa75f 48 89 45 f8 mov %rax, -0x08(%rbp)
193685 149627: 1727199 write 8 byte(s) @ 0x00007ffd5332f918 by PC 0x00007f2d023fa75f
193686 149628: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa763 48 8b 45 f8 mov -0x08(%rbp), %rax
193687 149628: 1727199 read 8 byte(s) @ 0x00007ffd5332f918 by PC 0x00007f2d023fa763
193688 149629: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa767 48 83 c0 28 add $0x28, %rax
193689 149630: 1727199 ifetch 4 byte(s) @ 0x00007f2d023fa76b 48 89 45 f0 mov %rax, -0x10(%rbp)
193690 149630: 1727199 write 8 byte(s) @ 0x00007ffd5332f910 by PC 0x00007f2d023fa76b
193691 149631: 1727199 ifetch 1 byte(s) @ 0x00007f2d023fa76f 90 nop
193692 149632: 1727199 ifetch 1 byte(s) @ 0x00007f2d023fa770 5d pop %rbp
193693 149632: 1727199 read 8 byte(s) @ 0x00007ffd5332f920 by PC 0x00007f2d023fa770
193694 149633: 1727199 ifetch 1 byte(s) @ 0x00007f2d023fa771 c3 ret
193695 149633: 1727199 read 8 byte(s) @ 0x00007ffd5332f928 by PC 0x00007f2d023fa771
193696 149634: 1727199 ifetch 7 byte(s) @ 0x00007f2d05c38f90 48 c7 c0 0f 00 00 00 mov $0x0000000f, %rax
193697 149635: 1727199 ifetch 2 byte(s) @ 0x00007f2d05c38f97 0f 05 syscall
193698 149635: 1727199
193699 149635: 1727199
193700 149635: 1727199
193701 149635: 1727199
193702 149635: 1727199
193703 149635: 1727199
193704 149636: 1727199 ifetch 2 byte(s) @ 0x00007f2d023fab86 0f 05 syscall
193705 149636: 1727199
193706 149636: 1727199
193707 149636: 1727199
193708 149637: 1727199 ifetch 1 byte(s) @ 0x00007f2d023fab88 c3 ret
```
Disabling "Syscall instruction not followed by syscall marker" (later I added the removal in raw2trace) we have no errors:
```
$ bin64/drrun -t drcachesim -simulator_type invariant_checker -indir drmemtrace.*.dir
Trace invariant checks passed
```
We used to think this would result in a PC discontinuity: but there is no PC discontinuity to report here since the checker has to allow a synchronous signal restarting the instr. To a human it looks like an auto-restart syscall even though really it's a syscall that never happened the first time. I guess auto-restart never *completed* the first time -- but still different.
Contributor guide
Assessment
This issue has not been assessed yet.