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