4 Caution: This module requires additional review when modified.
5 This driver will have external input - communicate buffer in SMM mode.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()
10 will receive untrusted input and do basic validation.
12 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
14 SPDX-License-Identifier: BSD-2-Clause-Patent
19 #include <Library/UefiDriverEntryPoint.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Library/SmmServicesTableLib.h>
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/SmmMemLib.h>
27 #include <Library/LockBoxLib.h>
29 #include <Protocol/SmmReadyToLock.h>
30 #include <Protocol/SmmCommunication.h>
31 #include <Protocol/LockBox.h>
32 #include <Guid/SmmLockBox.h>
34 BOOLEAN mLocked
= FALSE
;
37 Dispatch function for SMM lock box save.
39 Caution: This function may receive untrusted input.
40 Restore buffer and length are external input, so this function will validate
43 @param LockBoxParameterSave parameter of lock box save
47 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*LockBoxParameterSave
51 EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave
;
57 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
58 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
62 CopyMem (&TempLockBoxParameterSave
, LockBoxParameterSave
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE
));
67 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterSave
.Buffer
, (UINTN
)TempLockBoxParameterSave
.Length
)) {
68 DEBUG ((EFI_D_ERROR
, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));
69 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
73 // The SpeculationBarrier() call here is to ensure the above range check for
74 // the CommBuffer have been completed before calling into SaveLockBox().
76 SpeculationBarrier ();
81 Status
= SaveLockBox (
82 &TempLockBoxParameterSave
.Guid
,
83 (VOID
*)(UINTN
)TempLockBoxParameterSave
.Buffer
,
84 (UINTN
)TempLockBoxParameterSave
.Length
86 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)Status
;
91 Dispatch function for SMM lock box set attributes.
93 @param LockBoxParameterSetAttributes parameter of lock box set attributes
96 SmmLockBoxSetAttributes (
97 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*LockBoxParameterSetAttributes
101 EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes
;
107 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
108 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
112 CopyMem (&TempLockBoxParameterSetAttributes
, LockBoxParameterSetAttributes
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
));
117 Status
= SetLockBoxAttributes (
118 &TempLockBoxParameterSetAttributes
.Guid
,
119 TempLockBoxParameterSetAttributes
.Attributes
121 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)Status
;
126 Dispatch function for SMM lock box update.
128 Caution: This function may receive untrusted input.
129 Restore buffer and length are external input, so this function will validate
132 @param LockBoxParameterUpdate parameter of lock box update
136 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*LockBoxParameterUpdate
140 EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate
;
146 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
147 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
151 CopyMem (&TempLockBoxParameterUpdate
, LockBoxParameterUpdate
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
));
156 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterUpdate
.Buffer
, (UINTN
)TempLockBoxParameterUpdate
.Length
)) {
157 DEBUG ((EFI_D_ERROR
, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));
158 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
162 // The SpeculationBarrier() call here is to ensure the above range check for
163 // the CommBuffer have been completed before calling into UpdateLockBox().
165 SpeculationBarrier ();
170 Status
= UpdateLockBox (
171 &TempLockBoxParameterUpdate
.Guid
,
172 (UINTN
)TempLockBoxParameterUpdate
.Offset
,
173 (VOID
*)(UINTN
)TempLockBoxParameterUpdate
.Buffer
,
174 (UINTN
)TempLockBoxParameterUpdate
.Length
176 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)Status
;
181 Dispatch function for SMM lock box restore.
183 Caution: This function may receive untrusted input.
184 Restore buffer and length are external input, so this function will validate
187 @param LockBoxParameterRestore parameter of lock box restore
191 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*LockBoxParameterRestore
195 EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore
;
197 CopyMem (&TempLockBoxParameterRestore
, LockBoxParameterRestore
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
));
202 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterRestore
.Buffer
, (UINTN
)TempLockBoxParameterRestore
.Length
)) {
203 DEBUG ((EFI_D_ERROR
, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));
204 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
211 if ((TempLockBoxParameterRestore
.Length
== 0) && (TempLockBoxParameterRestore
.Buffer
== 0)) {
212 Status
= RestoreLockBox (
213 &TempLockBoxParameterRestore
.Guid
,
218 Status
= RestoreLockBox (
219 &TempLockBoxParameterRestore
.Guid
,
220 (VOID
*)(UINTN
)TempLockBoxParameterRestore
.Buffer
,
221 (UINTN
*)&TempLockBoxParameterRestore
.Length
223 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_SUCCESS
)) {
225 // Return the actual Length value.
227 LockBoxParameterRestore
->Length
= TempLockBoxParameterRestore
.Length
;
230 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)Status
;
235 Dispatch function for SMM lock box restore all in place.
237 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
240 SmmLockBoxRestoreAllInPlace (
241 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*LockBoxParameterRestoreAllInPlace
246 Status
= RestoreAllLockBoxInPlace ();
247 LockBoxParameterRestoreAllInPlace
->Header
.ReturnStatus
= (UINT64
)Status
;
252 Dispatch function for a Software SMI handler.
254 Caution: This function may receive untrusted input.
255 Communicate buffer and buffer size are external input, so this function will do basic validation.
257 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
258 @param Context Points to an optional handler context which was specified when the
259 handler was registered.
260 @param CommBuffer A pointer to a collection of data in memory that will
261 be conveyed from a non-SMM environment into an SMM environment.
262 @param CommBufferSize The size of the CommBuffer.
264 @retval EFI_SUCCESS Command is handled successfully.
270 IN EFI_HANDLE DispatchHandle
,
271 IN CONST VOID
*Context OPTIONAL
,
272 IN OUT VOID
*CommBuffer OPTIONAL
,
273 IN OUT UINTN
*CommBufferSize OPTIONAL
276 EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*LockBoxParameterHeader
;
277 UINTN TempCommBufferSize
;
279 DEBUG ((DEBUG_INFO
, "SmmLockBox SmmLockBoxHandler Enter\n"));
282 // If input is invalid, stop processing this SMI
284 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
288 TempCommBufferSize
= *CommBufferSize
;
293 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER
)) {
294 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size invalid!\n"));
297 if (!SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
298 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));
302 LockBoxParameterHeader
= (EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
304 LockBoxParameterHeader
->ReturnStatus
= (UINT64
)-1;
306 DEBUG ((DEBUG_INFO
, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN
)LockBoxParameterHeader
));
308 DEBUG ((DEBUG_INFO
, "SmmLockBox Command - %x\n", (UINTN
)LockBoxParameterHeader
->Command
));
310 switch (LockBoxParameterHeader
->Command
) {
311 case EFI_SMM_LOCK_BOX_COMMAND_SAVE
:
312 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE
)) {
313 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
316 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*)(UINTN
)LockBoxParameterHeader
);
318 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE
:
319 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
)) {
320 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
323 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*)(UINTN
)LockBoxParameterHeader
);
325 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE
:
326 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
)) {
327 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
330 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*)(UINTN
)LockBoxParameterHeader
);
332 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES
:
333 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
)) {
334 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
337 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*)(UINTN
)LockBoxParameterHeader
);
339 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE
:
340 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
)) {
341 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
344 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*)(UINTN
)LockBoxParameterHeader
);
347 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command invalid!\n"));
351 LockBoxParameterHeader
->Command
= (UINT32
)-1;
353 DEBUG ((DEBUG_INFO
, "SmmLockBox SmmLockBoxHandler Exit\n"));
359 Smm Ready To Lock event notification handler.
361 It sets a flag indicating that SMRAM has been locked.
363 @param[in] Protocol Points to the protocol's unique identifier.
364 @param[in] Interface Points to the interface instance.
365 @param[in] Handle The handle on which the interface was installed.
367 @retval EFI_SUCCESS Notification handler runs successfully.
371 SmmReadyToLockEventNotify (
372 IN CONST EFI_GUID
*Protocol
,
382 Entry Point for LockBox SMM driver.
384 @param[in] ImageHandle Image handle of this driver.
385 @param[in] SystemTable A Pointer to the EFI System Table.
388 @return Others Some error occurs.
392 SmmLockBoxEntryPoint (
393 IN EFI_HANDLE ImageHandle
,
394 IN EFI_SYSTEM_TABLE
*SystemTable
398 EFI_HANDLE DispatchHandle
;
402 // Register LockBox communication handler
404 Status
= gSmst
->SmiHandlerRegister (
406 &gEfiSmmLockBoxCommunicationGuid
,
409 ASSERT_EFI_ERROR (Status
);
412 // Register SMM Ready To Lock Protocol notification
414 Status
= gSmst
->SmmRegisterProtocolNotify (
415 &gEfiSmmReadyToLockProtocolGuid
,
416 SmmReadyToLockEventNotify
,
419 ASSERT_EFI_ERROR (Status
);
422 // Install NULL to DXE data base as notify
425 Status
= gBS
->InstallProtocolInterface (
427 &gEfiLockBoxProtocolGuid
,
428 EFI_NATIVE_INTERFACE
,
431 ASSERT_EFI_ERROR (Status
);