Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp881516pxb; Tue, 3 Nov 2020 15:24:20 -0800 (PST) X-Google-Smtp-Source: ABdhPJxNJk6gTsdykCoS0x9ZG9y18U7fbbIBsXcg/LRLz/mWvgnFQXO+W/jZ3f9pljNEoeX4lZ0N X-Received: by 2002:a17:907:262d:: with SMTP id aq13mr5079766ejc.484.1604445860049; Tue, 03 Nov 2020 15:24:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604445860; cv=none; d=google.com; s=arc-20160816; b=FCjiVyaD6mzVCVoKQIxK3W2TolsQTJStTNQDYPvIzVigs5a/WBHKK8g3ntVLZHaIMN /naoyL53gCEHaeqloNsm1R0VhRAYBcvbdjD2KPYUdXjqpKxN2gZw3//ZRBOi28i+TkGE pg4n9uKQ6UL3iq4/mGq0s+7NlqziyofiLosdHpK5ct2VJS1owQvp4ziAY8Vm/CcatwMn +ZFO69ydpPiH6qP+dNKOuwbwB4/x0UXjQm4rKmSiTY+A30KP13XXi9eX23CbvGGuvYf+ 7aALLt5pADeqObJYRFExf450JOiQ2f7t1TSB6U+MeE/sSQYmF7KKv56jQAwgnbvj0G2V Mtrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=udzrmqMQ2V8bz4NPosCKsK5bnkKDdgks435PF37j76c=; b=WJwxsic978lYNHhjnf4NnffnuMCTpxnpr40+XZwMdaKiua1QnUd4IL0U9J7z7EgYR/ qBfwFkt0xHiNyUFOxfO1KMmQ0ojLtMVTVBrFEipBH6dGmFtuh0qZWV/94JcrAMZZ8/Rx 3qCs37qPmYNR1SSdSeyzMLThQKr+FVyMcm5lR5E3youeyyVuvjK6KRvO3/1J56ArP9PD zZ3aPy0Ngvka9Vnc5CeM9orcNfTX8daPaerEGh8ZnILtC37yUL4ymwbYf72SNAzWlaZW bvdTdiVLvYqOSFQ7jFhqYS6y8c9SpRg96w8x9Inu9q6csDNMdTy5lOgUrUiIqaDHjtUa +J0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=j5tpqXLX; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 20si244577ejw.320.2020.11.03.15.23.57; Tue, 03 Nov 2020 15:24:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=j5tpqXLX; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732966AbgKCVCd (ORCPT + 99 others); Tue, 3 Nov 2020 16:02:33 -0500 Received: from mail.kernel.org ([198.145.29.99]:39546 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733109AbgKCVCa (ORCPT ); Tue, 3 Nov 2020 16:02:30 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9E91C21534; Tue, 3 Nov 2020 21:02:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604437349; bh=FCyb2yWZtm8ne2ht2ePdPJlQjqUG7UEe30Nllxhl/Zg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j5tpqXLXnmAr0OdPPBGA3rYuFn719Szt80WheOt0OXP7C7VPQKsbhftzV/1V/Rv6I 12XuDp5FE1Qy9QdNVN0DGU5RhyHqgf0G4tJz75tQLzOv1NhjnT16AbpFnQWp2iqF/5 FRnpG17e/JmF11rrDdgaSXJCyPTL3JbU+wOtVDbU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= , Jinoh Kang , Juergen Gross , Stefano Stabellini , Wei Liu Subject: [PATCH 4.19 037/191] xen/events: avoid removing an event channel while handling it Date: Tue, 3 Nov 2020 21:35:29 +0100 Message-Id: <20201103203237.524540698@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201103203232.656475008@linuxfoundation.org> References: <20201103203232.656475008@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Juergen Gross commit 073d0552ead5bfc7a3a9c01de590e924f11b5dd2 upstream. Today it can happen that an event channel is being removed from the system while the event handling loop is active. This can lead to a race resulting in crashes or WARN() splats when trying to access the irq_info structure related to the event channel. Fix this problem by using a rwlock taken as reader in the event handling loop and as writer when deallocating the irq_info structure. As the observed problem was a NULL dereference in evtchn_from_irq() make this function more robust against races by testing the irq_info pointer to be not NULL before dereferencing it. And finally make all accesses to evtchn_to_irq[row][col] atomic ones in order to avoid seeing partial updates of an array element in irq handling. Note that irq handling can be entered only for event channels which have been valid before, so any not populated row isn't a problem in this regard, as rows are only ever added and never removed. This is XSA-331. Cc: stable@vger.kernel.org Reported-by: Marek Marczykowski-Górecki Reported-by: Jinoh Kang Signed-off-by: Juergen Gross Reviewed-by: Stefano Stabellini Reviewed-by: Wei Liu Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events/events_base.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_X86 #include @@ -69,6 +70,23 @@ const struct evtchn_ops *evtchn_ops; */ static DEFINE_MUTEX(irq_mapping_update_lock); +/* + * Lock protecting event handling loop against removing event channels. + * Adding of event channels is no issue as the associated IRQ becomes active + * only after everything is setup (before request_[threaded_]irq() the handler + * can't be entered for an event, as the event channel will be unmasked only + * then). + */ +static DEFINE_RWLOCK(evtchn_rwlock); + +/* + * Lock hierarchy: + * + * irq_mapping_update_lock + * evtchn_rwlock + * IRQ-desc lock + */ + static LIST_HEAD(xen_irq_list_head); /* IRQ <-> VIRQ mapping. */ @@ -103,7 +121,7 @@ static void clear_evtchn_to_irq_row(unsi unsigned col; for (col = 0; col < EVTCHN_PER_ROW; col++) - evtchn_to_irq[row][col] = -1; + WRITE_ONCE(evtchn_to_irq[row][col], -1); } static void clear_evtchn_to_irq_all(void) @@ -140,7 +158,7 @@ static int set_evtchn_to_irq(unsigned ev clear_evtchn_to_irq_row(row); } - evtchn_to_irq[row][col] = irq; + WRITE_ONCE(evtchn_to_irq[row][col], irq); return 0; } @@ -150,7 +168,7 @@ int get_evtchn_to_irq(unsigned evtchn) return -1; if (evtchn_to_irq[EVTCHN_ROW(evtchn)] == NULL) return -1; - return evtchn_to_irq[EVTCHN_ROW(evtchn)][EVTCHN_COL(evtchn)]; + return READ_ONCE(evtchn_to_irq[EVTCHN_ROW(evtchn)][EVTCHN_COL(evtchn)]); } /* Get info for IRQ */ @@ -259,10 +277,14 @@ static void xen_irq_info_cleanup(struct */ unsigned int evtchn_from_irq(unsigned irq) { - if (unlikely(WARN(irq >= nr_irqs, "Invalid irq %d!\n", irq))) + const struct irq_info *info = NULL; + + if (likely(irq < nr_irqs)) + info = info_for_irq(irq); + if (!info) return 0; - return info_for_irq(irq)->evtchn; + return info->evtchn; } unsigned irq_from_evtchn(unsigned int evtchn) @@ -438,16 +460,21 @@ static int __must_check xen_allocate_irq static void xen_free_irq(unsigned irq) { struct irq_info *info = info_for_irq(irq); + unsigned long flags; if (WARN_ON(!info)) return; + write_lock_irqsave(&evtchn_rwlock, flags); + list_del(&info->list); set_info_for_irq(irq, NULL); WARN_ON(info->refcnt > 0); + write_unlock_irqrestore(&evtchn_rwlock, flags); + kfree(info); /* Legacy IRQ descriptors are managed by the arch. */ @@ -1233,6 +1260,8 @@ static void __xen_evtchn_do_upcall(void) int cpu = get_cpu(); unsigned count; + read_lock(&evtchn_rwlock); + do { vcpu_info->evtchn_upcall_pending = 0; @@ -1248,6 +1277,7 @@ static void __xen_evtchn_do_upcall(void) } while (count != 1 || vcpu_info->evtchn_upcall_pending); out: + read_unlock(&evtchn_rwlock); put_cpu(); }