From owner-dev-commits-src-all@freebsd.org Fri May 21 12:46:28 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 70DD263182A; Fri, 21 May 2021 12:46:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FmmZD2Y66z4TjH; Fri, 21 May 2021 12:46:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 36D5D1117C; Fri, 21 May 2021 12:46:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 14LCkSe7037729; Fri, 21 May 2021 12:46:28 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14LCkS3Q037728; Fri, 21 May 2021 12:46:28 GMT (envelope-from git) Date: Fri, 21 May 2021 12:46:28 GMT Message-Id: <202105211246.14LCkS3Q037728@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 347ae5f3457b - stable/13 - kqueue timer: Remove detached knotes from the process stop queue MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 347ae5f3457bfe316aa2fb3c27dd7f431da6e45a Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 May 2021 12:46:28 -0000 The branch stable/13 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=347ae5f3457bfe316aa2fb3c27dd7f431da6e45a commit 347ae5f3457bfe316aa2fb3c27dd7f431da6e45a Author: Mark Johnston AuthorDate: 2021-05-14 14:07:56 +0000 Commit: Mark Johnston CommitDate: 2021-05-21 12:45:34 +0000 kqueue timer: Remove detached knotes from the process stop queue There are some scenarios where a timer event may be detached when it is on the process' kqueue timer stop queue. If kqtimer_proc_continue() is called after that point, it will iterate over the queue and access freed timer structures. It is also possible, at least in a multithreaded program, for a stopped timer event to be scheduled without removing it from the process' stop queue. Ensure that we do not doubly enqueue the event structure in this case. Reported by: syzbot+cea0931bb4e34cd728bd@syzkaller.appspotmail.com Reported by: syzbot+9e1a2f3734652015998c@syzkaller.appspotmail.com Reviewed by: kib Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D30251 (cherry picked from commit 2cca77ee01343bf080f1b70f0217a84c200fe7c1) --- sys/kern/kern_event.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 03f4b3afbc28..6b8ab11cb2dc 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -680,11 +680,14 @@ struct kq_timer_cb_data { struct proc *p; struct knote *kn; int cpuid; + int flags; TAILQ_ENTRY(kq_timer_cb_data) link; sbintime_t next; /* next timer event fires at */ sbintime_t to; /* precalculated timer period, 0 for abs */ }; +#define KQ_TIMER_CB_ENQUEUED 0x01 + static void kqtimer_sched_callout(struct kq_timer_cb_data *kc) { @@ -706,6 +709,7 @@ kqtimer_proc_continue(struct proc *p) TAILQ_FOREACH_SAFE(kc, &p->p_kqtim_stop, link, kc1) { TAILQ_REMOVE(&p->p_kqtim_stop, kc, link); + kc->flags &= ~KQ_TIMER_CB_ENQUEUED; if (kc->next <= now) filt_timerexpire_l(kc->kn, true); else @@ -753,7 +757,10 @@ filt_timerexpire_l(struct knote *kn, bool proc_locked) if (!proc_locked) PROC_LOCK(p); if (P_SHOULDSTOP(p) || P_KILLED(p)) { - TAILQ_INSERT_TAIL(&p->p_kqtim_stop, kc, link); + if ((kc->flags & KQ_TIMER_CB_ENQUEUED) == 0) { + kc->flags |= KQ_TIMER_CB_ENQUEUED; + TAILQ_INSERT_TAIL(&p->p_kqtim_stop, kc, link); + } if (!proc_locked) PROC_UNLOCK(p); return; @@ -826,6 +833,7 @@ filt_timerattach(struct knote *kn) kc->kn = kn; kc->p = curproc; kc->cpuid = PCPU_GET(cpuid); + kc->flags = 0; callout_init(&kc->c, 1); filt_timerstart(kn, to); @@ -856,6 +864,11 @@ filt_timerdetach(struct knote *kn) kc = kn->kn_ptr.p_v; callout_drain(&kc->c); + if ((kc->flags & KQ_TIMER_CB_ENQUEUED) != 0) { + PROC_LOCK(kc->p); + TAILQ_REMOVE(&kc->p->p_kqtim_stop, kc, link); + PROC_UNLOCK(kc->p); + } free(kc, M_KQUEUE); old = atomic_fetchadd_int(&kq_ncallouts, -1); KASSERT(old > 0, ("Number of callouts cannot become negative"));