Re: [PATCH qemu] x86: don't let decompressed kernel image clobber setup_data

2023-01-01 Thread Mika Penttilä




On 1.1.2023 6.33, H. Peter Anvin wrote:



On 12/31/22 10:22, Jason A. Donenfeld wrote:

On Sat, Dec 31, 2022 at 03:24:32PM +0100, Borislav Petkov wrote:

On Sat, Dec 31, 2022 at 02:51:28PM +0100, Jason A. Donenfeld wrote:

That failure is unrelated to the ident mapping issue Peter and
I discussed. The original failure is described in the commit message:
decompression clobbers the data, so sd->next points to garbage.


Right


So with that understanding confirmed, I'm confused at your surprise that
hpa's unrelated fix to the different issue didn't fix this issue.



If decompression does clobber the data, then we *also* need to figure 
out why that is. There are basically three possibilities:


1. If physical KASLR is NOT used:

 a. The boot loader doesn't honor the kernel safe area properly;
 b. Somewhere in the process a bug in the calculation of the
    kernel safe area has crept in.

2. If physical KASLR IS used:

 The decompressor doesn't correctly keep track of nor relocate
 all the keep-out zones before picking a target address.


Seems setup_data is not included in those mem_avoid regions.



One is a bootloader bug, two is a kernel bug. My guess is (2) is the 
culprit, but (1b) should be checked, too.


 -hpa




--Mika



Re: [RFC PATCH 5/6] kvm: x86: add KVM_EXIT_MEMORY_ERROR exit

2021-11-11 Thread Mika Penttilä




On 11.11.2021 16.13, Chao Peng wrote:

Currently support to exit to userspace for private/shared memory
conversion.

Signed-off-by: Sean Christopherson 
Signed-off-by: Yu Zhang 
Signed-off-by: Chao Peng 
---
  arch/x86/kvm/mmu/mmu.c   | 20 
  include/uapi/linux/kvm.h | 15 +++
  2 files changed, 35 insertions(+)

diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index af5ecf4ef62a..78086aa8 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3950,6 +3950,17 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool 
prefault, gfn_t gfn,
  
  	slot = __kvm_vcpu_gfn_to_memslot(vcpu, gfn, private);
  
+	/*

+* Exit to userspace to map the requested private/shared memory region
+* if there is no memslot and (a) the access is private or (b) there is
+* an existing private memslot.  Emulated MMIO must be accessed through
+* shared GPAs, thus a memslot miss on a private GPA is always handled
+* as an implicit conversion "request".
+*/
+   if (!slot &&
+   (private || __kvm_vcpu_gfn_to_memslot(vcpu, gfn, true)))
+   goto out_convert;
+
/* Don't expose aliases for no slot GFNs or private memslots */
if ((cr2_or_gpa & vcpu_gpa_stolen_mask(vcpu)) &&
!kvm_is_visible_memslot(slot)) {
@@ -3994,6 +4005,15 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool 
prefault, gfn_t gfn,
*pfn = __gfn_to_pfn_memslot(slot, gfn, false, NULL,
write, writable, hva);
return false;
+
+out_convert:
+   vcpu->run->exit_reason = KVM_EXIT_MEMORY_ERROR;
+   vcpu->run->mem.type = private ? KVM_EXIT_MEM_MAP_PRIVATE
+ : KVM_EXIT_MEM_MAP_SHARE;
+   vcpu->run->mem.u.map.gpa = cr2_or_gpa;
+   vcpu->run->mem.u.map.size = PAGE_SIZE;
+   return true;
+
  

I think this does just retry, no exit to user space?





}
  
  static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 8d20caae9180..470c472a9451 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -233,6 +233,18 @@ struct kvm_xen_exit {
} u;
  };
  
+struct kvm_memory_exit {

+#define KVM_EXIT_MEM_MAP_SHARE  1
+#define KVM_EXIT_MEM_MAP_PRIVATE2
+   __u32 type;
+   union {
+   struct {
+   __u64 gpa;
+   __u64 size;
+   } map;
+   } u;
+};
+
  #define KVM_S390_GET_SKEYS_NONE   1
  #define KVM_S390_SKEYS_MAX1048576
  
@@ -272,6 +284,7 @@ struct kvm_xen_exit {

  #define KVM_EXIT_X86_BUS_LOCK 33
  #define KVM_EXIT_XEN  34
  #define KVM_EXIT_TDVMCALL 35
+#define KVM_EXIT_MEMORY_ERROR36
  
  /* For KVM_EXIT_INTERNAL_ERROR */

  /* Emulate instruction failed. */
@@ -455,6 +468,8 @@ struct kvm_run {
__u64 subfunc;
__u64 param[4];
} tdvmcall;
+   /* KVM_EXIT_MEMORY_ERROR */
+   struct kvm_memory_exit mem;
/* Fix the size of the union. */
char padding[256];
};