xorl %eax, %eax

Linux kernel x86 VMX EFER DoS

with one comment

This bug affects Linux kernel prior to 2.6.29-git1 and it was reported by Benjamin Gilbert of Canergie Mellon University. This affects only x86 based processors using VMX (Virtual Machine eXtensions). The following code is from Linux kernel 2.6.28.9 release.

912 /*
913  * Writes msr value into into the appropriate "register".
914  * Returns 0 on success, non-0 otherwise.
915  * Assumes vcpu_load() was already called.
916  */
917 static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
918 {

This function can be found at arch/x86/kvm/vmx.c and is being used to set the MSR (Model Specific Registers) on a VMX enabled, x86 based processor. To make this easier to understand have a look at arch/x86/include/asm/msr-index.h before proceeding with the bug. You will see this:

4 /* CPU model specific register (MSR) numbers */
5
6  /* x86-64 specific MSRs */
7  #define MSR_EFER                0xc0000080 /* extended feature register */
8  #define MSR_STAR                0xc0000081 /* legacy mode SYSCALL target */
9  #define MSR_LSTAR               0xc0000082 /* long mode SYSCALL target */
10 #define MSR_CSTAR               0xc0000083 /* compat mode SYSCALL target */
11 #define MSR_SYSCALL_MASK        0xc0000084 /* EFLAGS mask for syscall */
12 #define MSR_FS_BASE             0xc0000100 /* 64bit FS base */
13 #define MSR_GS_BASE             0xc0000101 /* 64bit GS base */
14 #define MSR_KERNEL_GS_BASE      0xc0000102 /* SwapGS GS shadow */
15
16 /* EFER bits: */
17 #define _EFER_SCE               0  /* SYSCALL/SYSRET */
18 #define _EFER_LME               8  /* Long mode enable */
19 #define _EFER_LMA               10 /* Long mode active (read-only) */
20 #define _EFER_NX                11 /* No execute enable */
21
22 #define EFER_SCE                (1<<_EFER_SCE)
23 #define EFER_LME                (1<<_EFER_LME)
24 #define EFER_LMA                (1<<_EFER_LMA)
25 #define EFER_NX                 (1<<_EFER_NX)


Now, let’s continue with vmx_set_msr() routine…

919        struct vcpu_vmx *vmx = to_vmx(vcpu);
920        struct kvm_msr_entry *msr;
921        int ret = 0;
922
923        switch (msr_index) {
924 #ifdef CONFIG_X86_64
925        case MSR_EFER:
926                vmx_load_host_state(vmx);
927                ret = kvm_set_msr_common(vcpu, msr_index, data);
928                break;
929        case MSR_FS_BASE:
930                vmcs_writel(GUEST_FS_BASE, data);
931                break;
932        case MSR_GS_BASE:
933                vmcs_writel(GUEST_GS_BASE, data);
934                break;
935 #endif
936        case MSR_IA32_SYSENTER_CS:
937                vmcs_write32(GUEST_SYSENTER_CS, data);
938                break;
        ...
960        default:
961                vmx_load_host_state(vmx);
962                msr = find_msr_entry(vmx, msr_index);
963                if (msr) {
964                        msr->data = data;
965                        break;
966                }
        ...
970        return ret;
971 }


Even though lines 924 through 935 should only work on x86_64 processors and enable the following registers:
– Extended FEature Register (EFER)
– 64bit FS base register (FS)
– 64bit GS base register (GS)
Register EFER can be directly accessed through the default case of the switch statement simply by requesting EFER_LME. To patch this, Avi Kivity of Red Hat did the following:

     switch (msr_index) {
-#ifdef CONFIG_X86_64
     case MSR_EFER:
         vmx_load_host_state(vmx);
         ret = kvm_set_msr_common(vcpu, msr_index, data);
         break;
+#ifdef CONFIG_X86_64
     case MSR_FS_BASE:
         vmcs_writel(GUEST_FS_BASE, data);

Now MSR_EFER is enabled on any x86 processor since it’s out of the ifdef clause.

Written by xorl

April 7, 2009 at 15:16

Posted in bugs, linux

One Response

Subscribe to comments with RSS.

  1. In fact, the first processor to implement the EFER MSR was the AMD K6. It was first used to enable the SYSCALL and SYSRET instructions, also introduced in the K6.

    Yuhong Bao

    May 21, 2009 at 23:59


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s