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 This program and the accompanying materials
15 are licensed and made available under the terms and conditions
16 of the BSD License which accompanies this distribution. The
17 full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include <Library/UefiDriverEntryPoint.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/UefiRuntimeServicesTableLib.h>
29 #include <Library/SmmServicesTableLib.h>
30 #include <Library/BaseLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/SmmMemLib.h>
34 #include <Library/LockBoxLib.h>
36 #include <Protocol/SmmReadyToLock.h>
37 #include <Protocol/SmmCommunication.h>
38 #include <Protocol/LockBox.h>
39 #include <Guid/SmmLockBox.h>
41 BOOLEAN mLocked
= FALSE
;
44 Dispatch function for SMM lock box save.
46 Caution: This function may receive untrusted input.
47 Restore buffer and length are external input, so this function will validate
50 @param LockBoxParameterSave parameter of lock box save
54 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*LockBoxParameterSave
58 EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave
;
64 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
65 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
69 CopyMem (&TempLockBoxParameterSave
, LockBoxParameterSave
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE
));
74 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterSave
.Buffer
, (UINTN
)TempLockBoxParameterSave
.Length
)) {
75 DEBUG ((EFI_D_ERROR
, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));
76 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
80 // The AsmLfence() call here is to ensure the above range check for the
81 // CommBuffer have been completed before calling into SaveLockBox().
88 Status
= SaveLockBox (
89 &TempLockBoxParameterSave
.Guid
,
90 (VOID
*)(UINTN
)TempLockBoxParameterSave
.Buffer
,
91 (UINTN
)TempLockBoxParameterSave
.Length
93 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)Status
;
98 Dispatch function for SMM lock box set attributes.
100 @param LockBoxParameterSetAttributes parameter of lock box set attributes
103 SmmLockBoxSetAttributes (
104 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*LockBoxParameterSetAttributes
108 EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes
;
114 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
115 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
119 CopyMem (&TempLockBoxParameterSetAttributes
, LockBoxParameterSetAttributes
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
));
124 Status
= SetLockBoxAttributes (
125 &TempLockBoxParameterSetAttributes
.Guid
,
126 TempLockBoxParameterSetAttributes
.Attributes
128 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)Status
;
133 Dispatch function for SMM lock box update.
135 Caution: This function may receive untrusted input.
136 Restore buffer and length are external input, so this function will validate
139 @param LockBoxParameterUpdate parameter of lock box update
143 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*LockBoxParameterUpdate
147 EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate
;
153 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
154 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
158 CopyMem (&TempLockBoxParameterUpdate
, LockBoxParameterUpdate
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
));
163 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterUpdate
.Buffer
, (UINTN
)TempLockBoxParameterUpdate
.Length
)) {
164 DEBUG ((EFI_D_ERROR
, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));
165 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
169 // The AsmLfence() call here is to ensure the above range check for the
170 // CommBuffer have been completed before calling into UpdateLockBox().
177 Status
= UpdateLockBox (
178 &TempLockBoxParameterUpdate
.Guid
,
179 (UINTN
)TempLockBoxParameterUpdate
.Offset
,
180 (VOID
*)(UINTN
)TempLockBoxParameterUpdate
.Buffer
,
181 (UINTN
)TempLockBoxParameterUpdate
.Length
183 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)Status
;
188 Dispatch function for SMM lock box restore.
190 Caution: This function may receive untrusted input.
191 Restore buffer and length are external input, so this function will validate
194 @param LockBoxParameterRestore parameter of lock box restore
198 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*LockBoxParameterRestore
202 EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore
;
204 CopyMem (&TempLockBoxParameterRestore
, LockBoxParameterRestore
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
));
209 if (!SmmIsBufferOutsideSmmValid ((UINTN
)TempLockBoxParameterRestore
.Buffer
, (UINTN
)TempLockBoxParameterRestore
.Length
)) {
210 DEBUG ((EFI_D_ERROR
, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));
211 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
218 if ((TempLockBoxParameterRestore
.Length
== 0) && (TempLockBoxParameterRestore
.Buffer
== 0)) {
219 Status
= RestoreLockBox (
220 &TempLockBoxParameterRestore
.Guid
,
225 Status
= RestoreLockBox (
226 &TempLockBoxParameterRestore
.Guid
,
227 (VOID
*)(UINTN
)TempLockBoxParameterRestore
.Buffer
,
228 (UINTN
*)&TempLockBoxParameterRestore
.Length
230 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_SUCCESS
)) {
232 // Return the actual Length value.
234 LockBoxParameterRestore
->Length
= TempLockBoxParameterRestore
.Length
;
237 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)Status
;
242 Dispatch function for SMM lock box restore all in place.
244 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
247 SmmLockBoxRestoreAllInPlace (
248 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*LockBoxParameterRestoreAllInPlace
253 Status
= RestoreAllLockBoxInPlace ();
254 LockBoxParameterRestoreAllInPlace
->Header
.ReturnStatus
= (UINT64
)Status
;
259 Dispatch function for a Software SMI handler.
261 Caution: This function may receive untrusted input.
262 Communicate buffer and buffer size are external input, so this function will do basic validation.
264 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
265 @param Context Points to an optional handler context which was specified when the
266 handler was registered.
267 @param CommBuffer A pointer to a collection of data in memory that will
268 be conveyed from a non-SMM environment into an SMM environment.
269 @param CommBufferSize The size of the CommBuffer.
271 @retval EFI_SUCCESS Command is handled successfully.
277 IN EFI_HANDLE DispatchHandle
,
278 IN CONST VOID
*Context OPTIONAL
,
279 IN OUT VOID
*CommBuffer OPTIONAL
,
280 IN OUT UINTN
*CommBufferSize OPTIONAL
283 EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*LockBoxParameterHeader
;
284 UINTN TempCommBufferSize
;
286 DEBUG ((DEBUG_INFO
, "SmmLockBox SmmLockBoxHandler Enter\n"));
289 // If input is invalid, stop processing this SMI
291 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
295 TempCommBufferSize
= *CommBufferSize
;
300 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER
)) {
301 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size invalid!\n"));
304 if (!SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
305 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));
309 LockBoxParameterHeader
= (EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
311 LockBoxParameterHeader
->ReturnStatus
= (UINT64
)-1;
313 DEBUG ((DEBUG_INFO
, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN
)LockBoxParameterHeader
));
315 DEBUG ((DEBUG_INFO
, "SmmLockBox Command - %x\n", (UINTN
)LockBoxParameterHeader
->Command
));
317 switch (LockBoxParameterHeader
->Command
) {
318 case EFI_SMM_LOCK_BOX_COMMAND_SAVE
:
319 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE
)) {
320 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
323 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*)(UINTN
)LockBoxParameterHeader
);
325 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE
:
326 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
)) {
327 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
330 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*)(UINTN
)LockBoxParameterHeader
);
332 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE
:
333 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
)) {
334 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
337 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*)(UINTN
)LockBoxParameterHeader
);
339 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES
:
340 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
)) {
341 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
344 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*)(UINTN
)LockBoxParameterHeader
);
346 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE
:
347 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
)) {
348 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
351 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*)(UINTN
)LockBoxParameterHeader
);
354 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command invalid!\n"));
358 LockBoxParameterHeader
->Command
= (UINT32
)-1;
360 DEBUG ((DEBUG_INFO
, "SmmLockBox SmmLockBoxHandler Exit\n"));
366 Smm Ready To Lock event notification handler.
368 It sets a flag indicating that SMRAM has been locked.
370 @param[in] Protocol Points to the protocol's unique identifier.
371 @param[in] Interface Points to the interface instance.
372 @param[in] Handle The handle on which the interface was installed.
374 @retval EFI_SUCCESS Notification handler runs successfully.
378 SmmReadyToLockEventNotify (
379 IN CONST EFI_GUID
*Protocol
,
389 Entry Point for LockBox SMM driver.
391 @param[in] ImageHandle Image handle of this driver.
392 @param[in] SystemTable A Pointer to the EFI System Table.
395 @return Others Some error occurs.
399 SmmLockBoxEntryPoint (
400 IN EFI_HANDLE ImageHandle
,
401 IN EFI_SYSTEM_TABLE
*SystemTable
405 EFI_HANDLE DispatchHandle
;
409 // Register LockBox communication handler
411 Status
= gSmst
->SmiHandlerRegister (
413 &gEfiSmmLockBoxCommunicationGuid
,
416 ASSERT_EFI_ERROR (Status
);
419 // Register SMM Ready To Lock Protocol notification
421 Status
= gSmst
->SmmRegisterProtocolNotify (
422 &gEfiSmmReadyToLockProtocolGuid
,
423 SmmReadyToLockEventNotify
,
426 ASSERT_EFI_ERROR (Status
);
429 // Install NULL to DXE data base as notify
432 Status
= gBS
->InstallProtocolInterface (
434 &gEfiLockBoxProtocolGuid
,
435 EFI_NATIVE_INTERFACE
,
438 ASSERT_EFI_ERROR (Status
);