vmcs_intel_x64_check_controls.cpp
Go to the documentation of this file.
1 //
2 // Bareflank Hypervisor
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 // Author: Connor Davis <davisc@ainfosec.com>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 
23 #include <gsl/gsl>
24 #include <view_as_pointer.h>
25 #include <vmcs/vmcs_intel_x64.h>
31 
33 
34 using namespace intel_x64;
35 using namespace vmcs;
36 
37 void
39 {
43 }
44 
45 void
47 {
68 }
69 
70 void
72 {
76 
78 }
79 
80 void
82 {
86 
88 }
89 
90 void
92 {
94  throw std::logic_error("the secondary controls field doesn't exist");
95 
99 
101 }
102 
103 void
105 {
106  if (vmcs::cr3_target_count::get() > 4)
107  throw std::logic_error("cr3 target count > 4");
108 }
109 
110 void
112 {
114  return;
115 
116  auto addr_a = vmcs::address_of_io_bitmap_a::get();
117  auto addr_b = vmcs::address_of_io_bitmap_b::get();
118 
119  if ((addr_a & 0x0000000000000FFF) != 0)
120  throw std::logic_error("io bitmap a addr not page aligned");
121 
122  if ((addr_b & 0x0000000000000FFF) != 0)
123  throw std::logic_error("io bitmap b addr not page aligned");
124 
125  if (!x64::is_physical_address_valid(addr_a))
126  throw std::logic_error("io bitmap a addr too large");
127 
128  if (!x64::is_physical_address_valid(addr_b))
129  throw std::logic_error("io bitmap b addr too large");
130 }
131 
132 void
134 {
136  return;
137 
139 
140  if ((addr & 0x0000000000000FFF) != 0)
141  throw std::logic_error("msr bitmap addr not page aligned");
142 
144  throw std::logic_error("msr bitmap addr too large");
145 }
146 
147 void
149 {
150  using namespace primary_processor_based_vm_execution_controls;
151  using namespace secondary_processor_based_vm_execution_controls;
152 
153  auto secondary_ctls_enabled = activate_secondary_controls::is_enabled();
154 
156  {
157  auto phys_addr = vmcs::virtual_apic_address::get();
158 
159  if (phys_addr == 0)
160  throw std::logic_error("virtual apic physical addr is NULL");
161 
162  if ((phys_addr & 0x0000000000000FFFUL) != 0)
163  throw std::logic_error("virtual apic addr not 4k aligned");
164 
165  if (!x64::is_physical_address_valid(phys_addr))
166  throw std::logic_error("virtual apic addr too large");
167 
168  if (secondary_ctls_enabled && virtual_interrupt_delivery::is_enabled_if_exists())
169  throw std::logic_error("tpr_shadow is enabled, but virtual interrupt delivery is enabled");
170 
171  auto tpr_threshold = tpr_threshold::get();
172 
173  if ((tpr_threshold & 0xFFFFFFF0UL) != 0)
174  throw std::logic_error("bits 31:4 of the tpr threshold must be 0");
175 
176  if (secondary_ctls_enabled && virtualize_apic_accesses::is_enabled_if_exists())
177  throw std::logic_error("tpr_shadow is enabled, but virtual apic is enabled");
178 
179  auto virt_addr = static_cast<uint8_t *>(g_mm->physint_to_virtptr(phys_addr));
180 
181  if (virt_addr == nullptr)
182  throw std::logic_error("virtual apic virtual addr is NULL");
183 
184  auto virt_addr_span = gsl::span<uint8_t>(virt_addr, 0x81);
185  auto vtpr = virt_addr_span[0x80];
186  auto vtpr_74 = (vtpr & 0xF0U) >> 4;
187  auto tpr_threshold_30 = static_cast<uint8_t>(tpr_threshold & 0x0000000FUL);
188 
189  if (tpr_threshold_30 > vtpr_74)
190  throw std::logic_error("invalid TPR threshold");
191  }
192  else
193  {
195  return;
196 
198  throw std::logic_error("virtualize_x2apic_mode must be disabled if tpr shadow is disabled");
199 
201  throw std::logic_error("apic_register_virtualization must be disabled if tpr shadow is disabled");
202 
204  throw std::logic_error("virtual_interrupt_delivery must be disabled if tpr shadow is disabled");
205  }
206 }
207 
208 void
210 {
212  return;
213 
215  throw std::logic_error("virtual NMI must be 0 if NMI exiting is 0");
216 }
217 
218 void
220 {
222  return;
223 
225  throw std::logic_error("NMI window exiting must be 0 if virtual NMI is 0");
226 }
227 
228 void
230 {
232  return;
233 
235  return;
236 
237  auto phys_addr = vmcs::apic_access_address::get_if_exists();
238 
239  if (phys_addr == 0)
240  throw std::logic_error("apic access physical addr is NULL");
241 
242  if ((phys_addr & 0x0000000000000FFF) != 0)
243  throw std::logic_error("apic access addr not 4k aligned");
244 
245  if (!x64::is_physical_address_valid(phys_addr))
246  throw std::logic_error("apic access addr too large");
247 }
248 
249 void
251 {
253  return;
254 
256  return;
257 
259  throw std::logic_error("apic accesses must be 0 if x2 apic mode is 1");
260 }
261 
262 void
264 {
266  return;
267 
269  return;
270 
272  throw std::logic_error("external_interrupt_exiting must be 1 "
273  "if virtual_interrupt_delivery is 1");
274 }
275 
276 void
278 {
280  return;
281 
283  throw std::logic_error("virtual interrupt delivery must be 1 "
284  "if posted interrupts is 1");
285 
287  throw std::logic_error("virtual interrupt delivery must be 1 "
288  "if posted interrupts is 1");
289 
291  throw std::logic_error("ack interrupt on exit must be 1 "
292  "if posted interrupts is 1");
293 
295 
296  if ((vector & 0x000000000000FF00UL) != 0)
297  throw std::logic_error("bits 15:8 of the notification vector must "
298  "be 0 if posted interrupts is 1");
299 
301 
302  if ((addr & 0x000000000000003FUL) != 0)
303  throw std::logic_error("bits 5:0 of the interrupt descriptor addr "
304  "must be 0 if posted interrupts is 1");
305 
307  throw std::logic_error("interrupt descriptor addr too large");
308 }
309 
310 void
312 {
314  return;
315 
317  return;
318 
320  throw std::logic_error("vpid cannot equal 0");
321 }
322 
323 void
325 {
326  using namespace msrs::ia32_vmx_ept_vpid_cap;
327  using namespace vmcs::ept_pointer;
328 
330  return;
331 
333  return;
334 
336 
337  if (mem_type == memory_type::uncacheable && !memory_type_uncacheable_supported::get())
338  throw std::logic_error("hardware does not support ept memory type: uncachable");
339 
340  if (mem_type == memory_type::write_back && !memory_type_write_back_supported::get())
341  throw std::logic_error("hardware does not support ept memory type: write-back");
342 
343  if (mem_type != memory_type::uncacheable && mem_type != memory_type::write_back)
344  throw std::logic_error("unknown eptp memory type");
345 
347  throw std::logic_error("the ept walk-through length must be 1 less than 4, i.e. 3");
348 
349  if (accessed_and_dirty_flags::is_enabled_if_exists() && !accessed_dirty_support::get())
350  throw std::logic_error("hardware does not support dirty / accessed flags for ept");
351 
353  throw std::logic_error("bits 11:7 and 63:48 of the eptp must be 0");
354 }
355 
356 void
358 {
360  return;
361 
363  return;
364 
365  auto pml_addr = vmcs::pml_address::get_if_exists();
366 
368  throw std::logic_error("ept must be enabled if pml is enabled");
369 
370  if (!x64::is_physical_address_valid(pml_addr))
371  throw std::logic_error("pml address must be a valid physical address");
372 
373  if ((pml_addr & 0x0000000000000FFF) != 0)
374  throw std::logic_error("bits 11:0 of the pml address must be 0");
375 }
376 
377 void
379 {
381  return;
382 
384  return;
385 
387  throw std::logic_error("enable ept must be 1 if unrestricted guest is 1");
388 }
389 
390 void
392 {
394  return;
395 
397  return;
398 
400  return;
401 
403  throw std::logic_error("unsupported vm function control bit set");
404 
406  return;
407 
409  throw std::logic_error("enable ept must be 1 if eptp switching is 1");
410 
411  auto eptp_list = vmcs::eptp_list_address::get_if_exists();
412 
413  if ((eptp_list & 0x0000000000000FFFU) != 0)
414  throw std::logic_error("bits 11:0 must be 0 for eptp list address");
415 
416  if (!x64::is_physical_address_valid(eptp_list))
417  throw std::logic_error("eptp list address addr too large");
418 }
419 
420 void
422 {
424  return;
425 
427  return;
428 
429  auto vmcs_vmread_bitmap_address = vmread_bitmap_address::get_if_exists();
430  auto vmcs_vmwrite_bitmap_address = vmwrite_bitmap_address::get_if_exists();
431 
432  if ((vmcs_vmread_bitmap_address & 0x0000000000000FFF) != 0)
433  throw std::logic_error("bits 11:0 must be 0 for the vmcs read bitmap address");
434 
435  if ((vmcs_vmwrite_bitmap_address & 0x0000000000000FFF) != 0)
436  throw std::logic_error("bits 11:0 must be 0 for the vmcs write bitmap address");
437 
438  if (!x64::is_physical_address_valid(vmcs_vmread_bitmap_address))
439  throw std::logic_error("vmcs read bitmap address addr too large");
440 
441  if (!x64::is_physical_address_valid(vmcs_vmwrite_bitmap_address))
442  throw std::logic_error("vmcs write bitmap address addr too large");
443 }
444 
445 void
447 {
449  return;
450 
452  return;
453 
454  auto vmcs_virt_except_info_address =
456 
457  if ((vmcs_virt_except_info_address & 0x0000000000000FFF) != 0)
458  throw std::logic_error("bits 11:0 must be 0 for the vmcs virt except info address");
459 
460  if (!x64::is_physical_address_valid(vmcs_virt_except_info_address))
461  throw std::logic_error("vmcs virt except info address addr too large");
462 }
463 
464 void
466 {
471 }
472 
473 void
475 {
477  auto ctls = vmcs::vm_exit_controls::get();
479 
481 }
482 
483 void
485 {
487  return;
488 
490  throw std::logic_error("save vmx preemption timer must be 0 "
491  "if activate vmx preemption timer is 0");
492 }
493 
494 void
496 {
497  auto msr_store_count = vm_exit_msr_store_count::get();
498 
499  if (msr_store_count == 0)
500  return;
501 
502  auto msr_store_addr = vmcs::vm_exit_msr_store_address::get();
503 
504  if ((msr_store_addr & 0x000000000000000F) != 0)
505  throw std::logic_error("bits 3:0 must be 0 for the exit msr store address");
506 
507  if (!x64::is_physical_address_valid(msr_store_addr))
508  throw std::logic_error("exit msr store addr too large");
509 
510  auto msr_store_addr_end = msr_store_addr + (msr_store_count * 16) - 1;
511 
512  if (!x64::is_physical_address_valid(msr_store_addr_end))
513  throw std::logic_error("end of exit msr store area too large");
514 }
515 
516 void
518 {
519  auto msr_load_count = vm_exit_msr_load_count::get();
520 
521  if (msr_load_count == 0)
522  return;
523 
524  auto msr_load_addr = vmcs::vm_exit_msr_load_address::get();
525 
526  if ((msr_load_addr & 0x000000000000000F) != 0)
527  throw std::logic_error("bits 3:0 must be 0 for the exit msr load address");
528 
529  if (!x64::is_physical_address_valid(msr_load_addr))
530  throw std::logic_error("exit msr load addr too large");
531 
532  auto msr_load_addr_end = msr_load_addr + (msr_load_count * 16) - 1;
533 
534  if (!x64::is_physical_address_valid(msr_load_addr_end))
535  throw std::logic_error("end of exit msr load area too large");
536 }
537 
538 void
540 {
548 }
549 
550 void
552 {
554  auto ctls = vm_entry_controls::get();
556 
558 }
559 
560 void
562 {
563  using namespace vm_entry_interruption_information_field;
564  using namespace msrs::ia32_vmx_true_procbased_ctls;
565 
567  return;
568 
571 
573  throw std::logic_error("interrupt information field type of 1 is reserved");
574 
576  throw std::logic_error("interrupt information field type of 7 "
577  "is reserved on this hardware");
578 
579  if (type == interruption_type::non_maskable_interrupt && vector != 2)
580  throw std::logic_error("interrupt information field vector must be "
581  "2 if the type field is 2 (NMI)");
582 
583  if (type == interruption_type::hardware_exception && vector > 31)
584  throw std::logic_error("interrupt information field vector must be "
585  "at most 31 if the type field is 3 (HE)");
586 
587  if (type == interruption_type::other_event && vector != 0)
588  throw std::logic_error("interrupt information field vector must be "
589  "0 if the type field is 7 (other)");
590 }
591 
592 void
594 {
595  using namespace vm_entry_interruption_information_field;
596  using namespace primary_processor_based_vm_execution_controls;
597  using namespace secondary_processor_based_vm_execution_controls;
598 
600  return;
601 
604 
606  {
608  throw std::logic_error("unrestricted guest must be 0 or PE must "
609  "be enabled in cr0 if deliver_error_code_bit is set");
610  }
611 
613  throw std::logic_error("interrupt information field type must be "
614  "3 if deliver_error_code_bit is set");
615 
616  switch (vector)
617  {
618  case 8:
619  case 10:
620  case 11:
621  case 12:
622  case 13:
623  case 14:
624  case 17:
625  break;
626 
627  default:
629  throw std::logic_error("vector must indicate exception that would normally "
630  "deliver an error code if deliver_error_code_bit is set");
631  }
632 
634  throw std::logic_error("deliver_error_code_bit must be 1");
635 }
636 
637 void
639 {
641  return;
642 
644  throw std::logic_error("reserved bits of the interrupt info field must be 0");
645 }
646 
647 void
649 {
651  return;
652 
654  return;
655 
656  if ((vm_entry_exception_error_code::get() & 0x00000000FFFF8000UL) != 0)
657  throw std::logic_error("bits 31:15 of the exception error code field must be 0 "
658  "if deliver error code bit is set in the interrupt info field");
659 }
660 
661 void
663 {
664  using namespace vm_entry_interruption_information_field;
665 
667  return;
668 
670  auto instruction_length = vm_entry_instruction_length::get();
671 
672  switch (type)
673  {
677  break;
678 
679  default:
680  return;
681  }
682 
684  throw std::logic_error("instruction length must be greater than zero");
685 
686  if (instruction_length > 15)
687  throw std::logic_error("instruction length must be in the range of 0-15 if type is 4, 5, 6");
688 }
689 
690 void
692 {
693  auto msr_load_count = vm_entry_msr_load_count::get();
694 
695  if (msr_load_count == 0)
696  return;
697 
698  auto msr_load_addr = vmcs::vm_entry_msr_load_address::get();
699 
700  if ((msr_load_addr & 0x000000000000000F) != 0)
701  throw std::logic_error("bits 3:0 must be 0 for the entry msr load address");
702 
703  if (!x64::is_physical_address_valid(msr_load_addr))
704  throw std::logic_error("entry msr load addr too large");
705 
706  auto msr_load_addr_end = msr_load_addr + (msr_load_count * 16) - 1;
707 
708  if (!x64::is_physical_address_valid(msr_load_addr_end))
709  throw std::logic_error("end of entry msr load area too large");
710 }
auto get()
auto get()
constexpr const auto name
auto is_physical_address_valid(T addr)
Definition: x64.h:126
auto is_disabled()
constexpr const auto software_interrupt
constexpr const auto other_event
constexpr const auto hardware_exception
constexpr const auto addr
Definition: cpuid_x64.h:80
auto get()
constexpr const auto software_exception
auto get()
auto get_if_exists(bool verbose=false) noexcept
constexpr const auto write_back
Definition: x64.h:46
constexpr const auto non_maskable_interrupt
auto get()
auto is_disabled()
auto get()
constexpr const auto privileged_software_exception
constexpr const auto reserved
Definition: vcpuid.h:33
#define g_mm
constexpr const auto uncacheable
Definition: x64.h:42
constexpr const auto addr
constexpr const auto name
Definition: cpuid_x64.h:81
auto get()
auto control_reserved_properly_set(MA msr_addr, C ctls, const char *ctls_name)
auto get()