Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp1676965pxp; Thu, 10 Mar 2022 09:53:37 -0800 (PST) X-Google-Smtp-Source: ABdhPJyvu5cHYhJVrj1u8n1tIa39DFGkGhNnuVrpawhF0MCtgqmN9gF3MwZX24/xKAAVvHeZZS0p X-Received: by 2002:a50:fe0d:0:b0:415:e2ee:65af with SMTP id f13-20020a50fe0d000000b00415e2ee65afmr5372249edt.383.1646934817422; Thu, 10 Mar 2022 09:53:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646934817; cv=none; d=google.com; s=arc-20160816; b=FTNHiHg631UoJliLrISDU8+Bdi+rlOq3LH+QoTGiCgfY2zpRmgiIsP85dahGu61ifb iostcLVs6Hmq5vNHV+SWgNSSN13OlkdR1QUCVnQG0NpWqS0FjlgbpHMIHNnPg81j21So nxOoD9QqUdV2ysBlkO2MAbW1JaODGrkKzvyIjzMP/F/dKUsC4PJV/J1t99nM8a/SWkiq UVK/hcE/NJ2mxebna0KlgHIF22ENy2tyeyEH7DeGlsDIeMqvhX4892bzvQcWm0e2qOxT j/QVBeI76QPcrDdscafavME+viP4TbPhXWjhEADKiqWduP6anWBcP1AOjKtJgtIhmXNc JHxQ== 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=B5ES3cFwRGwtZDZNhXLsIvKsGPKXtdyYPDqu3CK6UCo=; b=erWcvkResiguRdEi+105QVV+3xtVhxwvPDDxBz5Itt1C8NCJWjFfNkCE7ttWCNQ8vC R0zRoEttFRFp2C4/CzOLGaczKqF1jVItE6GYWTal3mVt+qYGjmv8MKjBYhiwimVrCMgy 710+1zyAMjJZfCZDFkNiEBGAUON9u6kxQvP6xNonr0ChXslcTAeJfjdEjzXPFiFZfZBz nTQNwLnzmcstJ1rH5Q3WX2O/oSHuGoIRx4/0UlDLsmLpG2T4zGGSKvTF5EkO3yUEloSu ytnPA6mJIH+PWENZrCJNJYQvdlqpuiiGoSzrQJBLzGIFibnaoBBa0uD9/9IJZUHeI+MQ Ee0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Zb7Ot0ZL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ej18-20020a056402369200b00416c0d02d57si1002919edb.372.2022.03.10.09.53.14; Thu, 10 Mar 2022 09:53:37 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Zb7Ot0ZL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243669AbiCJO1m (ORCPT + 99 others); Thu, 10 Mar 2022 09:27:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243712AbiCJOZC (ORCPT ); Thu, 10 Mar 2022 09:25:02 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 537B015F373; Thu, 10 Mar 2022 06:21:38 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 931D6B82678; Thu, 10 Mar 2022 14:21:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D72F1C340EB; Thu, 10 Mar 2022 14:21:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1646922082; bh=WMBsDGoFwKsBC3UgmdydLX9aTvQjG9Z/G7T0quQ9LAM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Zb7Ot0ZLD3/IpdTGiL2I+T+bKCl54QkryaeFAiyaihphbFHL8BsHpmCe+amaPMRlx RBMCQSmEJFZKiuR9xeIxdH3KtgsHnPU4KEXBF+lpAx72u3pwGSbQ5DleqgtQxEv4pG vz8LAFF/ZckAtWtQgmKVKm33XycdbABeWz765yAo= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Simon Gaiser , Juergen Gross , Jan Beulich Subject: [PATCH 4.14 30/31] xen/gnttab: fix gnttab_end_foreign_access() without page specified Date: Thu, 10 Mar 2022 15:18:43 +0100 Message-Id: <20220310140808.419605112@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220310140807.524313448@linuxfoundation.org> References: <20220310140807.524313448@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Juergen Gross Commit 42baefac638f06314298087394b982ead9ec444b upstream. gnttab_end_foreign_access() is used to free a grant reference and optionally to free the associated page. In case the grant is still in use by the other side processing is being deferred. This leads to a problem in case no page to be freed is specified by the caller: the caller doesn't know that the page is still mapped by the other side and thus should not be used for other purposes. The correct way to handle this situation is to take an additional reference to the granted page in case handling is being deferred and to drop that reference when the grant reference could be freed finally. This requires that there are no users of gnttab_end_foreign_access() left directly repurposing the granted page after the call, as this might result in clobbered data or information leaks via the not yet freed grant reference. This is part of CVE-2022-23041 / XSA-396. Reported-by: Simon Gaiser Signed-off-by: Juergen Gross Reviewed-by: Jan Beulich Signed-off-by: Greg Kroah-Hartman --- drivers/xen/grant-table.c | 30 +++++++++++++++++++++++------- include/xen/grant_table.h | 7 ++++++- 2 files changed, 29 insertions(+), 8 deletions(-) --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -114,6 +114,10 @@ struct gnttab_ops { * return the frame. */ unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref); + /* + * Read the frame number related to a given grant reference. + */ + unsigned long (*read_frame)(grant_ref_t ref); }; struct unmap_refs_callback_data { @@ -278,6 +282,11 @@ int gnttab_end_foreign_access_ref(grant_ } EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); +static unsigned long gnttab_read_frame_v1(grant_ref_t ref) +{ + return gnttab_shared.v1[ref].frame; +} + struct deferred_entry { struct list_head list; grant_ref_t ref; @@ -307,12 +316,9 @@ static void gnttab_handle_deferred(unsig spin_unlock_irqrestore(&gnttab_list_lock, flags); if (_gnttab_end_foreign_access_ref(entry->ref, entry->ro)) { put_free_entry(entry->ref); - if (entry->page) { - pr_debug("freeing g.e. %#x (pfn %#lx)\n", - entry->ref, page_to_pfn(entry->page)); - put_page(entry->page); - } else - pr_info("freeing g.e. %#x\n", entry->ref); + pr_debug("freeing g.e. %#x (pfn %#lx)\n", + entry->ref, page_to_pfn(entry->page)); + put_page(entry->page); kfree(entry); entry = NULL; } else { @@ -337,9 +343,18 @@ static void gnttab_handle_deferred(unsig static void gnttab_add_deferred(grant_ref_t ref, bool readonly, struct page *page) { - struct deferred_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + struct deferred_entry *entry; + gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; const char *what = KERN_WARNING "leaking"; + entry = kmalloc(sizeof(*entry), gfp); + if (!page) { + unsigned long gfn = gnttab_interface->read_frame(ref); + + page = pfn_to_page(gfn_to_pfn(gfn)); + get_page(page); + } + if (entry) { unsigned long flags; @@ -1011,6 +1026,7 @@ static const struct gnttab_ops gnttab_v1 .update_entry = gnttab_update_entry_v1, .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1, .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1, + .read_frame = gnttab_read_frame_v1, }; static void gnttab_request_version(void) --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -100,7 +100,12 @@ int gnttab_end_foreign_access_ref(grant_ * Note that the granted page might still be accessed (read or write) by the * other side after gnttab_end_foreign_access() returns, so even if page was * specified as 0 it is not allowed to just reuse the page for other - * purposes immediately. + * purposes immediately. gnttab_end_foreign_access() will take an additional + * reference to the granted page in this case, which is dropped only after + * the grant is no longer in use. + * This requires that multi page allocations for areas subject to + * gnttab_end_foreign_access() are done via alloc_pages_exact() (and freeing + * via free_pages_exact()) in order to avoid high order pages. */ void gnttab_end_foreign_access(grant_ref_t ref, int readonly, unsigned long page);