Bitdefender Hypervisor Memory Introspection
hook_cr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "hook_cr.h"
6 #include "callbacks.h"
7 #include "guests.h"
8 
9 
12  _In_ DWORD Cr,
13  _In_ DWORD Flags,
15  _In_opt_ void *Context,
16  _Out_opt_ HOOK_CR **Hook
17  )
42 {
44 
45  if (NULL == Callback)
46  {
48  }
49 
50  HOOK_CR *pHook = HpAllocWithTag(sizeof(*pHook), IC_TAG_CRH);
51  if (NULL == pHook)
52  {
54  }
55 
56  pHook->Callback = Callback;
57  pHook->Context = Context;
58  pHook->Disabled = FALSE;
59  pHook->Flags = Flags;
60  pHook->Cr = Cr;
61 
62  // Check if we already have a hook on this CR, in which case, we don't have to activate exits on it.
63  BOOLEAN bCrAlreadyHooked = FALSE;
64 
66  {
67  if (Cr == pListHook->Cr)
68  {
69  bCrAlreadyHooked = TRUE;
70  break;
71  }
72  }
73 
74  if (!bCrAlreadyHooked)
75  {
76  status = IntEnableCrWriteExit(Cr);
77  if (!INT_SUCCESS(status))
78  {
79  ERROR("[ERROR] IntEnableCrWriteExit failed: 0x%08x\n", status);
80  }
81  }
82 
83  if (0 == gGuest.CrHooks->HooksCount++)
84  {
85  status = IntEnableCrNotifications();
86  if (!INT_SUCCESS(status))
87  {
89  return status;
90  }
91  }
92 
94 
95  if (NULL != Hook)
96  {
97  *Hook = pHook;
98  }
99 
100  return status;
101 }
102 
103 
104 static INTSTATUS
106  _In_ HOOK_CR *Hook
107  )
117 {
118  if (!Hook->Disabled)
119  {
121  }
122 
124 
125  if (0 >= --gGuest.CrHooks->HooksCount)
126  {
127  return IntDisableCrNotifications();
128  }
129 
130  return INT_STATUS_SUCCESS;
131 }
132 
133 
134 INTSTATUS
136  _In_ HOOK_CR *Hook
137  )
151 {
152  INTSTATUS status = INT_STATUS_SUCCESS;
153 
154  if (NULL == Hook)
155  {
157  }
158 
159  CR_HOOK_STATE *pCrHooksState = gGuest.CrHooks;
160  if (NULL == pCrHooksState)
161  {
163  }
164 
165  Hook->Disabled = TRUE;
166 
167  BOOLEAN bCrStillHooked = FALSE;
168  list_for_each(pCrHooksState->CrHooksList, HOOK_CR, pHook)
169  {
170  if ((pHook != Hook) && (pHook->Cr == Hook->Cr))
171  {
172  bCrStillHooked = TRUE;
173  break;
174  }
175  }
176 
177  if (!bCrStillHooked)
178  {
179  status = IntDisableCrWriteExit(Hook->Cr);
180  if (!INT_SUCCESS(status))
181  {
182  ERROR("[ERROR] IntDisableCrWriteExit failed: 0x%08x\n", status);
183  }
184  }
185 
187  {
188  RemoveEntryList(&Hook->Link);
189 
190  status = IntHookCrDeleteHook(Hook);
191  if (!INT_SUCCESS(status))
192  {
193  ERROR("[ERROR] IntHookCrDeleteHook failed: 0x%08x\n", status);
194  }
195  }
196 
197  return status;
198 }
199 
200 
201 static INTSTATUS
203  void
204  )
211 {
212  INTSTATUS status = INT_STATUS_SUCCESS;
213 
214  CR_HOOK_STATE *pCrHookState = gGuest.CrHooks;
215  if (NULL == pCrHookState)
216  {
218  }
219 
220  list_for_each(pCrHookState->CrHooksList, HOOK_CR, pHook)
221  {
222  status = IntHookCrRemoveHook(pHook);
223  if (!INT_SUCCESS(status))
224  {
225  ERROR("[ERROR] IntHookCrRemoveHook failed: 0x%08x\n", status);
226  }
227  }
228 
229  return status;
230 }
231 
232 
233 INTSTATUS
235  void
236  )
245 {
246  INTSTATUS status = INT_STATUS_SUCCESS;
247 
248  if (NULL == gGuest.CrHooks)
249  {
251  }
252 
254  {
255  if (pHook->Disabled)
256  {
257  RemoveEntryList(&pHook->Link);
258 
259  status = IntHookCrDeleteHook(pHook);
260  if (!INT_SUCCESS(status))
261  {
262  ERROR("[ERROR] IntHookCrDeleteHook failed: 0x%08x\n", status);
263  }
264  }
265  }
266 
267  return status;
268 }
269 
270 
271 INTSTATUS
273  void
274  )
281 {
283  if (NULL == gGuest.CrHooks)
284  {
286  }
287 
289 
290  return INT_STATUS_SUCCESS;
291 }
292 
293 
294 INTSTATUS
296  void
297  )
304 {
305  if (NULL == gGuest.CrHooks)
306  {
308  }
309 
311 
313 
314  return INT_STATUS_SUCCESS;
315 }
#define _In_opt_
Definition: intro_sal.h:16
_Bool BOOLEAN
Definition: intro_types.h:58
LIST_ENTRY Link
List entry link.
Definition: hook_cr.h:45
INT64 HooksCount
Total number of CR hooks.
Definition: hook_cr.h:36
INTSTATUS IntHookCrUninit(void)
Uninit the control register hooks state.
Definition: hook_cr.c:295
static INTSTATUS IntDisableCrNotifications(void)
Definition: callbacks.h:210
#define _In_
Definition: intro_sal.h:21
void * Context
Optional context, will be passed to the callback.
Definition: hook_cr.h:50
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
CR_HOOK_STATE * CrHooks
CR hook state.
Definition: guests.h:389
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
#define ERROR(fmt,...)
Definition: glue.h:62
Handling a CR load.
Definition: guests.h:25
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
INTSTATUS IntDisableCrWriteExit(DWORD Cr)
Definition: glue.c:556
int INTSTATUS
The status data type.
Definition: introstatus.h:24
INTSTATUS(* PFUNC_CrWriteHookCallback)(void *Context, DWORD Cr, QWORD OldValue, QWORD NewValue, INTRO_ACTION *Action)
Called when a control-register write takes place.
Definition: hook_cr.h:21
#define IC_TAG_CRH
CR hook.
Definition: memtags.h:70
INTSTATUS IntHookCrInit(void)
Initialize the control registers hook state.
Definition: hook_cr.c:272
#define _Out_opt_
Definition: intro_sal.h:30
#define INT_STATUS_NOT_INITIALIZED
Definition: introstatus.h:266
#define IC_TAG_CRS
CR hook state.
Definition: memtags.h:71
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
CPU_STATE State
The state of this VCPU. Describes what action is the VCPU currently doing.
Definition: guests.h:173
INTSTATUS IntHookCrCommit(void)
Commit the control register hooks.
Definition: hook_cr.c:234
#define TRUE
Definition: intro_types.h:30
static INTSTATUS IntEnableCrNotifications(void)
Definition: callbacks.h:193
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
INTSTATUS IntEnableCrWriteExit(DWORD Cr)
Definition: glue.c:547
static INTSTATUS IntHookCrRemoveAllHooks(void)
Remove all control register write hooks.
Definition: hook_cr.c:202
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:135
INTSTATUS IntHookCrRemoveHook(HOOK_CR *Hook)
Remove a control register hook.
Definition: hook_cr.c:135
static void InitializeListHead(LIST_ENTRY *ListHead)
Definition: introlists.h:69
uint32_t DWORD
Definition: intro_types.h:49
PFUNC_CrWriteHookCallback Callback
Callback.
Definition: hook_cr.h:49
DWORD Cr
The CR number.
Definition: hook_cr.h:47
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
BOOLEAN Disabled
If true, the hook is disabled, and the callback will no longer be called.
Definition: hook_cr.h:48
static INTSTATUS IntHookCrDeleteHook(HOOK_CR *Hook)
Permanently delete a control register hook.
Definition: hook_cr.c:105
#define INT_STATUS_NOT_INITIALIZED_HINT
Definition: introstatus.h:320
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
LIST_HEAD CrHooksList
The list of CR hooks.
Definition: hook_cr.h:35
DWORD Flags
Flags. Can be used by the caller.
Definition: hook_cr.h:46
#define list_for_each(_head, _struct_type, _var)
Definition: introlists.h:41
INTSTATUS IntHookCrSetHook(DWORD Cr, DWORD Flags, PFUNC_CrWriteHookCallback Callback, void *Context, HOOK_CR **Hook)
Set a control register write hook.
Definition: hook_cr.c:11
#define FALSE
Definition: intro_types.h:34
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68