Do not go into sleep in sleepq_catch_signals() when SIGSTOP from

PT_ATTACH was consumed.

In particular, do not clear TDP_FSTP in ptracestop() if td_wchan is
non-NULL. Leave it to sleepq_catch_signal() to clear and convert zero
return code to EINTR.

Otherwise, per submitter report, if the PT_ATTACH SIGSTOP was
delivered right after the thread was added to the sleepqueue but not
yet really sleep, and cursig() caused debugger attach, the thread
sleeps instead of returning to the userspace boundary with EINTR.

PR: 231445
Reported by:	Efi Weiss <valmarelox@gmail.com>
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D20381
This commit is contained in:
Konstantin Belousov 2019-05-29 14:05:27 +00:00
parent 21db5fcc9d
commit ab74c84333
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=348360
2 changed files with 22 additions and 1 deletions

View File

@ -2576,7 +2576,15 @@ ptracestop(struct thread *td, int sig, ksiginfo_t *si)
p->p_xthread == NULL)) { p->p_xthread == NULL)) {
p->p_xsig = sig; p->p_xsig = sig;
p->p_xthread = td; p->p_xthread = td;
td->td_dbgflags &= ~TDB_FSTP;
/*
* If we are on sleepqueue already,
* let sleepqueue code decide if it
* needs to go sleep after attach.
*/
if (td->td_wchan == NULL)
td->td_dbgflags &= ~TDB_FSTP;
p->p_flag2 &= ~P2_PTRACE_FSTP; p->p_flag2 &= ~P2_PTRACE_FSTP;
p->p_flag |= P_STOPPED_SIG | P_STOPPED_TRACE; p->p_flag |= P_STOPPED_SIG | P_STOPPED_TRACE;
sig_suspend_threads(td, p, 0); sig_suspend_threads(td, p, 0);

View File

@ -498,6 +498,19 @@ sleepq_catch_signals(void *wchan, int pri)
} else { } else {
mtx_unlock(&ps->ps_mtx); mtx_unlock(&ps->ps_mtx);
} }
/*
* Do not go into sleep if this thread was the
* ptrace(2) attach leader. cursig() consumed
* SIGSTOP from PT_ATTACH, but we usually act
* on the signal by interrupting sleep, and
* should do that here as well.
*/
if ((td->td_dbgflags & TDB_FSTP) != 0) {
if (ret == 0)
ret = EINTR;
td->td_dbgflags &= ~TDB_FSTP;
}
} }
/* /*
* Lock the per-process spinlock prior to dropping the PROC_LOCK * Lock the per-process spinlock prior to dropping the PROC_LOCK