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