]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
MFC 332454,334009,334122: Various fixes for x86 debug exceptions.
authorjhb <jhb@FreeBSD.org>
Fri, 14 Sep 2018 23:21:52 +0000 (23:21 +0000)
committerjhb <jhb@FreeBSD.org>
Fri, 14 Sep 2018 23:21:52 +0000 (23:21 +0000)
commit4484bf717c82ee46f15a522b7fc088a3e85f3d5b
treeed241d89becac608b147fad2380d174ee8c47b3d
parentbf831a911e604e7cba25ccf3b43f4cd96c8754c6
MFC 332454,334009,334122: Various fixes for x86 debug exceptions.

332454:
Fix PSL_T inheritance on exec for x86.

The miscellaneous x86 sysent->sv_setregs() implementations tried to
migrate PSL_T from the previous program to the new executed one, but
they evaluated regs->tf_eflags after the whole regs structure was
bzeroed.  Make this functional by saving PSL_T value before zeroing.

Note that if the debugger is not attached, executing the first
instruction in the new program with PSL_T set results in SIGTRAP, and
since all intercepted signals are reset to default dispostion on
exec(2), this means that non-debugged process gets killed immediately
if PSL_T is inherited.  In particular, since suid images drop
P_TRACED, attempt to set PSL_T for execution of such program would
kill the process.

Another issue with userspace PSL_T handling is that it is reset by
trap().  It is reasonable to clear PSL_T when entering SIGTRAP
handler, to allow the signal to be handled without recursion or
delivery of blocked fault.  But it is not reasonable to return back to
the normal flow with PSL_T cleared.  This is too late to change, I
think.

334009:
Cleanups related to debug exceptions on x86.

- Add constants for fields in DR6 and the reserved fields in DR7.  Use
  these constants instead of magic numbers in most places that use DR6
  and DR7.
- Refer to T_TRCTRAP as "debug exception" rather than a "trace trap"
  as it is not just for trace exceptions.
- Always read DR6 for debug exceptions and only clear TF in the flags
  register for user exceptions where DR6.BS is set.
- Clear DR6 before returning from a debug exception handler as
  recommended by the SDM dating all the way back to the 386.  This
  allows debuggers to determine the cause of each exception.  For
  kernel traps, clear DR6 in the T_TRCTRAP case and pass DR6 by value
  to other parts of the handler (namely, user_dbreg_trap()).  For user
  traps, wait until after trapsignal to clear DR6 so that userland
  debuggers can read DR6 via PT_GETDBREGS while the thread is stopped
  in trapsignal().

334122:
x86: stop unconditionally clearing PSL_T on the trace trap.

We certainly should clear PSL_T when calling the SIGTRAP signal
handler, which is already done by all x86 sendsig(9) ABI code.  On the
other hand, there is no obvious reason why PSL_T needs to be cleared
when returning from the signal handler.  For instance, Linux allows
userspace to set PSL_T and keep tracing enabled for the desired
period.  There are userspace programs which would use PSL_T if we make
it possible, for instance sbcl.

Remember if PSL_T was set by PT_STEP or PT_SETSTEP by mean of TDB_STEP
flag, and only clear it when the flag is set.
14 files changed:
sys/amd64/amd64/machdep.c
sys/amd64/amd64/trap.c
sys/amd64/ia32/ia32_signal.c
sys/amd64/include/db_machdep.h
sys/amd64/linux/linux_sysvec.c
sys/amd64/linux32/linux32_sysvec.c
sys/amd64/vmm/amd/svm.c
sys/amd64/vmm/intel/vmx.c
sys/i386/i386/machdep.c
sys/i386/i386/trap.c
sys/i386/include/db_machdep.h
sys/sys/proc.h
sys/x86/include/reg.h
sys/x86/include/x86_var.h