Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp1254005imw; Tue, 5 Jul 2022 06:29:51 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vKWtm3/1AvoYtwrRln895LLTgkoBEn4fDU7dTWXlBqVk30Ant4phjmTcxPOX8vcVpZr9Vd X-Received: by 2002:a05:6402:5207:b0:435:a27b:88f7 with SMTP id s7-20020a056402520700b00435a27b88f7mr47461832edd.22.1657027790913; Tue, 05 Jul 2022 06:29:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657027790; cv=none; d=google.com; s=arc-20160816; b=vlu4OY7d4vLBJgo4g92qkHxXfjCemG6VZouHy3njBGj3Wh96WGGmo1BKtDtey6WHSL zuMH7SRJFHJNU8f2sORv+EJncxXxB3adBedERi9NKEjb7gNkh5fuDGM44prIXvxvxBKY 96SQXqTrapXlvaQlI+D3P9Zu6ole5jdglvcaiO1CTIWzKyXzEtCB27pVPgNlxogFJ3CS ztW8ntGIzUrug8eB+lLbiK//DIYVhKZJx4QHFELJOIgXBHpzLT5S7eZ/equdOoKv1IQY YyVqLg64FjL6ptK7jl5P11s6WUw6PlDOFWVklvAbLCtY3Sr/BRI+d4znBOm5QXimGOpA 8rWA== 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=j4WnjjfXk3aTnPpDZfOjNz0p955ftBEIjOLgVb+agI4=; b=Xw+y9nw3hmnboODKLui6nfzxpFSoUP5q5E4fWKM8RMeCSQzKxB6VONPwmx4qHKLCxc tAdWfppRqmSN/08fWcyNr/KMolzDFCWcs+UBZ/madIzbQJeudu2IRMT+3m0rsCfySYj7 kePmR/HWF4F5jTA6nvGd99Cyf3nBdVVEf+YiCfsWTQ47NGaza3OAF5ic0R7bJRb4LCvh Z2MQ7st0wZP3GfgmEEd07663sn2Q2UXKRPVkmxPJmmVq/h0IsEDk+MzxDOKIUtHiSuGC 7I2DzYU+diDjtzr1b/mKE/g1Hc/fovPTj8FNgaW/p0OKLcZRQ+VNPjDVxPgpyhBq+JYM eZZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=bG0qmfsl; 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 i5-20020a170906a28500b0070ed13d358fsi39094038ejz.194.2022.07.05.06.29.26; Tue, 05 Jul 2022 06:29:50 -0700 (PDT) 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=bG0qmfsl; 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 S234060AbiGEMGS (ORCPT + 99 others); Tue, 5 Jul 2022 08:06:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233605AbiGEMDh (ORCPT ); Tue, 5 Jul 2022 08:03:37 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7975715FF4; Tue, 5 Jul 2022 05:03:32 -0700 (PDT) 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 4FB76B817CC; Tue, 5 Jul 2022 12:03:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 968CDC341C7; Tue, 5 Jul 2022 12:03:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1657022610; bh=ePqjnMbn5sJMyG/Uk/PGDWQjEKsg5rOMaiI9dmyuPqg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bG0qmfsloVDaZI5ro4jDbT85AWmX5dpunjJV0bxOfvfcFLzsE5nVI78ihaPAXnse5 Ic/U4qbh8zhHehAnA7jkrQMOpBsU1KKKe2oDVYJp2rz85W6WmPec1r2tL6e+80IF5f svd3uX1A28e8j+m+FtDQWn5dqWFUKObVN5bEj7AI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Juergen Gross Subject: [PATCH 4.19 30/33] xen/blkfront: force data bouncing when backend is untrusted Date: Tue, 5 Jul 2022 13:58:22 +0200 Message-Id: <20220705115607.595445107@linuxfoundation.org> X-Mailer: git-send-email 2.37.0 In-Reply-To: <20220705115606.709817198@linuxfoundation.org> References: <20220705115606.709817198@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.8 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: Roger Pau Monne commit 2400617da7eebf9167d71a46122828bc479d64c9 upstream. Split the current bounce buffering logic used with persistent grants into it's own option, and allow enabling it independently of persistent grants. This allows to reuse the same code paths to perform the bounce buffering required to avoid leaking contiguous data in shared pages not part of the request fragments. Reporting whether the backend is to be trusted can be done using a module parameter, or from the xenstore frontend path as set by the toolstack when adding the device. This is CVE-2022-33742, part of XSA-403. Signed-off-by: Roger Pau Monné Reviewed-by: Juergen Gross Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkfront.c | 49 +++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -151,6 +151,10 @@ static unsigned int xen_blkif_max_ring_o module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444); MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring"); +static bool __read_mostly xen_blkif_trusted = true; +module_param_named(trusted, xen_blkif_trusted, bool, 0644); +MODULE_PARM_DESC(trusted, "Is the backend trusted"); + #define BLK_RING_SIZE(info) \ __CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages) @@ -211,6 +215,7 @@ struct blkfront_info unsigned int feature_discard:1; unsigned int feature_secdiscard:1; unsigned int feature_persistent:1; + unsigned int bounce:1; unsigned int discard_granularity; unsigned int discard_alignment; /* Number of 4KB segments handled */ @@ -300,7 +305,7 @@ static int fill_grant_buffer(struct blkf if (!gnt_list_entry) goto out_of_memory; - if (info->feature_persistent) { + if (info->bounce) { granted_page = alloc_page(GFP_NOIO | __GFP_ZERO); if (!granted_page) { kfree(gnt_list_entry); @@ -320,7 +325,7 @@ out_of_memory: list_for_each_entry_safe(gnt_list_entry, n, &rinfo->grants, node) { list_del(&gnt_list_entry->node); - if (info->feature_persistent) + if (info->bounce) __free_page(gnt_list_entry->page); kfree(gnt_list_entry); i--; @@ -366,7 +371,7 @@ static struct grant *get_grant(grant_ref /* Assign a gref to this page */ gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); BUG_ON(gnt_list_entry->gref == -ENOSPC); - if (info->feature_persistent) + if (info->bounce) grant_foreign_access(gnt_list_entry, info); else { /* Grant access to the GFN passed by the caller */ @@ -390,7 +395,7 @@ static struct grant *get_indirect_grant( /* Assign a gref to this page */ gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); BUG_ON(gnt_list_entry->gref == -ENOSPC); - if (!info->feature_persistent) { + if (!info->bounce) { struct page *indirect_page; /* Fetch a pre-allocated page to use for indirect grefs */ @@ -705,7 +710,7 @@ static int blkif_queue_rw_req(struct req .grant_idx = 0, .segments = NULL, .rinfo = rinfo, - .need_copy = rq_data_dir(req) && info->feature_persistent, + .need_copy = rq_data_dir(req) && info->bounce, }; /* @@ -1026,11 +1031,12 @@ static void xlvbd_flush(struct blkfront_ { blk_queue_write_cache(info->rq, info->feature_flush ? true : false, info->feature_fua ? true : false); - pr_info("blkfront: %s: %s %s %s %s %s\n", + pr_info("blkfront: %s: %s %s %s %s %s %s %s\n", info->gd->disk_name, flush_info(info), "persistent grants:", info->feature_persistent ? "enabled;" : "disabled;", "indirect descriptors:", - info->max_indirect_segments ? "enabled;" : "disabled;"); + info->max_indirect_segments ? "enabled;" : "disabled;", + "bounce buffer:", info->bounce ? "enabled" : "disabled;"); } static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset) @@ -1265,7 +1271,7 @@ static void blkif_free_ring(struct blkfr if (!list_empty(&rinfo->indirect_pages)) { struct page *indirect_page, *n; - BUG_ON(info->feature_persistent); + BUG_ON(info->bounce); list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) { list_del(&indirect_page->lru); __free_page(indirect_page); @@ -1282,7 +1288,7 @@ static void blkif_free_ring(struct blkfr 0, 0UL); rinfo->persistent_gnts_c--; } - if (info->feature_persistent) + if (info->bounce) __free_page(persistent_gnt->page); kfree(persistent_gnt); } @@ -1303,7 +1309,7 @@ static void blkif_free_ring(struct blkfr for (j = 0; j < segs; j++) { persistent_gnt = rinfo->shadow[i].grants_used[j]; gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); - if (info->feature_persistent) + if (info->bounce) __free_page(persistent_gnt->page); kfree(persistent_gnt); } @@ -1493,7 +1499,7 @@ static int blkif_completion(unsigned lon data.s = s; num_sg = s->num_sg; - if (bret->operation == BLKIF_OP_READ && info->feature_persistent) { + if (bret->operation == BLKIF_OP_READ && info->bounce) { for_each_sg(s->sg, sg, num_sg, i) { BUG_ON(sg->offset + sg->length > PAGE_SIZE); @@ -1552,7 +1558,7 @@ static int blkif_completion(unsigned lon * Add the used indirect page back to the list of * available pages for indirect grefs. */ - if (!info->feature_persistent) { + if (!info->bounce) { indirect_page = s->indirect_grants[i]->page; list_add(&indirect_page->lru, &rinfo->indirect_pages); } @@ -1847,6 +1853,10 @@ static int talk_to_blkback(struct xenbus if (!info) return -ENODEV; + /* Check if backend is trusted. */ + info->bounce = !xen_blkif_trusted || + !xenbus_read_unsigned(dev->nodename, "trusted", 1); + max_page_order = xenbus_read_unsigned(info->xbdev->otherend, "max-ring-page-order", 0); ring_page_order = min(xen_blkif_max_ring_order, max_page_order); @@ -2273,10 +2283,10 @@ static int blkfront_setup_indirect(struc if (err) goto out_of_memory; - if (!info->feature_persistent && info->max_indirect_segments) { + if (!info->bounce && info->max_indirect_segments) { /* - * We are using indirect descriptors but not persistent - * grants, we need to allocate a set of pages that can be + * We are using indirect descriptors but don't have a bounce + * buffer, we need to allocate a set of pages that can be * used for mapping indirect grefs */ int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info); @@ -2376,6 +2386,8 @@ static void blkfront_gather_backend_feat info->feature_persistent = !!xenbus_read_unsigned(info->xbdev->otherend, "feature-persistent", 0); + if (info->feature_persistent) + info->bounce = true; indirect_segments = xenbus_read_unsigned(info->xbdev->otherend, "feature-max-indirect-segments", 0); @@ -2751,6 +2763,13 @@ static void blkfront_delay_work(struct w struct blkfront_info *info; bool need_schedule_work = false; + /* + * Note that when using bounce buffers but not persistent grants + * there's no need to run blkfront_delay_work because grants are + * revoked in blkif_completion or else an error is reported and the + * connection is closed. + */ + mutex_lock(&blkfront_mutex); list_for_each_entry(info, &info_list, info_list) {