cachepc

Prime+Probe cache-based side-channel attack on AMD SEV-SNP protected virtual machines
git clone https://git.sinitax.com/sinitax/cachepc
Log | Files | Refs | Submodules | README | sfeed.txt

commit 32331c7f421411bccb87ea818a2a0198b8cf88aa
parent a2cdd64c6f915d969dfa21e23049ff4b3836b13d
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue,  7 Feb 2023 07:58:27 -0600

Add syscall to deinit events to prevent blocking on send

Diffstat:
Mcachepc/event.c | 21+++++++++++++++++++++
Mcachepc/event.h | 1+
Mcachepc/kvm.c | 11+++++++++++
Mcachepc/uapi.h | 8+++++---
Mtest/eviction.c | 3+++
Mtest/kvm-eviction.c | 12+++++-------
Mtest/kvm-pagestep.c | 31++++++++++++++-----------------
Mtest/kvm-step.c | 22+++++++++++++---------
Mtest/kvm-targetstep.c | 27+++++++++++++--------------
Mtest/kvm.c | 8++++++--
10 files changed, 92 insertions(+), 52 deletions(-)

diff --git a/cachepc/event.c b/cachepc/event.c @@ -24,6 +24,8 @@ rwlock_t cpc_event_lock; struct cpc_event cpc_event; bool cpc_event_avail; +bool cpc_skip_events; + EXPORT_SYMBOL(cpc_send_guest_event); EXPORT_SYMBOL(cpc_send_pause_event); EXPORT_SYMBOL(cpc_send_track_step_event); @@ -51,6 +53,7 @@ void cpc_events_reset(void) { write_lock(&cpc_event_lock); + cpc_skip_events = false; cpc_eventbuf_len = 0; cpc_event_batching = false; cpc_last_event_sent = 1; @@ -59,11 +62,29 @@ cpc_events_reset(void) write_unlock(&cpc_event_lock); } +void +cpc_events_skip(void) +{ + write_lock(&cpc_event_lock); + cpc_skip_events = true; + cpc_last_event_sent = 1; + cpc_last_event_acked = 1; + cpc_event_avail = false; + write_unlock(&cpc_event_lock); +} + int cpc_send_event(struct cpc_event event) { ktime_t deadline; + read_lock(&cpc_event_lock); + if (cpc_skip_events) { + read_unlock(&cpc_event_lock); + return 1; + } + read_unlock(&cpc_event_lock); + write_lock(&cpc_event_lock); if (cpc_last_event_sent != cpc_last_event_acked) { CPC_WARN("Event IDs out of sync\n"); diff --git a/cachepc/event.h b/cachepc/event.h @@ -14,6 +14,7 @@ extern bool cpc_event_batching; void cpc_events_init(void); void cpc_events_deinit(void); void cpc_events_reset(void); +void cpc_events_skip(void); int cpc_send_guest_event(uint64_t type, uint64_t val); int cpc_send_pause_event(void); diff --git a/cachepc/kvm.c b/cachepc/kvm.c @@ -109,6 +109,8 @@ static void cpc_pmc_setup(void *p); static void cpc_system_setup(void); static int cpc_reset_ioctl(void __user *arg_user); +static int cpc_deinit_ioctl(void __user *arg_user); + static int cpc_loglevel_ioctl(void __user *arg_user); static int cpc_memory_encrypt_op_ioctl(void __user *arg_user); @@ -306,6 +308,13 @@ cpc_reset_ioctl(void __user *arg_user) } int +cpc_deinit_ioctl(void __user *arg_user) +{ + cpc_events_skip(); + return 0; +} + +int cpc_loglevel_ioctl(void __user *arg_user) { uint32_t level; @@ -561,6 +570,8 @@ cpc_kvm_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) switch (ioctl) { case KVM_CPC_RESET: return cpc_reset_ioctl(arg_user); + case KVM_CPC_DEINIT: + return cpc_deinit_ioctl(arg_user); case KVM_CPC_LOGLEVEL: return cpc_loglevel_ioctl(arg_user); case KVM_CPC_MEMORY_ENCRYPT_OP: diff --git a/cachepc/uapi.h b/cachepc/uapi.h @@ -9,10 +9,12 @@ #define CPC_DO_VMMCALL(action, type, val) \ asm volatile("vmmcall" : : "a" (action), "b"(type), "c" (val) : "rdx") -#define KVM_CPC_RESET _IOWR(KVMIO, 0x20, __u32) -#define KVM_CPC_LOGLEVEL _IOW(KVMIO, 0x21, __u32) +#define KVM_CPC_RESET _IO(KVMIO, 0x20) +#define KVM_CPC_DEINIT _IO(KVMIO, 0x21) -#define KVM_CPC_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0x22, struct kvm_sev_cmd) +#define KVM_CPC_LOGLEVEL _IOW(KVMIO, 0x22, __u32) + +#define KVM_CPC_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0x23, struct kvm_sev_cmd) #define KVM_CPC_TEST_EVICTION _IOWR(KVMIO, 0x24, __u32) diff --git a/test/eviction.c b/test/eviction.c @@ -40,5 +40,8 @@ main(int argc, const char **argv) close(fd); + ret = ioctl(fd, KVM_CPC_DEINIT, &arg); + if (ret == -1) err(1, "KVM_CPC_DEINIT"); + return arg; } diff --git a/test/kvm-eviction.c b/test/kvm-eviction.c @@ -45,15 +45,10 @@ main(int argc, const char **argv) struct cpc_track_cfg cfg; int i, k, ret, exitcode; - vmtype = "kvm"; - if (argc > 1) vmtype = argv[1]; - if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev") - && strcmp(vmtype, "sev-es") - && strcmp(vmtype, "sev-snp")) - errx(1, "invalid vm mode: %s", vmtype); - setvbuf(stdout, NULL, _IONBF, 0); + parse_vmtype(argc, argv); + pin_process(0, TARGET_CORE, true); kvm_setup_init(); @@ -153,6 +148,9 @@ main(int argc, const char **argv) vm_deinit(&vms[WITH]); vm_deinit(&vms[WITHOUT]); + ret = ioctl(kvm_dev, KVM_CPC_DEINIT); + if (ret == -1) err(1, "KVM_CPC_DEINIT"); + kvm_setup_deinit(); return exitcode; diff --git a/test/kvm-pagestep.c b/test/kvm-pagestep.c @@ -42,10 +42,13 @@ monitor(struct kvm *kvm, bool baseline) } void -kill_child(void) +deinit(void) { - printf("Killing vm..\n"); + ioctl(kvm_dev, KVM_CPC_DEINIT); + kill(child, SIGKILL); + + kvm_setup_deinit(); } int @@ -58,15 +61,10 @@ main(int argc, const char **argv) uint64_t eventcnt; int ret; - vmtype = "kvm"; - if (argc > 1) vmtype = argv[1]; - if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev") - && strcmp(vmtype, "sev-es") - && strcmp(vmtype, "sev-snp")) - errx(1, "invalid vm mode: %s", vmtype); - setvbuf(stdout, NULL, _IONBF, 0); + parse_vmtype(argc, argv); + kvm_setup_init(); ipc = ipc_alloc(); @@ -100,10 +98,14 @@ main(int argc, const char **argv) printf("VM exit\n"); vm_deinit(&kvm); + + ipc_free(ipc); + + kvm_setup_deinit(); } else { pin_process(0, SECONDARY_CORE, true); - atexit(kill_child); + atexit(deinit); ipc_wait_child(ipc); @@ -123,13 +125,8 @@ main(int argc, const char **argv) } printf("Monitor exit\n"); - } - - ipc_free(ipc); - ret = ioctl(kvm_dev, KVM_CPC_RESET, NULL); - if (ret < 0) err(1, "KVM_CPC_RESET"); - - kvm_setup_deinit(); + ipc_free(ipc); + } } diff --git a/test/kvm-step.c b/test/kvm-step.c @@ -50,10 +50,13 @@ monitor(struct kvm *kvm, bool baseline) } void -kill_child(void) +deinit(void) { - printf("Killing vm..\n"); + ioctl(kvm_dev, KVM_CPC_DEINIT); + kill(child, SIGKILL); + + kvm_setup_deinit(); } int @@ -69,6 +72,8 @@ main(int argc, const char **argv) bool with_data; int ret; + setvbuf(stdout, NULL, _IONBF, 0); + with_data = true; if (argc > 1 && !strcmp(argv[1], "--exec-only")) { with_data = false; @@ -78,8 +83,6 @@ main(int argc, const char **argv) parse_vmtype(argc, argv); - setvbuf(stdout, NULL, _IONBF, 0); - kvm_setup_init(); ipc = ipc_alloc(); @@ -111,10 +114,13 @@ main(int argc, const char **argv) printf("VM exit\n"); vm_deinit(&kvm); + + ipc_free(ipc); + kvm_setup_deinit(); } else { pin_process(0, SECONDARY_CORE, true); - atexit(kill_child); + atexit(deinit); ipc_wait_child(ipc); @@ -178,10 +184,8 @@ main(int argc, const char **argv) } printf("Monitor exit\n"); - } - ipc_free(ipc); - - kvm_setup_deinit(); + ipc_free(ipc); + } } diff --git a/test/kvm-targetstep.c b/test/kvm-targetstep.c @@ -53,10 +53,13 @@ monitor(struct kvm *kvm, bool baseline) } void -kill_child(void) +deinit(void) { - printf("Killing vm..\n"); + ioctl(kvm_dev, KVM_CPC_DEINIT); + kill(child, SIGKILL); + + kvm_setup_deinit(); } int @@ -73,15 +76,10 @@ main(int argc, const char **argv) uint32_t arg; int ret; - vmtype = "kvm"; - if (argc > 1) vmtype = argv[1]; - if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev") - && strcmp(vmtype, "sev-es") - && strcmp(vmtype, "sev-snp")) - errx(1, "invalid vm mode: %s", vmtype); - setvbuf(stdout, NULL, _IONBF, 0); + parse_vmtype(argc, argv); + kvm_setup_init(); ipc = ipc_alloc(); @@ -113,10 +111,13 @@ main(int argc, const char **argv) printf("VM exit\n"); vm_deinit(&kvm); + + ipc_free(ipc); + kvm_setup_deinit(); } else { pin_process(0, SECONDARY_CORE, true); - atexit(kill_child); + atexit(deinit); ipc_wait_child(ipc); @@ -218,10 +219,8 @@ main(int argc, const char **argv) while (monitor(&kvm, false) != 2); printf("Monitor exit\n"); - } - - ipc_free(ipc); - kvm_setup_deinit(); + ipc_free(ipc); + } } diff --git a/test/kvm.c b/test/kvm.c @@ -28,8 +28,9 @@ #include <stdio.h> #include <stdlib.h> -int kvm_dev, sev_dev; -const char *vmtype; +int kvm_dev = -1; +int sev_dev = -1; +const char *vmtype = NULL; const char *sev_fwerr_strs[] = { [0x00] = "Success", @@ -504,5 +505,8 @@ void kvm_setup_deinit(void) { close(kvm_dev); + kvm_dev = -1; + close(sev_dev); + sev_dev = -1; }