Received: by 10.192.165.148 with SMTP id m20csp4143662imm; Mon, 30 Apr 2018 12:34:17 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpWmsTIap2uGiGuU/hJIKmnxDmm5HLxIyMFs/ruaRnoRa0hWM5Ws9cMq78E4qk+a4KMF8gx X-Received: by 2002:a17:902:5a88:: with SMTP id r8-v6mr13653692pli.78.1525116857877; Mon, 30 Apr 2018 12:34:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525116857; cv=none; d=google.com; s=arc-20160816; b=EzkoF9/gh5mYc3W6AY3F+11LLhb4cNI9aYoL21nnAgw/OWNGxAT3/12ODA+zSKnVFp CQcgfW84GFfm0vwTfolVbXXS4H2uHcmj7V81crSudgBgjzfhhMT94NUTTsCdvsVdqZCM VQ4GqdTbT3SkWhmqqmha96y3epR7Ygv8EMZn7HpfWIy7eIwuAL2NWEPnXG6VUaQBNa1q FADDLcjIsnwtpYy4Rz7tDJr2Vz4UG+maYgndzGJ9aSIJi2HwHwr5PK30x5Mlu6Rj872y OsCyomZqUSfkbTl6th5eOFO4lZAI0Bz/xpA0w+Hf8b0Xp1ays2UDK7EE31LpBJemuOqr qZ7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dmarc-filter :arc-authentication-results; bh=AI02XonvfkK+fF5r5lW7sRBRc6O3OUxhm9flUhSoDpU=; b=S8b3WRZry8RDMKKczq3E4XO7kSI4DCyC6hmHQa/FdMibHLPW/O4Pp1WHnr8AfEv7/E RKutpPodUJmG9MdmvXnduGlLVIQ9UwdRTwMsVxXyX5+z/CnMlSLKzSgCX/w0tpmxsxG8 qGEf1Rv0W1mDXr9EwMJY4hilUlS51FcTXV82Wqc/MsMfV/Kpx7L2wpxAD46VONyYfHjy MBBUBIG1wLzu4mvzUPf3s2pG5GPgND3oR8179OtCxM7WT7Wz1DWgsnFNmbr5+WJU3dco 1wxI+oykfp02c9Hfs6tNZdkeQOfN/cHIDJlhbqAPQyyV6PBQV7nyBilsHjfO0vrPCVm3 dapw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l67si8039476pfg.326.2018.04.30.12.34.03; Mon, 30 Apr 2018 12:34:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932472AbeD3TdJ (ORCPT + 99 others); Mon, 30 Apr 2018 15:33:09 -0400 Received: from mail.kernel.org ([198.145.29.99]:37330 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756441AbeD3T25 (ORCPT ); Mon, 30 Apr 2018 15:28:57 -0400 Received: from localhost (unknown [104.132.1.102]) (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 5867922DCB; Mon, 30 Apr 2018 19:28:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5867922DCB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=linuxfoundation.org Authentication-Results: mail.kernel.org; spf=fail smtp.mailfrom=gregkh@linuxfoundation.org From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mark Rutland , Shannon Zhao , Marc Zyngier Subject: [PATCH 4.16 078/113] KVM: arm/arm64: Close VMID generation race Date: Mon, 30 Apr 2018 12:24:49 -0700 Message-Id: <20180430184018.481197643@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180430184015.043892819@linuxfoundation.org> References: <20180430184015.043892819@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Marc Zyngier commit f0cf47d939d0b4b4f660c5aaa4276fa3488f3391 upstream. Before entering the guest, we check whether our VMID is still part of the current generation. In order to avoid taking a lock, we start with checking that the generation is still current, and only if not current do we take the lock, recheck, and update the generation and VMID. This leaves open a small race: A vcpu can bump up the global generation number as well as the VM's, but has not updated the VMID itself yet. At that point another vcpu from the same VM comes in, checks the generation (and finds it not needing anything), and jumps into the guest. At this point, we end-up with two vcpus belonging to the same VM running with two different VMIDs. Eventually, the VMID used by the second vcpu will get reassigned, and things will really go wrong... A simple solution would be to drop this initial check, and always take the lock. This is likely to cause performance issues. A middle ground is to convert the spinlock to a rwlock, and only take the read lock on the fast path. If the check fails at that point, drop it and acquire the write lock, rechecking the condition. This ensures that the above scenario doesn't occur. Cc: stable@vger.kernel.org Reported-by: Mark Rutland Tested-by: Shannon Zhao Signed-off-by: Marc Zyngier Signed-off-by: Greg Kroah-Hartman --- virt/kvm/arm/arm.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); static u32 kvm_next_vmid; static unsigned int kvm_vmid_bits __read_mostly; -static DEFINE_SPINLOCK(kvm_vmid_lock); +static DEFINE_RWLOCK(kvm_vmid_lock); static bool vgic_present; @@ -470,11 +470,16 @@ static void update_vttbr(struct kvm *kvm { phys_addr_t pgd_phys; u64 vmid; + bool new_gen; - if (!need_new_vmid_gen(kvm)) + read_lock(&kvm_vmid_lock); + new_gen = need_new_vmid_gen(kvm); + read_unlock(&kvm_vmid_lock); + + if (!new_gen) return; - spin_lock(&kvm_vmid_lock); + write_lock(&kvm_vmid_lock); /* * We need to re-check the vmid_gen here to ensure that if another vcpu @@ -482,7 +487,7 @@ static void update_vttbr(struct kvm *kvm * use the same vmid. */ if (!need_new_vmid_gen(kvm)) { - spin_unlock(&kvm_vmid_lock); + write_unlock(&kvm_vmid_lock); return; } @@ -516,7 +521,7 @@ static void update_vttbr(struct kvm *kvm vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid; - spin_unlock(&kvm_vmid_lock); + write_unlock(&kvm_vmid_lock); } static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)