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