test_vmcs_intel_x64_vmm_state.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 <test.h>
25 
26 #include <intrinsics/srs_x64.h>
27 #include <intrinsics/gdt_x64.h>
28 #include <intrinsics/idt_x64.h>
29 #include <intrinsics/debug_x64.h>
32 
33 #include <memory_manager/pat_x64.h>
35 
36 using namespace x64;
37 
38 extern uint64_t test_cr0;
39 extern uint64_t test_cr3;
40 extern uint64_t test_cr4;
41 
42 extern void setup_gdt();
43 extern void setup_idt();
44 
45 static uint64_t test_ia32_efer_msr;
46 
47 static void
48 setup_vmm_state(MockRepository &mocks)
49 {
50  auto pt = mocks.Mock<root_page_table_x64>();
51  mocks.OnCallFunc(root_pt).Return(pt);
52  mocks.OnCall(pt, root_page_table_x64::cr3).Return(test_cr3);
53 
54  test_cr0 = 0;
61 
62  test_cr3 = 0x000000ABCDEF0000;
63 
64  test_cr4 = 0;
80 }
81 
82 void
83 vmcs_ut::test_vmm_state_gdt_not_setup()
84 {
85  MockRepository mocks;
86  setup_vmm_state(mocks);
87 
88  auto cs_access_rights = (access_rights::ring0_cs_descriptor & 0xF0FFULL);
89  auto ss_access_rights = (access_rights::ring0_ss_descriptor & 0xF0FFULL);
90  auto fs_access_rights = (access_rights::ring0_fs_descriptor & 0xF0FFULL);
91  auto gs_access_rights = (access_rights::ring0_gs_descriptor & 0xF0FFULL);
92  auto tr_access_rights = (access_rights::ring0_tr_descriptor & 0xF0FFULL);
93 
94  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
95  {
96  this->expect_no_exception([&]
97  {
99 
100  this->expect_true(g_gdt.access_rights(1) == cs_access_rights);
101  this->expect_true(g_gdt.access_rights(2) == ss_access_rights);
102  this->expect_true(g_gdt.access_rights(3) == fs_access_rights);
103  this->expect_true(g_gdt.access_rights(4) == gs_access_rights);
104  this->expect_true(g_gdt.access_rights(5) == tr_access_rights);
105 
106  this->expect_true(g_gdt.base(1) == 0);
107  this->expect_true(g_gdt.base(2) == 0);
108  this->expect_true(g_gdt.base(3) == 0);
109  this->expect_true(g_gdt.base(4) == 0);
110  this->expect_true(g_gdt.base(5) == reinterpret_cast<gdt_x64::integer_pointer>(&g_tss));
111 
112  this->expect_true(g_gdt.limit(1) == 0xFFFFFFFF);
113  this->expect_true(g_gdt.limit(2) == 0xFFFFFFFF);
114  this->expect_true(g_gdt.limit(3) == 0xFFFFFFFF);
115  this->expect_true(g_gdt.limit(4) == 0xFFFFFFFF);
116  this->expect_true(g_gdt.limit(5) == sizeof(g_tss));
117  });
118  });
119 }
120 
121 void
122 vmcs_ut::test_vmm_state_segment_registers()
123 {
124  MockRepository mocks;
125  setup_vmm_state(mocks);
126 
127  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
128  {
129  this->expect_no_exception([&]
130  {
131  vmcs_intel_x64_vmm_state state{};
132 
133  this->expect_true(state.cs() == 1U << 3);
134  this->expect_true(state.ss() == 2U << 3);
135  this->expect_true(state.fs() == 3U << 3);
136  this->expect_true(state.gs() == 4U << 3);
137  this->expect_true(state.tr() == 5U << 3);
138  });
139  });
140 }
141 
142 void
143 vmcs_ut::test_vmm_state_control_registers()
144 {
145  MockRepository mocks;
146  setup_vmm_state(mocks);
147 
148  g_cpuid_regs.ebx = 0x00100080UL;
149 
150  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
151  {
152  this->expect_no_exception([&]
153  {
154  vmcs_intel_x64_vmm_state state{};
155 
156  this->expect_true(state.cr0() == test_cr0);
157  this->expect_true(state.cr3() == test_cr3);
158  this->expect_true(state.cr4() == test_cr4);
159  });
160  });
161 }
162 
163 void
164 vmcs_ut::test_vmm_state_rflags()
165 {
166  MockRepository mocks;
167  setup_vmm_state(mocks);
168 
169  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
170  {
171  this->expect_no_exception([&]
172  {
173  vmcs_intel_x64_vmm_state state{};
174  this->expect_true(state.rflags() == 0U);
175  });
176  });
177 }
178 
179 void
180 vmcs_ut::test_vmm_state_gdt_base()
181 {
182  MockRepository mocks;
183  setup_vmm_state(mocks);
184 
185  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
186  {
187  this->expect_no_exception([&]
188  {
189  vmcs_intel_x64_vmm_state state{};
190  this->expect_true(state.gdt_base() == g_gdt.base());
191  });
192  });
193 }
194 
195 void
196 vmcs_ut::test_vmm_state_idt_base()
197 {
198  MockRepository mocks;
199  setup_vmm_state(mocks);
200 
201  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
202  {
203  this->expect_no_exception([&]
204  {
205  vmcs_intel_x64_vmm_state state{};
206  this->expect_true(state.idt_base() == g_idt.base());
207  });
208  });
209 }
210 
211 void
212 vmcs_ut::test_vmm_state_gdt_limit()
213 {
214  MockRepository mocks;
215  setup_vmm_state(mocks);
216 
217  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
218  {
219  this->expect_no_exception([&]
220  {
221  vmcs_intel_x64_vmm_state state{};
222  this->expect_true(state.gdt_limit() == g_gdt.limit());
223  });
224  });
225 }
226 
227 void
228 vmcs_ut::test_vmm_state_idt_limit()
229 {
230  MockRepository mocks;
231  setup_vmm_state(mocks);
232 
233  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
234  {
235  this->expect_no_exception([&]
236  {
237  vmcs_intel_x64_vmm_state state{};
238  this->expect_true(state.idt_limit() == g_idt.limit());
239  });
240  });
241 }
242 
243 void
244 vmcs_ut::test_vmm_state_segment_registers_limit()
245 {
246  MockRepository mocks;
247  setup_vmm_state(mocks);
248 
249  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
250  {
251  this->expect_no_exception([&]
252  {
253  vmcs_intel_x64_vmm_state state{};
254 
255  this->expect_true(state.cs_limit() == g_gdt.limit(1U));
256  this->expect_true(state.ss_limit() == g_gdt.limit(2U));
257  this->expect_true(state.fs_limit() == g_gdt.limit(3U));
258  this->expect_true(state.gs_limit() == g_gdt.limit(4U));
259  this->expect_true(state.tr_limit() == g_gdt.limit(5U));
260  });
261  });
262 }
263 
264 void
265 vmcs_ut::test_vmm_state_segment_registers_access_rights()
266 {
267  MockRepository mocks;
268  setup_vmm_state(mocks);
269 
270  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
271  {
272  this->expect_no_exception([&]
273  {
274  vmcs_intel_x64_vmm_state state{};
275 
276  this->expect_true(state.cs_access_rights() == g_gdt.access_rights(1U));
277  this->expect_true(state.ss_access_rights() == g_gdt.access_rights(2U));
278  this->expect_true(state.fs_access_rights() == g_gdt.access_rights(3U));
279  this->expect_true(state.gs_access_rights() == g_gdt.access_rights(4U));
280  this->expect_true(state.tr_access_rights() == g_gdt.access_rights(5U));
281  });
282  });
283 }
284 
285 void
286 vmcs_ut::test_vmm_state_segment_registers_base()
287 {
288  MockRepository mocks;
289  setup_vmm_state(mocks);
290 
291  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
292  {
293  this->expect_no_exception([&]
294  {
295  vmcs_intel_x64_vmm_state state{};
296 
297  this->expect_true(state.cs_base() == g_gdt.base(1U));
298  this->expect_true(state.ss_base() == g_gdt.base(2U));
299  this->expect_true(state.fs_base() == g_gdt.base(3U));
300  this->expect_true(state.gs_base() == g_gdt.base(4U));
301  this->expect_true(state.tr_base() == g_gdt.base(5U));
302  });
303  });
304 }
305 
306 void
307 vmcs_ut::test_vmm_state_ia32_efer_msr()
308 {
309  MockRepository mocks;
310  setup_vmm_state(mocks);
311 
312  test_ia32_efer_msr = 0;
313  test_ia32_efer_msr |= msrs::ia32_efer::lme::mask;
314  test_ia32_efer_msr |= msrs::ia32_efer::lma::mask;
315  test_ia32_efer_msr |= msrs::ia32_efer::nxe::mask;
316 
317  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
318  {
319  this->expect_no_exception([&]
320  {
321  vmcs_intel_x64_vmm_state state{};
322  this->expect_true(state.ia32_pat_msr() == pat::pat_value);
323  this->expect_true(state.ia32_efer_msr() == test_ia32_efer_msr);
324  });
325  });
326 }
327 
328 void
329 vmcs_ut::test_vmm_state_dump()
330 {
331  MockRepository mocks;
332  setup_vmm_state(mocks);
333 
334  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
335  {
336  this->expect_no_exception([&]
337  {
338  vmcs_intel_x64_vmm_state state{};
339  this->expect_no_exception([&] { state.dump(); });
340  });
341  });
342 }
#define RUN_UNITTEST_WITH_MOCKS(a, b)
Definition: unittest.h:229
constexpr const auto ring0_cs_descriptor
Definition: x64.h:84
auto base() const
Definition: idt_x64.h:212
idt_x64 g_idt
access_rights_type access_rights(index_type index) const
Definition: gdt_x64.h:534
#define expect_no_exception(f)
Definition: unittest.h:198
constexpr const auto mask
Definition: cpuid_x64.h:85
constexpr const auto pt
Definition: mem_attr_x64.h:41
constexpr const auto pat_value
Definition: pat_x64.h:51
struct cpuid_regs g_cpuid_regs
Definition: test.cpp:35
virtual cr3_type cr3()
constexpr const auto ring0_tr_descriptor
Definition: x64.h:88
constexpr const auto ring0_gs_descriptor
Definition: x64.h:87
tss_x64 g_tss
integer_pointer base() const
Definition: gdt_x64.h:260
size_type limit() const
Definition: gdt_x64.h:270
constexpr const auto ring0_ss_descriptor
Definition: x64.h:85
gdt_x64 g_gdt
Definition: cache_x64.h:31
uintptr_t integer_pointer
Definition: gdt_x64.h:196
constexpr const auto ring0_fs_descriptor
Definition: x64.h:86
#define expect_true(a)
auto limit() const
Definition: idt_x64.h:222
root_page_table_x64 * root_pt() noexcept