I might be missing something here but I think what you say is only correct for the kvm_hypercall4 cases. All other functions use a smaller number of registers. #VC blindly assumes that all those registers are used in the vmcall and exposes them. Here are some examples: For example in the kvm_hypercall2 only rax, rbx, and rcx should be exposed. apic_id address is leaked with rdx when this hypercall is used in kvm_kick_cpu function. RSI is never used. I am not sure what value will be exposed to VMM in this case: 54 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, 55 unsigned long p2) 56 { 57 long ret; 58 asm volatile(KVM_HYPERCALL 59 : "=a"(ret) 60 : "a"(nr), "b"(p1), "c"(p2) 61 : "memory"); 62 return ret; 63 } And this function is called in : 820 static void kvm_kick_cpu(int cpu) 821 { 822 int apicid; 823 unsigned long flags = 0; 824 825 apicid = per_cpu(x86_cpu_to_apicid, cpu); 826 kvm_hypercall2(KVM_HC_KICK_CPU, flags, apicid); 827 } looking to what it is compiled in my machine : 151215 ffffffff8105def0 <kvm_kick_cpu>: 151216 { 151217 ffffffff8105def0: e8 fb 9e ff ff callq ffffffff81057df0 <__fentry__> 151218 apicid = per_cpu(x86_cpu_to_apicid, cpu); 151219 ffffffff8105def5: 48 63 ff movslq %edi,%rdi 151220 { 151221 ffffffff8105def8: 53 push %rbx 151222 apicid = per_cpu(x86_cpu_to_apicid, cpu); 151223 ffffffff8105def9: 48 c7 c0 58 16 01 00 mov $0x11658,%rax 151224 151225 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, 151226 unsigned long p2) 151227 { 151228 long ret; 151229 asm volatile(KVM_HYPERCALL 151230 ffffffff8105df00: 31 db xor %ebx,%ebx 151231 ffffffff8105df02: 48 8b 14 fd 00 19 cb mov -0x7e34e700(,%rdi,8),%rdx 151232 ffffffff8105df09: 81 151233 kvm_hypercall2(KVM_HC_KICK_CPU, flags, apicid); 151234 ffffffff8105df0a: 0f b7 0c 02 movzwl (%rdx,%rax,1),%ecx 151235 ffffffff8105df0e: b8 05 00 00 00 mov $0x5,%eax 151236 ffffffff8105df13: 0f 01 c1 vmcall 151237 } 151238 ffffffff8105df16: 5b pop %rbx 151239 ffffffff8105df17: c3 retq Similarly kvm_hypercall1 only need 2 registers to expose: 44 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) 45 { 46 long ret; 47 asm volatile(KVM_HYPERCALL 48 : "=a"(ret) 49 : "a"(nr), "b"(p1) 50 : "memory"); 51 return ret; 52 } And an example where it is used: 562 static void kvm_smp_send_call_func_ipi(const struct cpumask *mask) 563 { 564 int cpu; 565 566 native_send_call_func_ipi(mask); 567 568 /* Make sure other vCPUs get a chance to run if they need to. */ 569 for_each_cpu(cpu, mask) { 570 if (vcpu_is_preempted(cpu)) { 571 kvm_hypercall1(KVM_HC_SCHED_YIELD, per_cpu(x86_cpu_to_apicid, cpu)); 572 break; 573 } 574 } 575 } If we look at the function decompiled in my platform, here x86_cpu_to_apicid address is leaked in rdx. RSI also leaks some information from kvm_smp_send_call_function_ipi function. RCX is not used so it might include something from a higher caller. 151243 ffffffff8105df20 <kvm_smp_send_call_func_ipi>: 151244 { 151245 ffffffff8105df20: e8 cb 9e ff ff callq ffffffff81057df0 <__fentry__> 151246 ffffffff8105df25: 53 push %rbx 151247 ffffffff8105df26: 48 89 fb mov %rdi,%rbx 151248 native_send_call_func_ipi(mask); 151249 ffffffff8105df29: e8 a2 45 ff ff callq ffffffff810524d0 <native_send_call_func_ipi> 151250 for_each_cpu(cpu, mask) { 151251 ffffffff8105df2e: 41 b8 ff ff ff ff mov $0xffffffff,%r8d 151252 ffffffff8105df34: eb 0e jmp ffffffff8105df44 <kvm_smp_send_call_func_ipi+0x24> 151253 return PVOP_CALLEE1(bool, lock.vcpu_is_preempted, cpu); 151254 ffffffff8105df36: 49 63 f8 movslq %r8d,%rdi 151255 ffffffff8105df39: ff 14 25 90 93 02 82 callq *0xffffffff82029390 151256 if (vcpu_is_preempted(cpu)) { 151257 ffffffff8105df40: 84 c0 test %al,%al 151258 ffffffff8105df42: 75 18 jne ffffffff8105df5c <kvm_smp_send_call_func_ipi+0x3c> 151259 for_each_cpu(cpu, mask) { 151260 ffffffff8105df44: 44 89 c7 mov %r8d,%edi 151261 ffffffff8105df47: 48 89 de mov %rbx,%rsi 151262 ffffffff8105df4a: e8 61 44 39 00 callq ffffffff813f23b0 <cpumask_next> 151263 ffffffff8105df4f: 3b 05 2f 7e 12 01 cmp 0x1127e2f(%rip),%eax # ffffffff82185d84 <nr_cpu_ids> 151264 ffffffff8105df55: 41 89 c0 mov %eax,%r8d 151265 ffffffff8105df58: 72 dc jb ffffffff8105df36 <kvm_smp_send_call_func_ipi+0x16> 151266 } 151267 ffffffff8105df5a: 5b pop %rbx 151268 ffffffff8105df5b: c3 retq 151269 kvm_hypercall1(KVM_HC_SCHED_YIELD, per_cpu(x86_cpu_to_apicid, cpu)); 151270 ffffffff8105df5c: 48 8b 14 fd 00 19 cb mov -0x7e34e700(,%rdi,8),%rdx 151271 ffffffff8105df63: 81 151272 ffffffff8105df64: 48 c7 c0 58 16 01 00 mov $0x11658,%rax 151273 ffffffff8105df6b: 0f b7 1c 02 movzwl (%rdx,%rax,1),%ebx 151274 asm volatile(KVM_HYPERCALL 151275 ffffffff8105df6f: b8 0b 00 00 00 mov $0xb,%eax 151276 ffffffff8105df74: 0f 01 c1 vmcall 151277 } I am not sure how those leaked registers can be used, but depending on which function call hypercall[0-3], there will be some leak. -Erdem On Wed, Oct 28, 2020 at 2:49 AM Joerg Roedel <jroedel@xxxxxxx> wrote: > > On Tue, Oct 27, 2020 at 04:14:15PM -0700, Erdem Aktas wrote: > > It seems to me that the kvm_sev_es_hcall_prepare is leaking more > > information than it is needed. Is this an expected behavior? > > What exactly is leaked? The kvm hypercall uses RAX, RBX, RCX, RDX and > RSI for parameters. > > Regards, > > Joerg
![]() |