> What about PTRACE_SYSEMU_SINGLESTEP ? I will read the code > tomorrow, but it is easy to miss some detail and we don't > have any test-cases.
These exist purely for UML. So the real test cases are to use UML. To start with, make sure that check_sysemu() gets the same results as on the vanilla kernel. > Looks like, PTRACE_SYSEMU_SINGLESTEP is PTRACE_SINGLESTEP > plus: if we enter syscall we should > > - return UTRACE_SYSCALL_ABORT > > - avoid SYSCALL_EXIT report like PTRACE_SYSEMU Right. I believe that the intent is PTRACE_SYSEMU_SINGLESTEP into a syscall insn behaves exactly like PTRACE_SYSEMU. If it's any other insn, it behaves exactly like PTRACE_SINGLESTEP. > - avoid the unnecessary send_sigtrap() in syscall_trace_leave() > somehow, but the exact semantics is not clear to me... If there was a syscall-entry report under SYSEMU, then you do not also report that as a single-step stop. > In particular. The tracee stops in SYSCALL_ENTRY, the tracer > does PTRACE_SYSEMU_SINGLESTEP. We should just do enable_step() > and clear UTRACE_EVENT(SYSCALL_EXIT), correct? That is a possible implementation detail, sure. The semantics are that the syscall doesn't happen, and there is only one stop. > Afaics, PTRACE_SYSEMU means: > > - cancel this syscall, and do _not_ report SYSCALL_ENTRY > to the tracer > > - SYSCALL_EXIT should be reported, but send_sigtrap() > should be avoied (in case it was SYSEMU_SINGLESTEP). > > Correct? There is no distinction in ptrace between the entry and exit reports. So this is implementation detail, not semantics. The semantics say that the tracer sees only one stop per syscall insn, not two. The other thing that is possibly relevant to the semantics is the interaction with syscall audit. In the syscall entry path, we decide that the syscall will be skipped, then stop for the ptrace report. After resuming, we'll get to audit_syscall_entry and it will examine the register state as changed by ptrace before the resumption. So that will claim something or other (chosen by the tracer) for audit, even though the syscall doesn't really happen. Then we'll get to the syscall exit path, do audit_syscall_exit with the very same register state, and do nothing else. Those audit calls seem pretty useless since they don't even really tell a lie chosen by the tracer--the audit log just sees the "not really made" syscall entry state followed by the "aborted" (-ENOSYS) exit state. But it might be considered worthwhile upstream to keep this exactly as it was. > So. Looks like the only complication is that we should avoid > the unnecessary send_sigtrap() in syscall_trace_leave(), but > we shouldn't use TIF_SYSCALL_EMU - it must die. Right. There is another possible wrinkle, though this probably doesn't matter. If you used PTRACE_SYSEMU{,_SINGLESTEP} and got a syscall entry stop, then you can resume it with PTRACE_SYSCALL or PTRACE_SINGLESTEP instead. In those cases, you will get a syscall-exit report or will get a synthetic TRAP_BRKPT, looking at the "syscall returned -ENOSYS" state. I'm almost positive that nobody ever does this and that nobody cares about this behaving that way (i.e. UML doesn't care, and nobody else uses this stuff). But them's the manifest semantics of today. So if we were to care about preserving that, it could impinge on whether we implement by stopping in syscall-entry and then skipping syscall-exit or vice versa. Thanks, Roland