From owner-svn-src-stable@freebsd.org Fri Nov 9 17:43:24 2018 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4EFB61102862; Fri, 9 Nov 2018 17:43:24 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id CFAB784C75; Fri, 9 Nov 2018 17:43:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id B0A0A172C7; Fri, 9 Nov 2018 17:43:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wA9HhNwP004384; Fri, 9 Nov 2018 17:43:23 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wA9HhNYD004383; Fri, 9 Nov 2018 17:43:23 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201811091743.wA9HhNYD004383@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Fri, 9 Nov 2018 17:43:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r340290 - stable/11/sys/kern X-SVN-Group: stable-11 X-SVN-Commit-Author: kib X-SVN-Commit-Paths: stable/11/sys/kern X-SVN-Commit-Revision: 340290 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: CFAB784C75 X-Spamd-Result: default: False [-106.87 / 200.00]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; ALLOW_DOMAIN_WHITELIST(-100.00)[FreeBSD.org]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[4]; TO_MATCH_ENVRCPT_ALL(0.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; MIME_GOOD(-0.10)[text/plain]; TO_DN_NONE(0.00)[]; HAS_XAW(0.00)[]; R_SPF_SOFTFAIL(0.00)[~all]; DMARC_NA(0.00)[FreeBSD.org]; RCVD_COUNT_THREE(0.00)[4]; MX_GOOD(-0.01)[cached: mx1.FreeBSD.org]; NEURAL_HAM_SHORT(-1.00)[-1.000,0]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; RCVD_TLS_LAST(0.00)[]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; IP_SCORE(-3.76)[ip: (-9.91), ipnet: 2610:1c1:1::/48(-4.93), asn: 11403(-3.87), country: US(-0.09)] X-Rspamd-Server: mx1.freebsd.org X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Nov 2018 17:43:24 -0000 Author: kib Date: Fri Nov 9 17:43:23 2018 New Revision: 340290 URL: https://svnweb.freebsd.org/changeset/base/340290 Log: MFC r325771, r325777, r325778 (all by jhb): Only clear a pending thread event if one is pending. This fixes a panic when attaching to an already-stopped process. Also do some other clean ups for control flow of sendsig section. Reviewed by: jhb Sponsored by: The FreeBSD Foundation Modified: stable/11/sys/kern/sys_process.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/kern/sys_process.c ============================================================================== --- stable/11/sys/kern/sys_process.c Fri Nov 9 17:43:19 2018 (r340289) +++ stable/11/sys/kern/sys_process.c Fri Nov 9 17:43:23 2018 (r340290) @@ -870,19 +870,13 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi } /* not currently stopped */ - if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) == 0 || + if ((p->p_flag & P_STOPPED_TRACE) == 0 || p->p_suspcount != p->p_numthreads || (p->p_flag & P_WAITED) == 0) { error = EBUSY; goto fail; } - if ((p->p_flag & P_STOPPED_TRACE) == 0) { - static int count = 0; - if (count++ == 0) - printf("P_STOPPED_TRACE not set.\n"); - } - /* OK */ break; } @@ -927,11 +921,28 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi if (p->p_pptr != td->td_proc) { proc_reparent(p, td->td_proc); } - data = SIGSTOP; CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid, p->p_oppid); - goto sendsig; /* in PT_CONTINUE below */ + sx_xunlock(&proctree_lock); + proctree_locked = 0; + MPASS(p->p_xthread == NULL); + MPASS((p->p_flag & P_STOPPED_TRACE) == 0); + + /* + * If already stopped due to a stop signal, clear the + * existing stop before triggering a traced SIGSTOP. + */ + if ((p->p_flag & P_STOPPED_SIG) != 0) { + PROC_SLOCK(p); + p->p_flag &= ~(P_STOPPED_SIG | P_WAITED); + thread_unsuspend(p); + PROC_SUNLOCK(p); + } + + kern_psignal(p, SIGSTOP); + break; + case PT_CLEARSTEP: CTR2(KTR_PTRACE, "PT_CLEARSTEP: tid %d (pid %d)", td2->td_tid, p->p_pid); @@ -1118,8 +1129,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi sigqueue_delete(&td3->td_sigqueue, SIGSTOP); } - td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP); + td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP | + TDB_SUSPEND); } + if ((p->p_flag2 & P2_PTRACE_FSTP) != 0) { sigqueue_delete(&p->p_sigqueue, SIGSTOP); p->p_flag2 &= ~P2_PTRACE_FSTP; @@ -1130,54 +1143,45 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi break; } + sx_xunlock(&proctree_lock); + proctree_locked = 0; + sendsig: - /* + MPASS(proctree_locked == 0); + + /* * Clear the pending event for the thread that just * reported its event (p_xthread). This may not be * the thread passed to PT_CONTINUE, PT_STEP, etc. if * the debugger is resuming a different thread. + * + * Deliver any pending signal via the reporting thread. */ - td2 = p->p_xthread; - if (proctree_locked) { - sx_xunlock(&proctree_lock); - proctree_locked = 0; - } - p->p_xsig = data; + MPASS(p->p_xthread != NULL); + p->p_xthread->td_dbgflags &= ~TDB_XSIG; + p->p_xthread->td_xsig = data; p->p_xthread = NULL; - if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) { - /* deliver or queue signal */ - td2->td_dbgflags &= ~TDB_XSIG; - td2->td_xsig = data; + p->p_xsig = data; - /* - * P_WKILLED is insurance that a PT_KILL/SIGKILL always - * works immediately, even if another thread is - * unsuspended first and attempts to handle a different - * signal or if the POSIX.1b style signal queue cannot - * accommodate any new signals. - */ - if (data == SIGKILL) - proc_wkilled(p); + /* + * P_WKILLED is insurance that a PT_KILL/SIGKILL + * always works immediately, even if another thread is + * unsuspended first and attempts to handle a + * different signal or if the POSIX.1b style signal + * queue cannot accommodate any new signals. + */ + if (data == SIGKILL) + proc_wkilled(p); - if (req == PT_DETACH) { - FOREACH_THREAD_IN_PROC(p, td3) - td3->td_dbgflags &= ~TDB_SUSPEND; - } - /* - * unsuspend all threads, to not let a thread run, - * you should use PT_SUSPEND to suspend it before - * continuing process. - */ - PROC_SLOCK(p); - p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED); - thread_unsuspend(p); - PROC_SUNLOCK(p); - if (req == PT_ATTACH) - kern_psignal(p, data); - } else { - if (data) - kern_psignal(p, data); - } + /* + * Unsuspend all threads. To leave a thread + * suspended, use PT_SUSPEND to suspend it before + * continuing the process. + */ + PROC_SLOCK(p); + p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED); + thread_unsuspend(p); + PROC_SUNLOCK(p); break; case PT_WRITE_I: