Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp1792435pxp; Mon, 7 Mar 2022 02:26:22 -0800 (PST) X-Google-Smtp-Source: ABdhPJyrqZOon6okbimTX5qGDXL/JhT6JtjqJDzBCkRDKIkfLY1c/0ElUBsJR1AHneUaIQFUM/QB X-Received: by 2002:a17:90a:20a:b0:1be:e850:1a37 with SMTP id c10-20020a17090a020a00b001bee8501a37mr24293990pjc.28.1646648782275; Mon, 07 Mar 2022 02:26:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646648782; cv=none; d=google.com; s=arc-20160816; b=s986pCbn7bWCWcmeVdJslBM6ebLgAQLFmmBoMJvqWVgnsSdTUehvHpPa0PXzSGb4Bx wDf84WfrEY+HaI9iV8YPg+/jyxONIsmP62zkAqmTyuc7J17xJq3N7FV6vVQdimLckPj0 0kx9XP7poz/8w2l+9Ch36zWVY9Dwc4TL1LLcJmmYnH3DDfkfDq2kYJlNjhDuKqvtQx9k G8hrZEF+3/FmRdnMAu5ktjRp2bOkBVhfCVtpErWc1zhrtQxU71IkExdHYVc8ZsmK0U7a q/ybgA63WSGUs8htRBQu7cMFAiHOERYOIvxMfngy1Dya2Mg77nPwpV+kgWutW1Hq1dii vMeA== 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=MlTBX17eiPkvfQ2HLE8X6tFQ4Y1sE+Mc3X2V2rh+JRA=; b=U40pHe7/icsSGBFgDCSogvfoVGUTsn663ErycsSoE87E0z19chYWzFAVuWXoYYP63s 5KgMUHMLMNxVFrutS5yur2nCJhvQQw9DgagLMy+FpuO4ieahB1flfasxnwm4gui94NpW Et4DSrVy5t0z3un0NW99C+Wwl1D9iac7nGpMgdVY9cfqTEx32HgdoONvhliuIoqFZYD1 XhnEU0FSEDWoKPXQFrQJw2BiHvcfrx38I+UZVfndE84N81PJCnwohYepFCwPmQMB4jDf HPWMUgRoLFatTJ6uWniLNvUsRVJQcdrWsZBm5ZkFxY1jVc6mCHqy+bwcSRRJhLnZmPZz D2VA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=S+MYAYI+; 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 c7-20020a654207000000b00378ef4d76f4si12092752pgq.492.2022.03.07.02.26.08; Mon, 07 Mar 2022 02:26:22 -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=S+MYAYI+; 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 S238911AbiCGKCt (ORCPT + 99 others); Mon, 7 Mar 2022 05:02:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240957AbiCGJlm (ORCPT ); Mon, 7 Mar 2022 04:41:42 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 397B96CA4C; Mon, 7 Mar 2022 01:38:47 -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 CEA9AB810BD; Mon, 7 Mar 2022 09:38:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3DB86C340F3; Mon, 7 Mar 2022 09:38:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1646645925; bh=ifDCbOlvlfDMlQSljIfCesPKWuSzZT3V2906vyaUncs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S+MYAYI+/zPJ55gjXUZVxKKrOrsipUSMFQacs9b7mbhDyHs/LRqSmF687m+zkHAzP EU5gtox9U3PaPpBy/0NLo/NA3uT6Nb97MIbe3v8uae5AEwnng5U4g4EuCZPvp8AU9i h0dYbPF+Ae0kDOltf60Tp2ObqUdD74msROTmh4uA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Vitaly Kuznetsov , Michael Kelley , Wei Liu , Sasha Levin Subject: [PATCH 5.15 078/262] x86/hyperv: Properly deal with empty cpumasks in hyperv_flush_tlb_multi() Date: Mon, 7 Mar 2022 10:17:02 +0100 Message-Id: <20220307091704.692711717@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220307091702.378509770@linuxfoundation.org> References: <20220307091702.378509770@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: Vitaly Kuznetsov [ Upstream commit 51500b71d500f251037ed339047a4d9e7d7e295b ] KASAN detected the following issue: BUG: KASAN: slab-out-of-bounds in hyperv_flush_tlb_multi+0xf88/0x1060 Read of size 4 at addr ffff8880011ccbc0 by task kcompactd0/33 CPU: 1 PID: 33 Comm: kcompactd0 Not tainted 5.14.0-39.el9.x86_64+debug #1 Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.0 12/17/2019 Call Trace: dump_stack_lvl+0x57/0x7d print_address_description.constprop.0+0x1f/0x140 ? hyperv_flush_tlb_multi+0xf88/0x1060 __kasan_report.cold+0x7f/0x11e ? hyperv_flush_tlb_multi+0xf88/0x1060 kasan_report+0x38/0x50 hyperv_flush_tlb_multi+0xf88/0x1060 flush_tlb_mm_range+0x1b1/0x200 ptep_clear_flush+0x10e/0x150 ... Allocated by task 0: kasan_save_stack+0x1b/0x40 __kasan_kmalloc+0x7c/0x90 hv_common_init+0xae/0x115 hyperv_init+0x97/0x501 apic_intr_mode_init+0xb3/0x1e0 x86_late_time_init+0x92/0xa2 start_kernel+0x338/0x3eb secondary_startup_64_no_verify+0xc2/0xcb The buggy address belongs to the object at ffff8880011cc800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 960 bytes inside of 1024-byte region [ffff8880011cc800, ffff8880011ccc00) 'hyperv_flush_tlb_multi+0xf88/0x1060' points to hv_cpu_number_to_vp_number() and '960 bytes' means we're trying to get VP_INDEX for CPU#240. 'nr_cpus' here is exactly 240 so we're trying to access past hv_vp_index's last element. This can (and will) happen when 'cpus' mask is empty and cpumask_last() will return '>=nr_cpus'. Commit ad0a6bad4475 ("x86/hyperv: check cpu mask after interrupt has been disabled") tried to deal with empty cpumask situation but apparently didn't fully fix the issue. 'cpus' cpumask which is passed to hyperv_flush_tlb_multi() is 'mm_cpumask(mm)' (which is '&mm->cpu_bitmap'). This mask changes every time the particular mm is scheduled/unscheduled on some CPU (see switch_mm_irqs_off()), disabling IRQs on the CPU which is performing remote TLB flush has zero influence on whether the particular process can get scheduled/unscheduled on _other_ CPUs so e.g. in the case where the mm was scheduled on one other CPU and got unscheduled during hyperv_flush_tlb_multi()'s execution will lead to cpumask becoming empty. It doesn't seem that there's a good way to protect 'mm_cpumask(mm)' from changing during hyperv_flush_tlb_multi()'s execution. It would be possible to copy it in the very beginning of the function but this is a waste. It seems we can deal with changing cpumask just fine. When 'cpus' cpumask changes during hyperv_flush_tlb_multi()'s execution, there are two possible issues: - 'Under-flushing': we will not flush TLB on a CPU which got added to the mask while hyperv_flush_tlb_multi() was already running. This is not a problem as this is equal to mm getting scheduled on that CPU right after TLB flush. - 'Over-flushing': we may flush TLB on a CPU which is already cleared from the mask. First, extra TLB flush preserves correctness. Second, Hyper-V's TLB flush hypercall takes 'mm->pgd' argument so Hyper-V may avoid the flush if CR3 doesn't match. Fix the immediate issue with cpumask_last()/hv_cpu_number_to_vp_number() and remove the pointless cpumask_empty() check from the beginning of the function as it really doesn't protect anything. Also, avoid the hypercall altogether when 'flush->processor_mask' ends up being empty. Fixes: ad0a6bad4475 ("x86/hyperv: check cpu mask after interrupt has been disabled") Signed-off-by: Vitaly Kuznetsov Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20220106094611.1404218-1-vkuznets@redhat.com Signed-off-by: Wei Liu Signed-off-by: Sasha Levin --- arch/x86/hyperv/mmu.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index bd13736d0c054..0ad2378fe6ad7 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -68,15 +68,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, local_irq_save(flags); - /* - * Only check the mask _after_ interrupt has been disabled to avoid the - * mask changing under our feet. - */ - if (cpumask_empty(cpus)) { - local_irq_restore(flags); - return; - } - flush_pcpu = (struct hv_tlb_flush **) this_cpu_ptr(hyperv_pcpu_input_arg); @@ -115,7 +106,9 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, * must. We will also check all VP numbers when walking the * supplied CPU set to remain correct in all cases. */ - if (hv_cpu_number_to_vp_number(cpumask_last(cpus)) >= 64) + cpu = cpumask_last(cpus); + + if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64) goto do_ex_hypercall; for_each_cpu(cpu, cpus) { @@ -131,6 +124,12 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, __set_bit(vcpu, (unsigned long *) &flush->processor_mask); } + + /* nothing to flush if 'processor_mask' ends up being empty */ + if (!flush->processor_mask) { + local_irq_restore(flags); + return; + } } /* -- 2.34.1