From patchwork Thu May 25 18:33:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Luczaj X-Patchwork-Id: 13255586 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94479C7EE2F for ; Thu, 25 May 2023 18:36:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241970AbjEYSgT (ORCPT ); Thu, 25 May 2023 14:36:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241624AbjEYSfq (ORCPT ); Thu, 25 May 2023 14:35:46 -0400 Received: from mailtransmit04.runbox.com (mailtransmit04.runbox.com [IPv6:2a0c:5a00:149::25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A04CCE78 for ; Thu, 25 May 2023 11:34:24 -0700 (PDT) Received: from mailtransmit03.runbox ([10.9.9.163] helo=aibo.runbox.com) by mailtransmit04.runbox.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1q2Fmy-004iLE-Qh for kvm@vger.kernel.org; Thu, 25 May 2023 20:34:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rbox.co; s=selector2; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From; bh=0vM1SwvWLRynRevPA8p5AXkpK9F/ciBF2F4nAf4lNug=; b=qVdI6R8Yyb9VarnAxI1q6DLjz0 Mnlfky4iJAs3rb0M3Bvkxv00vBMVKxkaIiV/46qCloMOdboiK5AIP38LvDHzhL+r47ueiIaYo3vUl VL/Q3Up5gaqbTp6lJucIQQXNvLFg7ULjrgcgFwKKgfztf1FncHBqYE4n3IJFLjy3lI7DUuNLHMTz9 7IJQFxIpGMsBJ2ltnkMSaKaDRqWiLOowgq+1dO3p+tOq7H39bPYbYZke4Wd4J7WVXPi6iOioaBET+ w6BgnbCens01+Q/vkIKM1xXKqGU0UC4Ef5UQIgVL164RKNCV6GuJOB3dIi3eAEz29B3R8LGiGI01f 4qV+mrPg==; Received: from [10.9.9.73] (helo=submission02.runbox) by mailtransmit03.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1q2Fmy-0008Mf-Fc; Thu, 25 May 2023 20:34:16 +0200 Received: by submission02.runbox with esmtpsa [Authenticated ID (604044)] (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) id 1q2Fms-00047d-8E; Thu, 25 May 2023 20:34:10 +0200 From: Michal Luczaj To: seanjc@google.com Cc: pbonzini@redhat.com, shuah@kernel.org, kvm@vger.kernel.org, Michal Luczaj Subject: [PATCH 1/3] KVM: x86: Fix out-of-bounds access in kvm_recalculate_phys_map() Date: Thu, 25 May 2023 20:33:45 +0200 Message-Id: <20230525183347.2562472-2-mhal@rbox.co> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230525183347.2562472-1-mhal@rbox.co> References: <20230525183347.2562472-1-mhal@rbox.co> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Handle the case of vCPU addition and/or APIC enabling during the APIC map recalculations. Check the sanity of x2APIC ID in !x2apic_format && apic_x2apic_mode() case. kvm_recalculate_apic_map() creates the APIC map iterating over the list of vCPUs twice. First to find the max APIC ID and allocate a max-sized buffer, then again, calling kvm_recalculate_phys_map() for each vCPU. This opens a race window: value of max APIC ID can increase _after_ the buffer was allocated. Signed-off-by: Michal Luczaj --- arch/x86/kvm/lapic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index e542cf285b51..39b9a318d04c 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -265,10 +265,14 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, * mapped, i.e. is aliased to multiple vCPUs. The optimized * map requires a strict 1:1 mapping between IDs and vCPUs. */ - if (apic_x2apic_mode(apic)) + if (apic_x2apic_mode(apic)) { + if (x2apic_id > new->max_apic_id) + return -EINVAL; + physical_id = x2apic_id; - else + } else { physical_id = xapic_id; + } if (new->phys_map[physical_id]) return -EINVAL; From patchwork Thu May 25 18:33:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Luczaj X-Patchwork-Id: 13255584 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDC89C7EE29 for ; Thu, 25 May 2023 18:36:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241946AbjEYSgQ (ORCPT ); Thu, 25 May 2023 14:36:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241810AbjEYSfx (ORCPT ); Thu, 25 May 2023 14:35:53 -0400 Received: from mailtransmit04.runbox.com (mailtransmit04.runbox.com [IPv6:2a0c:5a00:149::25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64F1D10C4 for ; Thu, 25 May 2023 11:34:27 -0700 (PDT) Received: from mailtransmit02.runbox ([10.9.9.162] helo=aibo.runbox.com) by mailtransmit04.runbox.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1q2Fn0-004iLI-8V; Thu, 25 May 2023 20:34:18 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rbox.co; s=selector2; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From; bh=SHVweY2CMvk4sKOQvJToUzCaBD8mHXCN5HSp1yN28lA=; b=GQO/qQfr9w6bb/U4m7DkZY6OCX GLit98z+mS1vAeW7VI+xjFhfkfo3RAX8+QNw0ZVh8RLEygcHR6q4QoQW6z/uTUsctZGLH+jzMUo/O 45RuOEybBiUy6UFBV73BB0XeDG1jvl6HOtkqEDuwLnOHZvbGKMgQ4ZHAmParYXb5ISlhxY8fq8xkt Ap2HjkgpzctSqMqRjoq8hN+1PyDNUVOWT6YpWxFC8wJi+Q1tfj2PXIwPq9AvbPa808lArLxmiPlxr /lYe6mREJD+mo0eSt4sdLlz46F8OlT/0gb45IYvUJH3wEzaJUihXv8WNQXgETS/xsN1U9fxja6I/w 1NkKcHIg==; Received: from [10.9.9.73] (helo=submission02.runbox) by mailtransmit02.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1q2Fmz-0006XF-EP; Thu, 25 May 2023 20:34:17 +0200 Received: by submission02.runbox with esmtpsa [Authenticated ID (604044)] (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) id 1q2Fms-00047d-KJ; Thu, 25 May 2023 20:34:10 +0200 From: Michal Luczaj To: seanjc@google.com Cc: pbonzini@redhat.com, shuah@kernel.org, kvm@vger.kernel.org, Michal Luczaj Subject: [PATCH 2/3] KVM: x86: Simplify APIC ID selection in kvm_recalculate_phys_map() Date: Thu, 25 May 2023 20:33:46 +0200 Message-Id: <20230525183347.2562472-3-mhal@rbox.co> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230525183347.2562472-1-mhal@rbox.co> References: <20230525183347.2562472-1-mhal@rbox.co> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move the comments and condense the code. No functional change intended. Signed-off-by: Michal Luczaj --- Perhaps, as it was suggested by Maxim in [1], it would be a good moment to change kvm_recalculate_phys_map() to return bool? https://lore.kernel.org/kvm/e90e4c4bd558b9e41acea9f8ce84783e7341c9b4.camel@redhat.com/ arch/x86/kvm/lapic.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 39b9a318d04c..7db1c698f6da 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -223,10 +223,10 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, struct kvm_vcpu *vcpu, bool *xapic_id_mismatch) { + bool x2format = vcpu->kvm->arch.x2apic_format; struct kvm_lapic *apic = vcpu->arch.apic; u32 x2apic_id = kvm_x2apic_id(apic); u32 xapic_id = kvm_xapic_id(apic); - u32 physical_id; /* * Deliberately truncate the vCPU ID when detecting a mismatched APIC @@ -250,34 +250,24 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, * effective APIC ID, e.g. due to the x2APIC wrap or because the guest * manually modified its xAPIC IDs, events targeting that ID are * supposed to be recognized by all vCPUs with said ID. + * + * For !x2apic_format disable the optimized map if the physical APIC ID + * is already mapped, i.e. is aliased to multiple vCPUs. The optimized + * map requires a strict 1:1 mapping between IDs and vCPUs. + * + * See also kvm_apic_match_physical_addr(). */ - if (vcpu->kvm->arch.x2apic_format) { - /* See also kvm_apic_match_physical_addr(). */ - if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) && - x2apic_id <= new->max_apic_id) - new->phys_map[x2apic_id] = apic; - - if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id]) - new->phys_map[xapic_id] = apic; - } else { - /* - * Disable the optimized map if the physical APIC ID is already - * mapped, i.e. is aliased to multiple vCPUs. The optimized - * map requires a strict 1:1 mapping between IDs and vCPUs. - */ - if (apic_x2apic_mode(apic)) { - if (x2apic_id > new->max_apic_id) - return -EINVAL; + if (apic_x2apic_mode(apic) || (x2format && x2apic_id > 0xff)) { + if (x2apic_id > new->max_apic_id || + (!x2format && new->phys_map[x2apic_id])) + return !x2format; - physical_id = x2apic_id; - } else { - physical_id = xapic_id; - } - - if (new->phys_map[physical_id]) - return -EINVAL; + new->phys_map[x2apic_id] = apic; + } else { + if (new->phys_map[xapic_id]) + return !x2format; - new->phys_map[physical_id] = apic; + new->phys_map[xapic_id] = apic; } return 0; From patchwork Thu May 25 18:33:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Luczaj X-Patchwork-Id: 13255585 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9687CC7EE39 for ; Thu, 25 May 2023 18:36:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241961AbjEYSgS (ORCPT ); Thu, 25 May 2023 14:36:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241589AbjEYSfq (ORCPT ); Thu, 25 May 2023 14:35:46 -0400 Received: from mailtransmit05.runbox.com (mailtransmit05.runbox.com [IPv6:2a0c:5a00:149::26]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09B79E76 for ; Thu, 25 May 2023 11:34:23 -0700 (PDT) Received: from mailtransmit02.runbox ([10.9.9.162] helo=aibo.runbox.com) by mailtransmit05.runbox.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1q2Fmw-004VoD-IY; Thu, 25 May 2023 20:34:14 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rbox.co; s=selector2; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From; bh=vLvuHd+LAzIp2cUd2mozqN1y+pv5oHvYy+vbJE1B37o=; b=AJtJL/eKUCoy+JWWt7oeB7BQNO q6NRctL9gk2GrL+mtG5db4l0XxfeJz0wJFfCfKpjWlRtNtsp82zwiKV2FXqTi/pOR6uAvoJc86okJ NLdB2XbVvYF04EscpfoJs5ldQjgNjy0p9MUkvoSdLKcbu1XDBRXtWhYYDcX4S+bVMBvSxbT7jY31N uqalR27idH7YgHZiMpUwjZfC1+g6Q0fMaG1hLy8XhD6iZLsbzj2KSi+TiSb6LpK2rmv2Rth2gPYVd B6BdnoRz2IgCW/cQcyAvRbv0e+KgJgB9vtiLmg/7QlVeC6wsSoy0j4hYDdg2l6VjHMRuTu15+wBfn gNBgKqEA==; Received: from [10.9.9.73] (helo=submission02.runbox) by mailtransmit02.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1q2Fmv-0006W2-O7; Thu, 25 May 2023 20:34:14 +0200 Received: by submission02.runbox with esmtpsa [Authenticated ID (604044)] (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) id 1q2Fmt-00047d-0l; Thu, 25 May 2023 20:34:11 +0200 From: Michal Luczaj To: seanjc@google.com Cc: pbonzini@redhat.com, shuah@kernel.org, kvm@vger.kernel.org, Michal Luczaj Subject: [PATCH 3/3] KVM: selftests: Add test for race in kvm_recalculate_apic_map() Date: Thu, 25 May 2023 20:33:47 +0200 Message-Id: <20230525183347.2562472-4-mhal@rbox.co> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230525183347.2562472-1-mhal@rbox.co> References: <20230525183347.2562472-1-mhal@rbox.co> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Keep switching between LAPIC_MODE_X2APIC and LAPIC_MODE_DISABLED during APIC map construction. Signed-off-by: Michal Luczaj --- tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/recalc_apic_map_race.c | 110 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/recalc_apic_map_race.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 7a5ff646e7e7..c9b8f16fb23f 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -116,6 +116,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/sev_migrate_tests TEST_GEN_PROGS_x86_64 += x86_64/amx_test TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test +TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_race TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_race.c b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_race.c new file mode 100644 index 000000000000..1122df858623 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_race.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * recalc_apic_map_race + * + * Test for a race condition in kvm_recalculate_apic_map(). + */ + +#include +#include +#include + +#include "processor.h" +#include "test_util.h" +#include "kvm_util.h" +#include "apic.h" + +#define TIMEOUT 5 /* seconds */ +#define STUFFING 100 + +#define LAPIC_MODE_DISABLED 0 +#define LAPIC_MODE_X2APIC (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) +#define MAX_XAPIC_ID 0xff + +static int add_vcpu(struct kvm_vm *vm, long id) +{ + int vcpu = __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)id); + + static struct { + struct kvm_cpuid2 head; + struct kvm_cpuid_entry2 entry; + } cpuid = { + .head.nent = 1, + /* X86_FEATURE_X2APIC */ + .entry = { + .function = 0x1, + .index = 0, + .ecx = 1UL << 21 + } + }; + + ASSERT_EQ(ioctl(vcpu, KVM_SET_CPUID2, &cpuid.head), 0); + + return vcpu; +} + +static void set_apicbase(int vcpu, u64 mode) +{ + struct { + struct kvm_msrs head; + struct kvm_msr_entry entry; + } msr = { + .head.nmsrs = 1, + .entry = { + .index = MSR_IA32_APICBASE, + .data = mode + } + }; + + ASSERT_EQ(ioctl(vcpu, KVM_SET_MSRS, &msr.head), msr.head.nmsrs); +} + +static void *race(void *arg) +{ + struct kvm_lapic_state state = {}; + int vcpu = *(int *)arg; + + while (1) { + /* Trigger kvm_recalculate_apic_map(). */ + ioctl(vcpu, KVM_SET_LAPIC, &state); + pthread_testcancel(); + } + + return NULL; +} + +int main(void) +{ + int vcpu0, vcpuN, i; + struct kvm_vm *vm; + pthread_t thread; + time_t t; + + vm = vm_create_barebones(); + vm_create_irqchip(vm); + + vcpu0 = add_vcpu(vm, 0); + vcpuN = add_vcpu(vm, KVM_MAX_VCPUS); + + static_assert(MAX_XAPIC_ID + STUFFING < KVM_MAX_VCPUS); + for (i = 0; i < STUFFING; ++i) + close(add_vcpu(vm, MAX_XAPIC_ID + i)); + + ASSERT_EQ(pthread_create(&thread, NULL, race, &vcpu0), 0); + + pr_info("Testing recalc_apic_map_race...\n"); + + for (t = time(NULL) + TIMEOUT; time(NULL) < t;) { + set_apicbase(vcpuN, LAPIC_MODE_X2APIC); + set_apicbase(vcpuN, LAPIC_MODE_DISABLED); + } + + ASSERT_EQ(pthread_cancel(thread), 0); + ASSERT_EQ(pthread_join(thread, NULL), 0); + + close(vcpu0); + close(vcpuN); + kvm_vm_release(vm); + + return 0; +}