diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-28 15:58:19 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-28 15:58:19 +0000 |
commit | 4bcfa6dbf4bef29dd16183320eea536482e0121a (patch) | |
tree | df1ccb26decb5dd8062ef10828afbe499f3fe3b6 | |
parent | e0d15089783c9eb5e6e46f90781df82386bb4be1 (diff) | |
parent | e9ebf262fc0229aefd9f2366fba8870c2b17fdf5 (diff) | |
download | linux-kselftest-android13-frc-resolv-release.tar.gz |
Snap for 8512216 from e9ebf262fc0229aefd9f2366fba8870c2b17fdf5 to tm-frc-resolv-releaset_frc_res_330443000android13-frc-resolv-release
Change-Id: I8b5408e73f0ec944c35c4bde65d8bfce58f6e91d
8 files changed, 475 insertions, 95 deletions
diff --git a/Android.bp b/Android.bp index 0b9166c56315..e9e4d049591a 100644 --- a/Android.bp +++ b/Android.bp @@ -76,7 +76,6 @@ cc_defaults { "-Wno-parentheses-equality", "-Wno-pointer-arith", "-Wno-sign-compare", - "-Wno-unused-parameter", "-Wno-shift-negative-value", "-Wno-switch", "-Wno-absolute-value", @@ -126,6 +125,11 @@ cc_test { "tools/testing/selftests/breakpoints/breakpoint_test.c", ], }, + x86_64: { + srcs: [ + "tools/testing/selftests/breakpoints/breakpoint_test.c", + ], + }, }, } @@ -340,6 +344,21 @@ cc_test { defaults: ["kselftest_defaults"], } +// KVM test +cc_test { + name: "kselftest_kvm_arm64_tests", + relative_install_path: "linux-kselftest/kvm/aarch64", + local_include_dirs: [ "tools/testing/selftests"], + enabled: false, + arch: { + arm64: { + enabled: true, + srcs: ["tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c"], + }, + }, + defaults: ["kselftest_defaults"], +} + // Lib test sh_test { name: "kselftest_lib_printf", diff --git a/android/kselftest_test_list.mk b/android/kselftest_test_list.mk index 07df6fc5d758..46b9b92c58fb 100644 --- a/android/kselftest_test_list.mk +++ b/android/kselftest_test_list.mk @@ -31,6 +31,7 @@ kselftest_modules += \ kselftest_intel_pstate_tests_aperf \ kselftest_intel_pstate_tests_msr \ kselftest_kcmp_tests_kcmp_test \ + kselftest_kvm_arm64_tests_pvm_wipe_mem \ kselftest_net_tests_psock_tpacket \ kselftest_net_tests_socket \ kselftest_net_tests_reuseaddr_conflict \ diff --git a/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch b/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch deleted file mode 100644 index 7b1e1a1c32bc..000000000000 --- a/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 57b74c1b318625057398ccbe479a157507488d8c Mon Sep 17 00:00:00 2001 -From: Carlos Llamas <cmllamas@google.com> -Date: Tue, 14 Dec 2021 05:58:48 +0000 -Subject: [PATCH] selftests/binderfs: skip tests for unsupported kernels - -Binderfs was first introduced in Linux 5.0 release, so we need to skip -these tests for older kernels. Also, we force a successful exit as the -current framework doesn't handle KSFT_SKIP return codes. - -Signed-off-by: Carlos Llamas <cmllamas@google.com> ---- - .../filesystems/binderfs/binderfs_test.c | 28 +++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c -index 8c2ed962e1c7..be5a8f446066 100644 ---- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c -+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c -@@ -12,6 +12,7 @@ - #include <sys/mount.h> - #include <sys/stat.h> - #include <sys/types.h> -+#include <sys/utsname.h> - #include <unistd.h> - #include <linux/android/binder.h> - #include <linux/android/binderfs.h> -@@ -267,8 +268,35 @@ static void binderfs_test_unprivileged() - __do_binderfs_test(); - } - -+/* binderfs first introduced in Linux 5.0 */ -+bool binderfs_supported(void) -+{ -+ const int min_kernel_version = 5; -+ struct utsname utsname; -+ int ret, version; -+ -+ ret = uname(&utsname); -+ if (ret) -+ ksft_exit_fail_msg("%s - Failed to get kernel version\n", -+ strerror(errno)); -+ -+ ret = sscanf(utsname.release, "%d.", &version); -+ if (ret != 1) -+ ksft_exit_fail_msg("%s - Failed to parse uname: %s\n", -+ strerror(errno), utsname.release); -+ -+ return version >= min_kernel_version? true: false; -+} -+ -+ - int main(int argc, char *argv[]) - { -+ /* Force success exit for older kernels */ -+ if (!binderfs_supported()) { -+ ksft_print_msg("Skipping tests - binderfs not supported\n"); -+ ksft_exit_pass(); -+ } -+ - binderfs_test_privileged(); - binderfs_test_unprivileged(); - ksft_exit_pass(); --- -2.34.1.173.g76aa8bc2d0-goog - diff --git a/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch b/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch new file mode 100644 index 000000000000..590ee72368dc --- /dev/null +++ b/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch @@ -0,0 +1,246 @@ +From a9dc703806031c8535c84c9905979f86dfaec1d3 Mon Sep 17 00:00:00 2001 +From: Quentin Perret <qperret@google.com> +Date: Thu, 17 Feb 2022 19:34:27 +0000 +Subject: [PATCH] ANDROID: kvm: Test that pVM memory is wiped during teardown + +In protected KVM mode, we expect the hypervisor to protect guest secrets +when they are torn down. Add a test checking this property by running a +minimal guest, and checking that the content of memory has been wiped by +the hypervisor after teardown. + +Note: although some of the pKVM code has already landed upstream, the +functionality tested here hasn't at the time of writing. Once it does, +this test should be sent upstream for review to replace this ANDROID +patch. + +Bug: 218934075 +Signed-off-by: Quentin Perret <qperret@google.com> +Change-Id: I4a347908d189f2c4835fd576b26fae7c10ec9b22 +--- + Android.bp | 15 ++ + android/kselftest_test_list.mk | 1 + + .../selftests/kvm/aarch64/pvm_wipe_mem.c | 174 ++++++++++++++++++ + 3 files changed, 190 insertions(+) + create mode 100644 tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c + +diff --git a/Android.bp b/Android.bp +index 0b9166c56315..08805a161450 100644 +--- a/Android.bp ++++ b/Android.bp +@@ -340,6 +340,21 @@ cc_test { + defaults: ["kselftest_defaults"], + } + ++// KVM test ++cc_test { ++ name: "kselftest_kvm_arm64_tests", ++ relative_install_path: "linux-kselftest/kvm/aarch64", ++ local_include_dirs: [ "tools/testing/selftests"], ++ enabled: false, ++ arch: { ++ arm64: { ++ enabled: true, ++ srcs: ["tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c"], ++ }, ++ }, ++ defaults: ["kselftest_defaults"], ++} ++ + // Lib test + sh_test { + name: "kselftest_lib_printf", +diff --git a/android/kselftest_test_list.mk b/android/kselftest_test_list.mk +index 07df6fc5d758..46b9b92c58fb 100644 +--- a/android/kselftest_test_list.mk ++++ b/android/kselftest_test_list.mk +@@ -31,6 +31,7 @@ kselftest_modules += \ + kselftest_intel_pstate_tests_aperf \ + kselftest_intel_pstate_tests_msr \ + kselftest_kcmp_tests_kcmp_test \ ++ kselftest_kvm_arm64_tests_pvm_wipe_mem \ + kselftest_net_tests_psock_tpacket \ + kselftest_net_tests_socket \ + kselftest_net_tests_reuseaddr_conflict \ +diff --git a/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c +new file mode 100644 +index 000000000000..4af8ca3c4bad +--- /dev/null ++++ b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c +@@ -0,0 +1,174 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Test checking that memory of protected guests is wiped after teardown. ++ * ++ * Copyright (C) 2022, Google LLC. ++ */ ++ ++#define _GNU_SOURCE ++ ++#include <err.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <stdio.h> ++#include <stdint.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include <linux/kvm.h> ++#include <sys/ioctl.h> ++#include <sys/mman.h> ++ ++#include "kselftest.h" ++ ++#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31) ++ ++#define REG_X(number) (0x6030000000100000ULL + (number) * 2UL) ++#define REG_PC 0x6030000000100040ULL ++ ++static void set_one_reg(int vcpufd, uint64_t reg_id, uint64_t val) ++{ ++ uint64_t reg_data; ++ struct kvm_one_reg reg; ++ int ret; ++ ++ reg.addr = (__u64) ®_data; ++ reg_data = val; ++ reg.id = reg_id; ++ ++ ret = ioctl(vcpufd, KVM_SET_ONE_REG, ®); ++ if (ret < 0) ++ ksft_exit_fail_msg("Failed to set reg: %d\n", ret); ++} ++ ++static int get_kvm(void) ++{ ++ size_t run_size; ++ int kvm, ret; ++ ++ kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC); ++ if (kvm < 0) ++ ksft_exit_skip("KVM not supported\n"); ++ ++ ret = ioctl(kvm, KVM_GET_API_VERSION, NULL); ++ if (ret != 12) ++ ksft_exit_fail_msg("KVM_GET_API_VERSION %d, expected 12", ret); ++ ++ run_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); ++ if (run_size < sizeof(struct kvm_run)) ++ ksft_exit_fail_msg("KVM_GET_VCPU_MMAP_SIZE unexpectedly small\n"); ++ ++ return kvm; ++} ++ ++static int create_protected_vm(int kvm) ++{ ++ int vmfd = ioctl(kvm, KVM_CREATE_VM, KVM_VM_TYPE_ARM_PROTECTED); ++ ++ if (vmfd < 0) ++ ksft_exit_skip("Protected guests not supported: %d\n", vmfd); ++ ++ return vmfd; ++} ++ ++static int create_vcpu(int vmfd, struct kvm_run **run) ++{ ++ struct kvm_vcpu_init vcpu_init; ++ int vcpufd, ret; ++ ++ ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &vcpu_init); ++ if (ret) ++ ksft_exit_fail_msg("Failed to set kvm_vcpu_init %d\n", ret); ++ ++ vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0); ++ if (vcpufd < 0) ++ ksft_exit_fail_msg("Failed to create VCPU: %d\n", vcpufd); ++ ++ *run = mmap(NULL, sizeof(**run), PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0); ++ if (!run) ++ ksft_exit_fail_msg("Failed to mmap vcpu_run struct\n"); ++ ++ ret = ioctl(vcpufd, KVM_ARM_VCPU_INIT, &vcpu_init); ++ if (ret) ++ ksft_exit_fail_msg("Failed to initialize VCPU %d\n", ret); ++ ++ return vcpufd; ++} ++ ++static void teardown(int kvm, int vmfd, int vcpufd, struct kvm_run *run) ++{ ++ int ret = munmap(run, sizeof(*run)); ++ ++ if (ret) ++ ksft_exit_fail_msg("Failed to unmap vCPU run: %d\n", ret); ++ ++ ret = close(vcpufd); ++ if (ret) ++ ksft_exit_fail_msg("Failed to destroy VCPU: %d\n", ret); ++ ++ ret = close(vmfd); ++ if (ret) ++ ksft_exit_fail_msg("Failed to destroy VM: %d\n", ret); ++ ++ ret = close(kvm); ++ if (ret) ++ ksft_exit_fail_msg("Failed to close KVM fd: %d\n", ret); ++} ++ ++int main(void) ++{ ++ struct kvm_userspace_memory_region region; ++ long page_size = sysconf(_SC_PAGESIZE); ++ int ret, kvm, vmfd, vcpufd; ++ uint32_t guest_code[2]; ++ struct kvm_run *run; ++ uint8_t *guest_mem; ++ size_t run_size; ++ ++ kvm = get_kvm(); ++ vmfd = create_protected_vm(kvm); ++ vcpufd = create_vcpu(vmfd, &run); ++ ++ /* Create a one-page memslot for the guest */ ++ guest_mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_ANONYMOUS, -1, 0); ++ if (guest_mem == MAP_FAILED) ++ ksft_exit_fail_msg("Failed to mmap guest memory\n"); ++ region = (struct kvm_userspace_memory_region) { ++ .slot = 0, ++ .guest_phys_addr = 1UL << 30, ++ .memory_size = page_size, ++ .userspace_addr = (uint64_t)guest_mem, ++ }; ++ ++ /* Copy some code in guest memory. */ ++ guest_code[0] = 0xf9400001; /* 1: ldr x1, [x0] */ ++ guest_code[1] = 0x17ffffff; /* b 1b */ ++ memcpy(guest_mem, guest_code, sizeof(guest_code)); ++ ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); ++ if (ret) ++ ksft_exit_fail_msg("Failed to set memory region: %d\n", ret); ++ ++ /* ++ * Get the VCPU to run one instruction, to be sure the page containing ++ * the code has been faulted in. ++ */ ++ set_one_reg(vcpufd, REG_PC, region.guest_phys_addr); ++ set_one_reg(vcpufd, REG_X(0), region.guest_phys_addr + region.memory_size); ++ ret = ioctl(vcpufd, KVM_RUN, NULL); ++ if (ret) ++ ksft_exit_fail_msg("Failed to run vcpu: %d\n", ret); ++ if (run->exit_reason != KVM_EXIT_MMIO) ++ ksft_exit_fail_msg("Unexpected KVM exit reason: %u\n", run->exit_reason); ++ ++ /* ++ * Tear the guest down, and check that the donated memory has been ++ * wiped by the hypervisor. ++ */ ++ teardown(kvm, vmfd, vcpufd, run); ++ if (!memcmp(guest_mem, guest_code, sizeof(guest_code))) ++ ksft_exit_fail_msg("Protected guest memory has not been poisoned\n"); ++ ++ ksft_exit_pass(); ++} +-- +2.35.1.473.g83b2b277ed-goog + diff --git a/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch b/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch new file mode 100644 index 000000000000..0920fb307ed0 --- /dev/null +++ b/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch @@ -0,0 +1,33 @@ +From 30c060a86f0e56c19e18ade48c0ee7592edfc317 Mon Sep 17 00:00:00 2001 +From: Edward Liaw <edliaw@google.com> +Date: Thu, 24 Mar 2022 00:29:56 +0000 +Subject: [PATCH] selftests: userfaultfd skip if unavailable + +Skip userfaultfd selftest if the syscall is not available for this +kernel. + +Bug: 207175332 +Bug: 206503000 +Test: atest vts_linux_kselftest_arm_64:vm_userfaultfd_shmem_arm_64 +Change-Id: I60e4d6cc5b3886048ffa1995e4b090f6fbe26b3d +Signed-off-by: Edward Liaw <edliaw@google.com> +--- + tools/testing/selftests/vm/userfaultfd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c +index ffc78f3..17947fe 100644 +--- a/tools/testing/selftests/vm/userfaultfd.c ++++ b/tools/testing/selftests/vm/userfaultfd.c +@@ -665,7 +665,7 @@ static int userfaultfd_open(int features) + if (errno == ENOSYS) { + fprintf(stderr, + "userfaultfd syscall not available in this kernel\n"); +- exit(KSFT_PASS); ++ exit(KSFT_SKIP); + } + fprintf(stderr, + "userfaultfd syscall failed with errno: %d\n", errno); +-- +2.35.1.1021.g381101b075-goog + diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c index 4465b4f6a81a..397bf265ba97 100644 --- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c +++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c @@ -12,7 +12,6 @@ #include <sys/mount.h> #include <sys/stat.h> #include <sys/types.h> -#include <sys/utsname.h> #include <unistd.h> #include <linux/android/binder.h> #include <linux/android/binderfs.h> @@ -274,35 +273,8 @@ static void binderfs_test_unprivileged() __do_binderfs_test(); } -/* binderfs first introduced in Linux 5.0 */ -bool binderfs_supported(void) -{ - const int min_kernel_version = 5; - struct utsname utsname; - int ret, version; - - ret = uname(&utsname); - if (ret) - ksft_exit_fail_msg("%s - Failed to get kernel version\n", - strerror(errno)); - - ret = sscanf(utsname.release, "%d.", &version); - if (ret != 1) - ksft_exit_fail_msg("%s - Failed to parse uname: %s\n", - strerror(errno), utsname.release); - - return version >= min_kernel_version? true: false; -} - - int main(int argc, char *argv[]) { - /* Force success exit for older kernels */ - if (!binderfs_supported()) { - ksft_print_msg("Skipping tests - binderfs not supported\n"); - ksft_exit_pass(); - } - binderfs_test_privileged(); binderfs_test_unprivileged(); ksft_exit_pass(); diff --git a/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c new file mode 100644 index 000000000000..4af8ca3c4bad --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test checking that memory of protected guests is wiped after teardown. + * + * Copyright (C) 2022, Google LLC. + */ + +#define _GNU_SOURCE + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <linux/kvm.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include "kselftest.h" + +#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31) + +#define REG_X(number) (0x6030000000100000ULL + (number) * 2UL) +#define REG_PC 0x6030000000100040ULL + +static void set_one_reg(int vcpufd, uint64_t reg_id, uint64_t val) +{ + uint64_t reg_data; + struct kvm_one_reg reg; + int ret; + + reg.addr = (__u64) ®_data; + reg_data = val; + reg.id = reg_id; + + ret = ioctl(vcpufd, KVM_SET_ONE_REG, ®); + if (ret < 0) + ksft_exit_fail_msg("Failed to set reg: %d\n", ret); +} + +static int get_kvm(void) +{ + size_t run_size; + int kvm, ret; + + kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC); + if (kvm < 0) + ksft_exit_skip("KVM not supported\n"); + + ret = ioctl(kvm, KVM_GET_API_VERSION, NULL); + if (ret != 12) + ksft_exit_fail_msg("KVM_GET_API_VERSION %d, expected 12", ret); + + run_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); + if (run_size < sizeof(struct kvm_run)) + ksft_exit_fail_msg("KVM_GET_VCPU_MMAP_SIZE unexpectedly small\n"); + + return kvm; +} + +static int create_protected_vm(int kvm) +{ + int vmfd = ioctl(kvm, KVM_CREATE_VM, KVM_VM_TYPE_ARM_PROTECTED); + + if (vmfd < 0) + ksft_exit_skip("Protected guests not supported: %d\n", vmfd); + + return vmfd; +} + +static int create_vcpu(int vmfd, struct kvm_run **run) +{ + struct kvm_vcpu_init vcpu_init; + int vcpufd, ret; + + ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &vcpu_init); + if (ret) + ksft_exit_fail_msg("Failed to set kvm_vcpu_init %d\n", ret); + + vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0); + if (vcpufd < 0) + ksft_exit_fail_msg("Failed to create VCPU: %d\n", vcpufd); + + *run = mmap(NULL, sizeof(**run), PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0); + if (!run) + ksft_exit_fail_msg("Failed to mmap vcpu_run struct\n"); + + ret = ioctl(vcpufd, KVM_ARM_VCPU_INIT, &vcpu_init); + if (ret) + ksft_exit_fail_msg("Failed to initialize VCPU %d\n", ret); + + return vcpufd; +} + +static void teardown(int kvm, int vmfd, int vcpufd, struct kvm_run *run) +{ + int ret = munmap(run, sizeof(*run)); + + if (ret) + ksft_exit_fail_msg("Failed to unmap vCPU run: %d\n", ret); + + ret = close(vcpufd); + if (ret) + ksft_exit_fail_msg("Failed to destroy VCPU: %d\n", ret); + + ret = close(vmfd); + if (ret) + ksft_exit_fail_msg("Failed to destroy VM: %d\n", ret); + + ret = close(kvm); + if (ret) + ksft_exit_fail_msg("Failed to close KVM fd: %d\n", ret); +} + +int main(void) +{ + struct kvm_userspace_memory_region region; + long page_size = sysconf(_SC_PAGESIZE); + int ret, kvm, vmfd, vcpufd; + uint32_t guest_code[2]; + struct kvm_run *run; + uint8_t *guest_mem; + size_t run_size; + + kvm = get_kvm(); + vmfd = create_protected_vm(kvm); + vcpufd = create_vcpu(vmfd, &run); + + /* Create a one-page memslot for the guest */ + guest_mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (guest_mem == MAP_FAILED) + ksft_exit_fail_msg("Failed to mmap guest memory\n"); + region = (struct kvm_userspace_memory_region) { + .slot = 0, + .guest_phys_addr = 1UL << 30, + .memory_size = page_size, + .userspace_addr = (uint64_t)guest_mem, + }; + + /* Copy some code in guest memory. */ + guest_code[0] = 0xf9400001; /* 1: ldr x1, [x0] */ + guest_code[1] = 0x17ffffff; /* b 1b */ + memcpy(guest_mem, guest_code, sizeof(guest_code)); + ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); + if (ret) + ksft_exit_fail_msg("Failed to set memory region: %d\n", ret); + + /* + * Get the VCPU to run one instruction, to be sure the page containing + * the code has been faulted in. + */ + set_one_reg(vcpufd, REG_PC, region.guest_phys_addr); + set_one_reg(vcpufd, REG_X(0), region.guest_phys_addr + region.memory_size); + ret = ioctl(vcpufd, KVM_RUN, NULL); + if (ret) + ksft_exit_fail_msg("Failed to run vcpu: %d\n", ret); + if (run->exit_reason != KVM_EXIT_MMIO) + ksft_exit_fail_msg("Unexpected KVM exit reason: %u\n", run->exit_reason); + + /* + * Tear the guest down, and check that the donated memory has been + * wiped by the hypervisor. + */ + teardown(kvm, vmfd, vcpufd, run); + if (!memcmp(guest_mem, guest_code, sizeof(guest_code))) + ksft_exit_fail_msg("Protected guest memory has not been poisoned\n"); + + ksft_exit_pass(); +} diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index ffc78f3e4444..17947feb6d8e 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -665,7 +665,7 @@ static int userfaultfd_open(int features) if (errno == ENOSYS) { fprintf(stderr, "userfaultfd syscall not available in this kernel\n"); - exit(KSFT_PASS); + exit(KSFT_SKIP); } fprintf(stderr, "userfaultfd syscall failed with errno: %d\n", errno); |