0224-kvm-x86-fix-RSM-when-PCID-is-non-zero.patch 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. From 59b914593681a98524e4f3ba239544f77f03d14a Mon Sep 17 00:00:00 2001
  2. From: Paolo Bonzini <[email protected]>
  3. Date: Thu, 21 Dec 2017 00:49:14 +0100
  4. Subject: [PATCH 224/242] kvm: x86: fix RSM when PCID is non-zero
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. CVE-2017-5754
  9. rsm_load_state_64() and rsm_enter_protected_mode() load CR3, then
  10. CR4 & ~PCIDE, then CR0, then CR4.
  11. However, setting CR4.PCIDE fails if CR3[11:0] != 0. It's probably easier
  12. in the long run to replace rsm_enter_protected_mode() with an emulator
  13. callback that sets all the special registers (like KVM_SET_SREGS would
  14. do). For now, set the PCID field of CR3 only after CR4.PCIDE is 1.
  15. Reported-by: Laszlo Ersek <[email protected]>
  16. Tested-by: Laszlo Ersek <[email protected]>
  17. Fixes: 660a5d517aaab9187f93854425c4c63f4a09195c
  18. Cc: [email protected]
  19. Signed-off-by: Paolo Bonzini <[email protected]>
  20. (cherry picked from commit fae1a3e775cca8c3a9e0eb34443b310871a15a92)
  21. Signed-off-by: Andy Whitcroft <[email protected]>
  22. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  23. (cherry picked from commit dba4ceb9a91ed2d11a47722436b3c0be15e791d4)
  24. Signed-off-by: Fabian Grünbichler <[email protected]>
  25. ---
  26. arch/x86/kvm/emulate.c | 32 +++++++++++++++++++++++++-------
  27. 1 file changed, 25 insertions(+), 7 deletions(-)
  28. diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
  29. index fb0055953fbc..155f2af2cb39 100644
  30. --- a/arch/x86/kvm/emulate.c
  31. +++ b/arch/x86/kvm/emulate.c
  32. @@ -2399,9 +2399,21 @@ static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n)
  33. }
  34. static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
  35. - u64 cr0, u64 cr4)
  36. + u64 cr0, u64 cr3, u64 cr4)
  37. {
  38. int bad;
  39. + u64 pcid;
  40. +
  41. + /* In order to later set CR4.PCIDE, CR3[11:0] must be zero. */
  42. + pcid = 0;
  43. + if (cr4 & X86_CR4_PCIDE) {
  44. + pcid = cr3 & 0xfff;
  45. + cr3 &= ~0xfff;
  46. + }
  47. +
  48. + bad = ctxt->ops->set_cr(ctxt, 3, cr3);
  49. + if (bad)
  50. + return X86EMUL_UNHANDLEABLE;
  51. /*
  52. * First enable PAE, long mode needs it before CR0.PG = 1 is set.
  53. @@ -2420,6 +2432,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
  54. bad = ctxt->ops->set_cr(ctxt, 4, cr4);
  55. if (bad)
  56. return X86EMUL_UNHANDLEABLE;
  57. + if (pcid) {
  58. + bad = ctxt->ops->set_cr(ctxt, 3, cr3 | pcid);
  59. + if (bad)
  60. + return X86EMUL_UNHANDLEABLE;
  61. + }
  62. +
  63. }
  64. return X86EMUL_CONTINUE;
  65. @@ -2430,11 +2448,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
  66. struct desc_struct desc;
  67. struct desc_ptr dt;
  68. u16 selector;
  69. - u32 val, cr0, cr4;
  70. + u32 val, cr0, cr3, cr4;
  71. int i;
  72. cr0 = GET_SMSTATE(u32, smbase, 0x7ffc);
  73. - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u32, smbase, 0x7ff8));
  74. + cr3 = GET_SMSTATE(u32, smbase, 0x7ff8);
  75. ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED;
  76. ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0);
  77. @@ -2476,14 +2494,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
  78. ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8));
  79. - return rsm_enter_protected_mode(ctxt, cr0, cr4);
  80. + return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
  81. }
  82. static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
  83. {
  84. struct desc_struct desc;
  85. struct desc_ptr dt;
  86. - u64 val, cr0, cr4;
  87. + u64 val, cr0, cr3, cr4;
  88. u32 base3;
  89. u16 selector;
  90. int i, r;
  91. @@ -2500,7 +2518,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
  92. ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
  93. cr0 = GET_SMSTATE(u64, smbase, 0x7f58);
  94. - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u64, smbase, 0x7f50));
  95. + cr3 = GET_SMSTATE(u64, smbase, 0x7f50);
  96. cr4 = GET_SMSTATE(u64, smbase, 0x7f48);
  97. ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00));
  98. val = GET_SMSTATE(u64, smbase, 0x7ed0);
  99. @@ -2528,7 +2546,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
  100. dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
  101. ctxt->ops->set_gdt(ctxt, &dt);
  102. - r = rsm_enter_protected_mode(ctxt, cr0, cr4);
  103. + r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
  104. if (r != X86EMUL_CONTINUE)
  105. return r;
  106. --
  107. 2.14.2