Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Dec 2019 09:21:00 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r355385 - stable/12/sys/kern
Message-ID:  <201912040921.xB49L0Mx079338@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Dec  4 09:21:00 2019
New Revision: 355385
URL: https://svnweb.freebsd.org/changeset/base/355385

Log:
  MFC r355146:
  Ease the life of PT_TO_SCE/PT_TO_SCX users when debuggee sleeps in
  sigsuspend(2)/sig{timed,}wait(2).

Modified:
  stable/12/sys/kern/kern_sig.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/kern/kern_sig.c
==============================================================================
--- stable/12/sys/kern/kern_sig.c	Wed Dec  4 09:18:32 2019	(r355384)
+++ stable/12/sys/kern/kern_sig.c	Wed Dec  4 09:21:00 2019	(r355385)
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/procdesc.h>
+#include <sys/ptrace.h>
 #include <sys/posix4.h>
 #include <sys/pioctl.h>
 #include <sys/racct.h>
@@ -1252,11 +1253,13 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
 	int error, sig, timo, timevalid = 0;
 	struct timespec rts, ets, ts;
 	struct timeval tv;
+	bool traced;
 
 	p = td->td_proc;
 	error = 0;
 	ets.tv_sec = 0;
 	ets.tv_nsec = 0;
+	traced = false;
 
 	if (timeout != NULL) {
 		if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
@@ -1309,6 +1312,11 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
 			timo = 0;
 		}
 
+		if (traced) {
+			error = EINTR;
+			break;
+		}
+
 		error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", timo);
 
 		if (timeout != NULL) {
@@ -1320,6 +1328,16 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
 				error = 0;
 			}
 		}
+
+		/*
+		 * If PTRACE_SCE or PTRACE_SCX were set after
+		 * userspace entered the syscall, return spurious
+		 * EINTR after wait was done.  Only do this as last
+		 * resort after rechecking for possible queued signals
+		 * and expired timeouts.
+		 */
+		if (error == 0 && (p->p_ptevents & PTRACE_SYSCALL) != 0)
+			traced = true;
 	}
 
 	new_block = saved_mask;
@@ -1532,6 +1550,14 @@ kern_sigsuspend(struct thread *td, sigset_t mask)
 			has_sig += postsig(sig);
 		}
 		mtx_unlock(&p->p_sigacts->ps_mtx);
+
+		/*
+		 * If PTRACE_SCE or PTRACE_SCX were set after
+		 * userspace entered the syscall, return spurious
+		 * EINTR.
+		 */
+		if ((p->p_ptevents & PTRACE_SYSCALL) != 0)
+			has_sig += 1;
 	}
 	PROC_UNLOCK(p);
 	td->td_errno = EINTR;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912040921.xB49L0Mx079338>