Understanding Spectre v2 and How the Vulnerability

Since the emerging of the OpenStack cloud computing platform in the Ubuntu community, increasing number of public/private cloud service providers choose to deploy it all over the world. Recently, Spectre and Meltdown have caused a panic in the world and the Spectre V2 is the only one which can attack the host system from the guest VM. It's vital to know the detailed process of the attack. Gavin Guo will give a detail explanation and an example of how to attack the host system.

1.Understanding Spectre v2 and How the Vulnerability Impact the Cloud Security Engineering Technical Lead Gavin Guo Wechat

2. Agenda ● Introduction ● What's the Side-Channel Attack? ● Two kinds of branch prediction mechanisms. ● Generic Branch Predictor ● Indirect Branch Predictor ● Spectre V2 PoC

3. Introduction ● The slide is based on Jann Horn's work[5][9]. Kudos to Jann Horn! ● The PoC can be downloaded from chromium bugs checking website[9]. ● As the detail process is too _COMPLICATED_, I had an detail presentation in Chinese at Taiwan Linux Kernel Hackers Club on 2018/06/12: ● 主題分享:深入 Spectre V2 - VM 如何攻擊 Host?- (Gavin Guo) ● Youtube: https://www.youtube.com/watch?v=zYRI60uAwYc. ● Youku: https://v.youku.com/v_show/id_XMzY2MTQzMzg5Mg ● And the detail slide is uploaded to: ● For China: http://kernel.ubuntu.com/~gavinguo/spectre_v2/spectrev1v2v4-meltdownv3-gavin-guo.pdf ● Slideshare: https://www.slideshare.net/GavinGuo3/spectrev12-fv22fv4-vs-meltdownv3-102527086

4. What's Side-Channel Attack? (Speculation + Flush + Reload) Attacker Victim Address Space if (offset < DATA_LENGTH) { // Where Speculation Address Space happens unsigned char value = data[offset]; unsigned long index2 = (value & 1) * 0x100; o C unsigned char value2 = signal[index2]; P signal[0] signal[0] } 1 Attacker flush the shared cache line. 3 Attacker reloads the Victim loads the 2 shared cache line by cache and measure the time. It's faster if Speculation. already loaded. Cache

5. What's Generic Branch Predictor? Address Space The Generic Branch JMP 0x414100041000 Predictor is the Branch Branch Target Buffer Target Buffer which is Source Destination part of the CPU to 0x414100045123 predict the target 00041000 00045123 address of the branch JMP 0x414200041000 instruction before the execution unit calculate the result. 0x414200045123

6.What's Indirect Branch Predictor? Fetch Decode Execute Branch History IP address Register(BHB) Indirect Branch Predictor Calculated Indirect Branch Predictor Buffer branch target address Taken or Not-Taken Register Hash File Tag 2bc Function %r8 %r8 ... src1 src1 data ALU Indirect Branch Target Buffer Predicted src2 src2 0xb0 ... Target data Address Tag Target ... immediate icache callq *0xb0(%r8)

7. What’s the Indirect Branch History Buffer XOR Math? 58 bits ad Source d r[0 ,19 ] XOR BHB << 2 Some of the bits of the BHB ,5] r [0 Destination dd state seem to be folded together a further using XOR when used for void bhb_update(uint58_t *bhb_state, unsigned a BTB access, but the precise long src, unsigned long dst) { folding function hasn't been *bhb_state <<= 2; *bhb_state ^= (dst & 0x3f); understood yet. *bhb_state ^= (src & 0xc0) >> 6; *bhb_state ^= (src & 0xc00) >> (10 - 2); *bhb_state ^= (src & 0xc000) >> (14 - 4); The only fact is that the BHB is *bhb_state ^= (src & 0x30) << (6 - 4); shifted two bits at a time. We *bhb_state ^= (src & 0x300) << (8 - 8); *bhb_state ^= (src & 0x3000) >> (12 - 10); can guess the BHB by the trick. *bhb_state ^= (src & 0x30000) >> (16 - 12); *bhb_state ^= (src & 0xc0000) >> (18 - 14); } Ref: [5]

8. Ju Co m vmx_vcpu_run() vmx_complete_atomic_exit_c onstprop_88() addr_iret ns p T { 0x4720 t r ab { 0xfcbd ss Refill the IBHB/BTB by uc le } 0x4734 ret constructing the iret stack tio 0xfcbe vmx_vcpu_run sp with the ret instruction. n } 0xfcbe eflags The number is the offset to the vmx_complete_ato kvm_intel_load_address. mic_exit_constprop cs _88 Stack of Branch Target Injection 0x4734 0xcf48 0xcf48 0xcf48 ip kvm_arch_vcpu_ioctl_run -> 0xffffffff81514edd 0xcf48 0xcf48 0xcf48 kvm_arch_vcpu_ioctl_run <- __vmx_complete_interrupts(ret) Iret_area addr_iret 0xcf48(iret) 0xcf48 0xcf48 0xcf48 vmx_complete_interrupts -> __vmx_complete_interrupts(call) 0xcf48 0xcf48 0xcf48 ss 0x4720 vmx_vcpu_run -> vmx_complete_interrupts(call) 0xc3 0xc3 0xc3 0xc3 vmx_complete_atomic_exit_constpr op_88 sp vmx_vcpu_run <- vmx_recover_nmi_blocking(ret) 0xc3 0xc3 0xc3 0xc3 Ret_area 0xc3 0xc3 0xc3 0xc3 eflags vmx_vcpu_run -> vmx_recover_nmi_blocking(call) 0xc3(ret) 0xc3 0xc3 0xc3 0xc3 vmx_vcpu_run <- vmx_complete_atomic_exit_constprop_88(ret) cs 0xc3 0xc3 0xc3 0xc3 0xfcbd 0xc3 0xc3 0xc3 0xc3 ip vmx_vcpu_run -> vmx_vcpu_run vmx_complete_atomic_exit_constprop_88(call)

9. V2 1 6 t re Prepare the hookpoint In the user space of VM, Measure the time difference ec C data(eBPF) for attacking train the IBP to simulate loading leak address in p P o the VMExit and make it run share_page by the S specific address(e.g. 2 core_pattern) then call to the hook gadget to side-channel trick and vmcall(hypervisor call) which access the guessed virtual determine the leak bit. address. Guest userspace causes VM exit. Simulation of VA PA VMX non-root mode VMExit 0xffffffff81514edd Guest kernel VMExit user(r/w/x) ret VMX non-root mode Host kernel 3 5 VMX-root mode 4 __bpf_prog_run use the prebuilt bpf for(;;) Gadget instructions to implement side-channel { attack to leak the specific system address vmlaunch/vmresume; ffffffff81514edd: mov %r9,%rsi vmx_complete_atomic_exit_constprop_88(vmx); information to the share_page. ffffffff81514ee0: callq *0xb0(%r8) vmx_recover_nmi_blocking(vmx); ex: ffffffff81c845e0 D core_pattern r8+0xb0=__bpf_prog_run, r9=bpf_insn * vmx_complete_interrupts(vmx); } Speculation ffffffffbcc845e0 63 6f 72 65 00 00 | core ....|

10. How to get the physical address of mmap user space virtual address?mmap a page for the Use the side-channel trick to determine if 1 4 side-channel attack. mmap user page is cached. If yes, we find the PA, otherwise, go to step 3. VA PA Put the next guessed mapped In the user space of VM, 2 train the IBP to simulate VA in the register and call the vmcall in the user space to the VMExit and make it run to the hook gadget to mmap user space cause the VMExit. address access the guessed virtual Guest userspace 3 address. Simulation of VMX non-root mode VMExit ? +0xa9def *page_offset_base Guest kernel 0xffff8c0000000000 user(r/w/x) ret VMX non-root mode Load the data . for(;;) . from guessed VA { +0xa9def . Host kernel vmlaunch; vmx_complete_atomic_exit_constprop_88(vmx); Gadget *page_offset_base VMX-root vmx_recover_nmi_blocking(vmx); +64G mode vmx_complete_interrupts(vmx); Speculation 0xffff8c1000000000 }

11.How to get the page_offset virtual address? Use the side-channel attack to The PA(physical address) 4 determine if mmap user page is 1 of the mmap page is known cached. If yes, we find the from the previous step. PAGE_OFFSET, otherwise, go to step 3. VA PA Put the next guess mapped VA(Old PAGE_OFFSET+1GB+PA) In the user space of VM, 2 train the IBP to simulate in the register and call the vmcall in the user space to cause the VMExit. the VMExit and make it run to the hook gadget to mmap user space access the guessed virtual address Guest userspace 3 address. Simulation of VMX non-root mode VMExit PA +0x2c9d3 0xFFFF880000000000 Guest kernel VMExit user(r/w/x) ret VMX non-root mode Shift 1GB Load the data for(;;) 1GB from guessed VA { +0x2c9d3 . Host kernel vmlaunch; 1GB . VMX-root vmx_complete_atomic_exit_constprop_88(vmx); Gadget . vmx_recover_nmi_blocking(vmx); mode vmx_complete_interrupts(vmx); Speculation 0xFFFFFFFFFFFFFFFF }