/
KeVerifyContextXStateCetU.c
78 lines (69 loc) · 2.38 KB
/
KeVerifyContextXStateCetU.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
NTSTATUS
KeVerifyContextXStateCetU (
_In_ PKTHREAD Thread,
_In_ PCONTEXT ContextRecord,
_Outptr_ PULONG_PTR ShadowStack
)
{
PXSAVE_CET_U_FORMAT cetData;
PXSAVE_AREA_HEADER xsaveData;
NTSTATUS status;
if (!BooleanFlagOn(Context->Context.ContextFlags, CONTEXT_XSTATE))
{
return STATUS_SUCCESS;
}
//
// Get the address of the CET state from the supplied context
//
cetData = (PXSAVE_CET_U_FORMAT)RtlLocateExtendedFeature2((PCONTEXT_EX)(Context + 1),
XSTATE_CET_U,
&SharedUserData.XState,
NULL);
if (cetData == NULL)
{
return STATUS_SUCCESS;
}
*ShadowStack = __readmsr(MSR_IA32_PL3_SSP);
//
// Check if the context contains values for CET registers.
// If it doesn't, it means CET registers will not be set, and
// will disable CET if it was previously enabled.
//
xsaveData = (PXSAVE_AREA_HEADER)RTL_CONTEXT_CHUNK(Context, XState);
if (Thread->CetUserShadowStack != FALSE)
{
if (!BooleanFlagOn(xsaveData->Mask, XSTATE_MASK_CET_U))
{
//
// If the thread has CET enabled but the new context doesn't have
// CET registers in it, set the CET registers in the context to
// the current CET values.
//
SetFlag(xsaveData->Mask, XSTATE_MASK_CET_U);
cetData->Ia32CetUMsr = MSR_IA32_CET_SHSTK_EN;
cetData->Ia32Pl3SspMsr = *ShadowStack;
return STATUS_SUCCESS;
}
//
// Verify that the new Ssp value is inside the shadow stack
//
status = KiVerifyContextXStateCetUEnabled(cetData, *ShadowStack);
if (NT_SUCCESS(status))
{
return STATUS_SUCCESS;
}
return status;
}
//
// If the thread doesn't have CET enabled and the new context doesn't
// have CET registers, or the CET mask is set but the CET registers
// don't hold any value, allow because the CET state will not change.
//
if (!(BooleanFlagOn(xsaveData->Mask, XSTATE_MASK_CET_U)) ||
((cetData->Ia32CetUMsr == 0) &&
(cetData->Ia32Pl3SspMsr == NULL)))
{
return STATUS_SUCCESS;
}
return STATUS_SET_CONTEXT_DENIED;
}