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