[RFC PATCH 4/6] kvm: Lock guest RAMBlocks via PKRU during host userspace execution

Jacky Li <[email protected]>
Newsgroups gmane.comp.emulators.kvm.devel,gmane.comp.emulators.qemu
Message-ID <[email protected]>
Protect guest RAMBlocks from host-side speculative execution attacks by
locking and unlocking the guest memory protection key before and after
`KVM_RUN`.

Signed-off-by: Jacky Li <[email protected]>
---
 accel/kvm/kvm-all.c       |  7 ++++++-
 include/exec/cpu-common.h |  2 ++
 system/physmem.c          |  6 +++++-
 util/pkey.c               | 45 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 83cbd120a8..ae395cd374 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -19,6 +19,7 @@
 
 #include <linux/kvm.h>
 
+#include "exec/cpu-common.h"
 #include "qemu/atomic.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
@@ -3666,7 +3667,11 @@ int kvm_vcpu_ioctl(CPUState *cpu, unsigned long type, ...)
 
     trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg);
     accel_cpu_ioctl_begin(cpu);
-    ret = ioctl(cpu->kvm_fd, type, arg);
+    if (type == KVM_RUN) {
+        ret = qemu_pkey_kvm_run(cpu->kvm_fd, arg);
+    } else {
+        ret = ioctl(cpu->kvm_fd, type, arg);
+    }
     accel_cpu_ioctl_end(cpu);
     if (ret == -1) {
         ret = -errno;
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 28399088f6..90047128de 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -114,4 +114,6 @@ static inline CPUState *env_cpu(CPUArchState *env)
 
 void qemu_init_guest_memory_pkey(void);
 int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot);
+void qemu_reset_pkey_with_ibpb(void);
+int qemu_pkey_kvm_run(int fd, void *arg);
 #endif /* CPU_COMMON_H */
diff --git a/system/physmem.c b/system/physmem.c
index 9f5a0f194c..c7101f6841 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2755,7 +2755,11 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
                                     1, lock, is_write);
     }
 
-    return ramblock_ptr(block, addr);
+    void *ptr = ramblock_ptr(block, addr);
+    if (ptr) {
+        qemu_reset_pkey_with_ibpb();
+    }
+    return ptr;
 }
 
 /*
diff --git a/util/pkey.c b/util/pkey.c
index 0151714f32..2e42da7d9c 100644
--- a/util/pkey.c
+++ b/util/pkey.c
@@ -117,17 +117,62 @@ __attribute__((target("pku"))) int qemu_pkey_mprotect_guest_memory(void *addr,
     return pkey_mprotect(addr, len, prot, pkey);
 }
 
+__attribute__((target("pku"))) void qemu_reset_pkey_with_ibpb(void)
+{
+    int pkey = guest_memory_pkey;
+    if (pkey == -1) {
+        return;
+    }
+    if (inline_pkey_get(pkey) == 0) {
+        return;
+    }
+
+    /* IBPB */
+    prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0,
+                0);
+
+    inline_pkey_set(pkey, 0);
+}
+
+__attribute__((target("pku"))) int qemu_pkey_kvm_run(int fd, void *arg)
+{
+    int pkey = guest_memory_pkey;
+    if (pkey == -1) {
+        return ioctl(fd, KVM_RUN, arg);
+    }
+
+    assert(pkey >= 0 && pkey < KEY_COUNT);
+
+    inline_pkey_set(pkey, 0);
+
+    intptr_t ret = local_syscall3(__NR_ioctl, fd, KVM_RUN, (intptr_t)arg);
+
+    inline_pkey_set(pkey, PKEY_DISABLE_ACCESS);
+
+    if (ret < 0) {
+        errno = -ret;
+        ret = -1;
+    }
+    return (int)ret;
+}
+
 #else
 /* Dummy implementations for all other configurations (non-x86_64 Linux, */
 /* Windows, macOS, etc.) */
 #if defined(CONFIG_LINUX)
 #include <linux/kvm.h>
 #include <sys/ioctl.h>
+
+int qemu_pkey_kvm_run(int fd, void *arg)
+{ return ioctl(fd, KVM_RUN, arg); }
 #endif
 
 void qemu_init_guest_memory_pkey(void)
 {}
 
+void qemu_reset_pkey_with_ibpb(void)
+{}
+
 int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot)
 {
     return 0;

-- 
2.55.0.737.g08866a6d13-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.