]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
CommitLineData
1c837cd5 1/** @file\r
e8c758dc 2 LockBox SMM driver.\r
d1102dba 3\r
32177f69
JY
4 Caution: This module requires additional review when modified.\r
5 This driver will have external input - communicate buffer in SMM mode.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
d1102dba 8\r
32177f69
JY
9 SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()\r
10 will receive untrusted input and do basic validation.\r
1c837cd5 11\r
f068aa03 12Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
e8c758dc 13\r
9d510e61 14SPDX-License-Identifier: BSD-2-Clause-Patent\r
1c837cd5 15\r
16**/\r
17\r
18#include <PiSmm.h>\r
19#include <Library/UefiDriverEntryPoint.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/UefiRuntimeServicesTableLib.h>\r
22#include <Library/SmmServicesTableLib.h>\r
23#include <Library/BaseLib.h>\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/DebugLib.h>\r
842b1242 26#include <Library/SmmMemLib.h>\r
1c837cd5 27#include <Library/LockBoxLib.h>\r
842b1242 28\r
1c837cd5 29#include <Protocol/SmmReadyToLock.h>\r
30#include <Protocol/SmmCommunication.h>\r
1c837cd5 31#include <Protocol/LockBox.h>\r
32#include <Guid/SmmLockBox.h>\r
33\r
34BOOLEAN mLocked = FALSE;\r
35\r
1c837cd5 36/**\r
37 Dispatch function for SMM lock box save.\r
38\r
32177f69
JY
39 Caution: This function may receive untrusted input.\r
40 Restore buffer and length are external input, so this function will validate\r
41 it is in SMRAM.\r
42\r
d1102dba 43 @param LockBoxParameterSave parameter of lock box save\r
1c837cd5 44**/\r
45VOID\r
46SmmLockBoxSave (\r
47 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave\r
48 )\r
49{\r
50 EFI_STATUS Status;\r
5e5bb2a9 51 EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave;\r
1c837cd5 52\r
53 //\r
54 // Sanity check\r
55 //\r
56 if (mLocked) {\r
57 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
58 LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
59 return ;\r
60 }\r
61\r
5e5bb2a9
SZ
62 CopyMem (&TempLockBoxParameterSave, LockBoxParameterSave, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE));\r
63\r
32177f69
JY
64 //\r
65 // Sanity check\r
66 //\r
842b1242 67 if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterSave.Buffer, (UINTN)TempLockBoxParameterSave.Length)) {\r
9d00d20e 68 DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));\r
32177f69
JY
69 LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
70 return ;\r
71 }\r
ee65b84e 72 //\r
10777573
HW
73 // The SpeculationBarrier() call here is to ensure the above range check for\r
74 // the CommBuffer have been completed before calling into SaveLockBox().\r
ee65b84e 75 //\r
10777573 76 SpeculationBarrier ();\r
32177f69 77\r
1c837cd5 78 //\r
79 // Save data\r
80 //\r
81 Status = SaveLockBox (\r
5e5bb2a9
SZ
82 &TempLockBoxParameterSave.Guid,\r
83 (VOID *)(UINTN)TempLockBoxParameterSave.Buffer,\r
84 (UINTN)TempLockBoxParameterSave.Length\r
1c837cd5 85 );\r
86 LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;\r
87 return ;\r
88}\r
89\r
90/**\r
91 Dispatch function for SMM lock box set attributes.\r
92\r
93 @param LockBoxParameterSetAttributes parameter of lock box set attributes\r
94**/\r
95VOID\r
96SmmLockBoxSetAttributes (\r
97 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes\r
98 )\r
99{\r
100 EFI_STATUS Status;\r
5e5bb2a9 101 EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes;\r
1c837cd5 102\r
103 //\r
104 // Sanity check\r
105 //\r
106 if (mLocked) {\r
107 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
108 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
109 return ;\r
110 }\r
111\r
5e5bb2a9
SZ
112 CopyMem (&TempLockBoxParameterSetAttributes, LockBoxParameterSetAttributes, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES));\r
113\r
1c837cd5 114 //\r
115 // Update data\r
116 //\r
117 Status = SetLockBoxAttributes (\r
5e5bb2a9
SZ
118 &TempLockBoxParameterSetAttributes.Guid,\r
119 TempLockBoxParameterSetAttributes.Attributes\r
1c837cd5 120 );\r
121 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;\r
122 return ;\r
123}\r
124\r
125/**\r
126 Dispatch function for SMM lock box update.\r
127\r
32177f69
JY
128 Caution: This function may receive untrusted input.\r
129 Restore buffer and length are external input, so this function will validate\r
130 it is in SMRAM.\r
131\r
d1102dba 132 @param LockBoxParameterUpdate parameter of lock box update\r
1c837cd5 133**/\r
134VOID\r
135SmmLockBoxUpdate (\r
136 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate\r
137 )\r
138{\r
139 EFI_STATUS Status;\r
5e5bb2a9 140 EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate;\r
1c837cd5 141\r
142 //\r
143 // Sanity check\r
144 //\r
145 if (mLocked) {\r
146 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
147 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
148 return ;\r
149 }\r
150\r
5e5bb2a9
SZ
151 CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE));\r
152\r
32177f69
JY
153 //\r
154 // Sanity check\r
155 //\r
842b1242 156 if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) {\r
9d00d20e 157 DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));\r
32177f69
JY
158 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
159 return ;\r
160 }\r
ee65b84e 161 //\r
10777573
HW
162 // The SpeculationBarrier() call here is to ensure the above range check for\r
163 // the CommBuffer have been completed before calling into UpdateLockBox().\r
ee65b84e 164 //\r
10777573 165 SpeculationBarrier ();\r
32177f69 166\r
1c837cd5 167 //\r
168 // Update data\r
169 //\r
170 Status = UpdateLockBox (\r
5e5bb2a9
SZ
171 &TempLockBoxParameterUpdate.Guid,\r
172 (UINTN)TempLockBoxParameterUpdate.Offset,\r
173 (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer,\r
174 (UINTN)TempLockBoxParameterUpdate.Length\r
1c837cd5 175 );\r
176 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;\r
177 return ;\r
178}\r
179\r
180/**\r
181 Dispatch function for SMM lock box restore.\r
182\r
32177f69
JY
183 Caution: This function may receive untrusted input.\r
184 Restore buffer and length are external input, so this function will validate\r
185 it is in SMRAM.\r
186\r
d1102dba 187 @param LockBoxParameterRestore parameter of lock box restore\r
1c837cd5 188**/\r
189VOID\r
190SmmLockBoxRestore (\r
191 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore\r
192 )\r
193{\r
194 EFI_STATUS Status;\r
5e5bb2a9
SZ
195 EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore;\r
196\r
197 CopyMem (&TempLockBoxParameterRestore, LockBoxParameterRestore, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE));\r
1c837cd5 198\r
199 //\r
200 // Sanity check\r
201 //\r
842b1242 202 if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterRestore.Buffer, (UINTN)TempLockBoxParameterRestore.Length)) {\r
9d00d20e 203 DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));\r
1c837cd5 204 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
205 return ;\r
206 }\r
207\r
208 //\r
209 // Restore data\r
210 //\r
5e5bb2a9 211 if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) {\r
1476a257 212 Status = RestoreLockBox (\r
5e5bb2a9 213 &TempLockBoxParameterRestore.Guid,\r
1476a257 214 NULL,\r
215 NULL\r
216 );\r
217 } else {\r
218 Status = RestoreLockBox (\r
5e5bb2a9
SZ
219 &TempLockBoxParameterRestore.Guid,\r
220 (VOID *)(UINTN)TempLockBoxParameterRestore.Buffer,\r
221 (UINTN *)&TempLockBoxParameterRestore.Length\r
1476a257 222 );\r
a9ae5b37
SZ
223 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)) {\r
224 //\r
225 // Return the actual Length value.\r
226 //\r
f068aa03
SZ
227 LockBoxParameterRestore->Length = TempLockBoxParameterRestore.Length;\r
228 }\r
1476a257 229 }\r
1c837cd5 230 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;\r
231 return ;\r
232}\r
233\r
234/**\r
235 Dispatch function for SMM lock box restore all in place.\r
236\r
237 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place\r
238**/\r
239VOID\r
240SmmLockBoxRestoreAllInPlace (\r
241 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace\r
242 )\r
243{\r
244 EFI_STATUS Status;\r
245\r
246 Status = RestoreAllLockBoxInPlace ();\r
247 LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;\r
248 return ;\r
249}\r
250\r
251/**\r
252 Dispatch function for a Software SMI handler.\r
253\r
32177f69
JY
254 Caution: This function may receive untrusted input.\r
255 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
256\r
1c837cd5 257 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
258 @param Context Points to an optional handler context which was specified when the\r
259 handler was registered.\r
260 @param CommBuffer A pointer to a collection of data in memory that will\r
261 be conveyed from a non-SMM environment into an SMM environment.\r
262 @param CommBufferSize The size of the CommBuffer.\r
263\r
264 @retval EFI_SUCCESS Command is handled successfully.\r
265\r
266**/\r
267EFI_STATUS\r
268EFIAPI\r
269SmmLockBoxHandler (\r
270 IN EFI_HANDLE DispatchHandle,\r
271 IN CONST VOID *Context OPTIONAL,\r
272 IN OUT VOID *CommBuffer OPTIONAL,\r
273 IN OUT UINTN *CommBufferSize OPTIONAL\r
274 )\r
275{\r
276 EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;\r
164a9b67 277 UINTN TempCommBufferSize;\r
1c837cd5 278\r
558f58e3 279 DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Enter\n"));\r
1c837cd5 280\r
164a9b67
SZ
281 //\r
282 // If input is invalid, stop processing this SMI\r
283 //\r
284 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
285 return EFI_SUCCESS;\r
286 }\r
287\r
288 TempCommBufferSize = *CommBufferSize;\r
289\r
32177f69
JY
290 //\r
291 // Sanity check\r
292 //\r
164a9b67 293 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) {\r
32177f69
JY
294 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n"));\r
295 return EFI_SUCCESS;\r
296 }\r
842b1242 297 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
9d00d20e 298 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));\r
32177f69
JY
299 return EFI_SUCCESS;\r
300 }\r
301\r
1c837cd5 302 LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);\r
303\r
304 LockBoxParameterHeader->ReturnStatus = (UINT64)-1;\r
305\r
558f58e3 306 DEBUG ((DEBUG_INFO, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));\r
1c837cd5 307\r
558f58e3 308 DEBUG ((DEBUG_INFO, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));\r
1c837cd5 309\r
310 switch (LockBoxParameterHeader->Command) {\r
311 case EFI_SMM_LOCK_BOX_COMMAND_SAVE:\r
164a9b67 312 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) {\r
32177f69
JY
313 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));\r
314 break;\r
315 }\r
1c837cd5 316 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);\r
317 break;\r
318 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:\r
164a9b67 319 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) {\r
32177f69
JY
320 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));\r
321 break;\r
322 }\r
1c837cd5 323 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);\r
324 break;\r
325 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:\r
164a9b67 326 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) {\r
32177f69
JY
327 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));\r
328 break;\r
329 }\r
1c837cd5 330 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);\r
331 break;\r
332 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:\r
164a9b67 333 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) {\r
32177f69
JY
334 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));\r
335 break;\r
336 }\r
1c837cd5 337 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);\r
338 break;\r
339 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:\r
164a9b67 340 if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) {\r
32177f69
JY
341 DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));\r
342 break;\r
343 }\r
1c837cd5 344 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);\r
345 break;\r
346 default:\r
32177f69 347 DEBUG ((EFI_D_ERROR, "SmmLockBox Command invalid!\n"));\r
1c837cd5 348 break;\r
349 }\r
350\r
351 LockBoxParameterHeader->Command = (UINT32)-1;\r
352\r
558f58e3 353 DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Exit\n"));\r
1c837cd5 354\r
355 return EFI_SUCCESS;\r
356}\r
357\r
358/**\r
359 Smm Ready To Lock event notification handler.\r
360\r
361 It sets a flag indicating that SMRAM has been locked.\r
d1102dba 362\r
1c837cd5 363 @param[in] Protocol Points to the protocol's unique identifier.\r
364 @param[in] Interface Points to the interface instance.\r
365 @param[in] Handle The handle on which the interface was installed.\r
366\r
367 @retval EFI_SUCCESS Notification handler runs successfully.\r
368 **/\r
369EFI_STATUS\r
370EFIAPI\r
371SmmReadyToLockEventNotify (\r
372 IN CONST EFI_GUID *Protocol,\r
373 IN VOID *Interface,\r
374 IN EFI_HANDLE Handle\r
375 )\r
376{\r
377 mLocked = TRUE;\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381/**\r
382 Entry Point for LockBox SMM driver.\r
383\r
384 @param[in] ImageHandle Image handle of this driver.\r
385 @param[in] SystemTable A Pointer to the EFI System Table.\r
386\r
d1102dba 387 @retval EFI_SUCEESS\r
1c837cd5 388 @return Others Some error occurs.\r
389**/\r
390EFI_STATUS\r
391EFIAPI\r
392SmmLockBoxEntryPoint (\r
393 IN EFI_HANDLE ImageHandle,\r
394 IN EFI_SYSTEM_TABLE *SystemTable\r
395 )\r
396{\r
397 EFI_STATUS Status;\r
398 EFI_HANDLE DispatchHandle;\r
399 VOID *Registration;\r
1c837cd5 400\r
401 //\r
402 // Register LockBox communication handler\r
403 //\r
404 Status = gSmst->SmiHandlerRegister (\r
405 SmmLockBoxHandler,\r
406 &gEfiSmmLockBoxCommunicationGuid,\r
407 &DispatchHandle\r
408 );\r
409 ASSERT_EFI_ERROR (Status);\r
410\r
411 //\r
412 // Register SMM Ready To Lock Protocol notification\r
413 //\r
414 Status = gSmst->SmmRegisterProtocolNotify (\r
415 &gEfiSmmReadyToLockProtocolGuid,\r
416 SmmReadyToLockEventNotify,\r
417 &Registration\r
418 );\r
419 ASSERT_EFI_ERROR (Status);\r
420\r
421 //\r
422 // Install NULL to DXE data base as notify\r
423 //\r
424 ImageHandle = NULL;\r
425 Status = gBS->InstallProtocolInterface (\r
426 &ImageHandle,\r
427 &gEfiLockBoxProtocolGuid,\r
428 EFI_NATIVE_INTERFACE,\r
429 NULL\r
430 );\r
431 ASSERT_EFI_ERROR (Status);\r
432\r
433 return Status;\r
434}\r