From patchwork Fri Oct 27 18:22:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 13439112 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 95239C25B47 for ; Fri, 27 Oct 2023 19:32:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:Reply-To:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:Message-ID :References:Mime-Version:In-Reply-To:Date:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9n5p/wpB/7NRN+YVRyGHMa7x+q8+5zBeXA9u3uLUSjs=; b=GN0Pu54PqQyNeu sDkgMDX96tqyc2IQCsM/3Tk6Q015UyBROW5PwLWinAymkJzhQViu4/A6Nr4FAscZmC9SjTSyGNkX2 OwWPgzzan5mL9f6zRCes+mcwj76mgQqdlStWh/B9ShiTzAjGPniXrearrgBeQtV0EN0r/tRgvw5Xu mzfbxj5XQNMGO2QEzQvu6pUwMxhUnyJ6QcIw/eE+Mz65My0RK3gsJK/tkJjwDM7/cZOjDcSgfoEqc OOter1qmeT0WnMsjBbeM5rCyI73C8F1Wjg/buq+g9wm78n5Ioc9bpEkFDDAkTI8Z2q7X0XZbTQaWG /Pq+WowfTTtWnzEB7YyA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qwSZ3-00H6T9-2u; Fri, 27 Oct 2023 19:32:13 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qwRUe-00GxqA-2n for linux-riscv@bombadil.infradead.org; Fri, 27 Oct 2023 18:23:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Cc:To:From:Subject: Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To:Sender: Content-Transfer-Encoding:Content-ID:Content-Description; bh=sbbTeqIjFnESn/3c//KYIg/yBP25ARIIaxIo9NdR+Rs=; b=F5vmkJU9x6D8YqBcY2WMajQMzs 7BloCIYOoVIK6MJp433+EH/NKO1a7Saaztk2HEFbFgnZFNPjH4HH2y4MGq/wcVVaUSTw8l09PWlzt Zk9qNle5tOWjmSW8gpvYG5Y8XjvICA6lLaubTEoYAAVECNJuY3aH+SgffMEiWyqRxYkKH8VR2NHqM Q00CShLD4+1W7n4pQk5p5jAesFlHEsipTeOSMfg8ILTxMq0joQR5L+s/crwLZakagt1mTsfDbr4YD f3pKlJXOMCTFn1FeiE6E8Zb4ZCxCxD8QDs5g6Pclb+z2cKbGzRQhovbVPXlSq7ipvTJgiwyThR5Ae w3C8QSAw==; Received: from mail-yw1-x1149.google.com ([2607:f8b0:4864:20::1149]) by desiato.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qwRUb-000uu0-1G for linux-riscv@lists.infradead.org; Fri, 27 Oct 2023 18:23:35 +0000 Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5a7b9e83b70so22730597b3.0 for ; Fri, 27 Oct 2023 11:23:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698431011; x=1699035811; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=sbbTeqIjFnESn/3c//KYIg/yBP25ARIIaxIo9NdR+Rs=; b=dY4f2AbVovDPFJ4VmLYEsMSOBnRlFnWLl6SivaPZccGdI1rAH2RfjBmMdxFV/gW0sV ix1EtPmHGkuTYva+KABHCLijJcRNNdgzVr3SS/+dpbV15alf+IYCs4Ap3Bowg1CWi6WI SfcK0FjYXAJ1wpuGmwYkCRGiLS5IqBlrOWz7xNs155pwJgXOBKZ136o4t4OJ5/NcVTvJ 1tjVL2GINGk3hu34MIEc/zFGPAkcrzgL5nooMsW5IH9iTf2BkDlEPFm6FslNRRrjypst VL0b2DRt/eovzvSOMVxgncaUdzzym2iEZXSHS77DekxJ+cU2UwFfan+jqGbi/zsQuMzQ j1+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698431011; x=1699035811; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=sbbTeqIjFnESn/3c//KYIg/yBP25ARIIaxIo9NdR+Rs=; b=Q0EVCyo2k7gHRzmUyOd88EzWetB65ZZVGsU5dWktYbdzdnKOVCPoJI8+twUiFZcd/u 1wpB4PfSSBGYJFzMuJWMfSTnLoS6bLLnbOMm1FOffiGiPzBR+Ii/tRAyeim56jGKaTRD JzD8EhhaAOIFIVGzueA+XrscEzBEVrdKHySZsYtIPujiVXy8YaWAAVEAeYzIu/rzXn0n KAPMlcCQw6fFiZfCtr9kI0ugdU1uv+5Qgw2kt72ZF//+cYriwZ9+3vj0BZPrLNf4Ysz0 RlvQkPDkyZethfPr92/VM89BPCu92TF2UM7bKuQhDE+E0Fi0aqtCR49kJfeTy1VS6PHL UXuw== X-Gm-Message-State: AOJu0YzpYtu7g2LcT/XNY0wLINpqBjVzvtu01sFRte9LmBhCi4O/QBb5 /19od88W7nV3xYlqF1rFyucAGfdNv0Q= X-Google-Smtp-Source: AGHT+IHBWIjPxzRJgKiud97ZCtykjvc4+klLDW+Sn0Y068ZaDLScSJEVBpBXvLWKn1zDVFylTXJJKJ/wubw= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a0d:ca0f:0:b0:59b:e663:23b0 with SMTP id m15-20020a0dca0f000000b0059be66323b0mr102894ywd.4.1698431011148; Fri, 27 Oct 2023 11:23:31 -0700 (PDT) Date: Fri, 27 Oct 2023 11:22:15 -0700 In-Reply-To: <20231027182217.3615211-1-seanjc@google.com> Mime-Version: 1.0 References: <20231027182217.3615211-1-seanjc@google.com> X-Mailer: git-send-email 2.42.0.820.g83a721a137-goog Message-ID: <20231027182217.3615211-34-seanjc@google.com> Subject: [PATCH v13 33/35] KVM: selftests: Expand set_memory_region_test to validate guest_memfd() From: Sean Christopherson To: Paolo Bonzini , Marc Zyngier , Oliver Upton , Huacai Chen , Michael Ellerman , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Sean Christopherson , Alexander Viro , Christian Brauner , "Matthew Wilcox (Oracle)" , Andrew Morton Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-mips@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Xiaoyao Li , Xu Yilun , Chao Peng , Fuad Tabba , Jarkko Sakkinen , Anish Moorthy , David Matlack , Yu Zhang , Isaku Yamahata , " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " , Vlastimil Babka , Vishal Annapurve , Ackerley Tng , Maciej Szmigiero , David Hildenbrand , Quentin Perret , Michael Roth , Wang , Liam Merwick , Isaku Yamahata , "Kirill A . Shutemov" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231027_192333_657160_AF71FE5C X-CRM114-Status: GOOD ( 14.33 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Sean Christopherson Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org From: Chao Peng Expand set_memory_region_test to exercise various positive and negative testcases for private memory. - Non-guest_memfd() file descriptor for private memory - guest_memfd() from different VM - Overlapping bindings - Unaligned bindings Signed-off-by: Chao Peng Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng [sean: trim the testcases to remove duplicate coverage] Signed-off-by: Sean Christopherson --- .../selftests/kvm/include/kvm_util_base.h | 10 ++ .../selftests/kvm/set_memory_region_test.c | 100 ++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 8ec122f5fcc8..e4d2cd9218b2 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -819,6 +819,16 @@ static inline struct kvm_vm *vm_create_barebones(void) return ____vm_create(VM_SHAPE_DEFAULT); } +static inline struct kvm_vm *vm_create_barebones_protected_vm(void) +{ + const struct vm_shape shape = { + .mode = VM_MODE_DEFAULT, + .type = KVM_X86_SW_PROTECTED_VM, + }; + + return ____vm_create(shape); +} + static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus) { return __vm_create(VM_SHAPE_DEFAULT, nr_runnable_vcpus, 0); diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c index b32960189f5f..ca83e3307a98 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -385,6 +385,98 @@ static void test_add_max_memory_regions(void) kvm_vm_free(vm); } + +static void test_invalid_guest_memfd(struct kvm_vm *vm, int memfd, + size_t offset, const char *msg) +{ + int r = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA, MEM_REGION_SIZE, + 0, memfd, offset); + TEST_ASSERT(r == -1 && errno == EINVAL, "%s", msg); +} + +static void test_add_private_memory_region(void) +{ + struct kvm_vm *vm, *vm2; + int memfd, i; + + pr_info("Testing ADD of KVM_MEM_PRIVATE memory regions\n"); + + vm = vm_create_barebones_protected_vm(); + + test_invalid_guest_memfd(vm, vm->kvm_fd, 0, "KVM fd should fail"); + test_invalid_guest_memfd(vm, vm->fd, 0, "VM's fd should fail"); + + memfd = kvm_memfd_alloc(MEM_REGION_SIZE, false); + test_invalid_guest_memfd(vm, memfd, 0, "Regular memfd() should fail"); + close(memfd); + + vm2 = vm_create_barebones_protected_vm(); + memfd = vm_create_guest_memfd(vm2, MEM_REGION_SIZE, 0); + test_invalid_guest_memfd(vm, memfd, 0, "Other VM's guest_memfd() should fail"); + + vm_set_user_memory_region2(vm2, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA, MEM_REGION_SIZE, 0, memfd, 0); + close(memfd); + kvm_vm_free(vm2); + + memfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE, 0); + for (i = 1; i < PAGE_SIZE; i++) + test_invalid_guest_memfd(vm, memfd, i, "Unaligned offset should fail"); + + vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA, MEM_REGION_SIZE, 0, memfd, 0); + close(memfd); + + kvm_vm_free(vm); +} + +static void test_add_overlapping_private_memory_regions(void) +{ + struct kvm_vm *vm; + int memfd; + int r; + + pr_info("Testing ADD of overlapping KVM_MEM_PRIVATE memory regions\n"); + + vm = vm_create_barebones_protected_vm(); + + memfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE * 4, 0); + + vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA, MEM_REGION_SIZE * 2, 0, memfd, 0); + + vm_set_user_memory_region2(vm, MEM_REGION_SLOT + 1, KVM_MEM_PRIVATE, + MEM_REGION_GPA * 2, MEM_REGION_SIZE * 2, + 0, memfd, MEM_REGION_SIZE * 2); + + /* + * Delete the first memslot, and then attempt to recreate it except + * with a "bad" offset that results in overlap in the guest_memfd(). + */ + vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA, 0, NULL, -1, 0); + + /* Overlap the front half of the other slot. */ + r = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA * 2 - MEM_REGION_SIZE, + MEM_REGION_SIZE * 2, + 0, memfd, 0); + TEST_ASSERT(r == -1 && errno == EEXIST, "%s", + "Overlapping guest_memfd() bindings should fail with EEXIST"); + + /* And now the back half of the other slot. */ + r = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_PRIVATE, + MEM_REGION_GPA * 2 + MEM_REGION_SIZE, + MEM_REGION_SIZE * 2, + 0, memfd, 0); + TEST_ASSERT(r == -1 && errno == EEXIST, "%s", + "Overlapping guest_memfd() bindings should fail with EEXIST"); + + close(memfd); + kvm_vm_free(vm); +} + int main(int argc, char *argv[]) { #ifdef __x86_64__ @@ -401,6 +493,14 @@ int main(int argc, char *argv[]) test_add_max_memory_regions(); + if (kvm_has_cap(KVM_CAP_GUEST_MEMFD) && + (kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM))) { + test_add_private_memory_region(); + test_add_overlapping_private_memory_regions(); + } else { + pr_info("Skipping tests for KVM_MEM_PRIVATE memory regions\n"); + } + #ifdef __x86_64__ if (argc > 1) loops = atoi_positive("Number of iterations", argv[1]);