From 9fd115f20a0ab85b91328ec025f0e5a946eefcbb Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov Date: Thu, 8 Feb 2024 19:15:55 +0300 Subject: [PATCH] Ring3: Fixed SysCallInstallMultipleProtocolInterfaces. --- MdeModulePkg/Core/Dxe/SysCall/BootServices.c | 69 ++++++++++++------- .../Dxe/SysCall/X64/CoreBootServices.nasm | 59 ++++++++++++++++ MdePkg/Include/Uefi/UefiSpec.h | 2 + .../Ring3UefiBootServicesTableLib.c | 24 ++++++- 4 files changed, 128 insertions(+), 26 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c index df73724486..ad07e0c635 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -11,8 +11,6 @@ #include #include -#define MAX_LIST 32 - VOID EFIAPI DisableSMAP ( @@ -25,6 +23,15 @@ EnableSMAP ( VOID ); +EFI_STATUS +EFIAPI +CallInstallMultipleProtocolInterfaces ( + IN EFI_HANDLE *Handle, + IN VOID **ArgList, + IN UINT32 ArgListSize, + IN VOID *Function + ); + VOID EFIAPI InternalEnterUserImage ( @@ -73,7 +80,9 @@ CallBootService ( EFI_HANDLE Argument5; UINT32 Argument6; UINT32 Index; - UINTN *ArgList[MAX_LIST]; + VOID **UserArgList; + VOID *CoreArgList[MAX_LIST]; + EFI_HANDLE CoreHandle; EFI_DRIVER_BINDING_PROTOCOL *CoreDriverBinding; @@ -92,8 +101,9 @@ CallBootService ( CoreProtocol = &gEfiDevicePathUtilitiesProtocolGuid; MemoryCoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL); } else { - CoreProtocol = NULL; - MemoryCoreSize = 0; + DEBUG ((DEBUG_ERROR, "Ring0: Unknown protocol.\n")); + EnableSMAP (); + return EFI_INVALID_PARAMETER; } EnableSMAP (); @@ -129,8 +139,9 @@ CallBootService ( CoreProtocol = &gEfiLoadedImageProtocolGuid; MemoryCoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL); } else { - CoreProtocol = NULL; - MemoryCoreSize = 0; + DEBUG ((DEBUG_ERROR, "Ring0: Unknown protocol.\n")); + EnableSMAP (); + return EFI_INVALID_PARAMETER; } Argument4 = (EFI_HANDLE)UserRsp->Arguments[4]; @@ -165,31 +176,34 @@ CallBootService ( // ... // DisableSMAP (); - for (Index = 0; ((VOID *)UserRsp->Arguments[Index] != NULL) && (Index < MAX_LIST); Index += 2) { - if (CompareGuid ((EFI_GUID *)UserRsp->Arguments[Index], &gEfiDriverBindingProtocolGuid)) { - ArgList[Index] = (UINTN *)&gEfiDriverBindingProtocolGuid; + CoreHandle = *(EFI_HANDLE *)CoreRbp->Argument1; + UserArgList = (VOID **)CoreRbp->Argument2; + + for (Index = 0; UserArgList[Index] != NULL; ++Index) { + if (CompareGuid ((EFI_GUID *)UserArgList[Index], &gEfiDriverBindingProtocolGuid)) { + CoreArgList[Index] = (VOID *)&gEfiDriverBindingProtocolGuid; MemoryCoreSize = sizeof (EFI_DRIVER_BINDING_PROTOCOL); - } else if (CompareGuid ((EFI_GUID *)UserRsp->Arguments[Index], &gEfiComponentNameProtocolGuid)) { - ArgList[Index] = (UINTN *)&gEfiComponentNameProtocolGuid; + continue; + } else if (CompareGuid ((EFI_GUID *)UserArgList[Index], &gEfiComponentNameProtocolGuid)) { + CoreArgList[Index] = (VOID *)&gEfiComponentNameProtocolGuid; MemoryCoreSize = sizeof (EFI_COMPONENT_NAME_PROTOCOL); - } else { - DEBUG ((DEBUG_INFO, "Ring0: Argument %d is not a GUID.\n", Index)); + continue; + } else if ((Index % 2) == 0) { + DEBUG ((DEBUG_ERROR, "Ring0: Unknown protocol.\n")); + EnableSMAP (); + return EFI_INVALID_PARAMETER; } - ArgList[Index + 1] = AllocateCopyPool (MemoryCoreSize, (VOID *)UserRsp->Arguments[Index + 1]); + CoreArgList[Index] = AllocateCopyPool (MemoryCoreSize, (VOID *)UserArgList[Index]); } EnableSMAP (); - if ((Index == MAX_LIST) && ((VOID *)UserRsp->Arguments[Index] != NULL)) { - DEBUG ((DEBUG_ERROR, "Ring0: Too many protocols!\n")); - return EFI_OUT_OF_RESOURCES; - } - - ArgList[Index] = NULL; + ASSERT (Index < MAX_LIST); + CoreArgList[Index] = NULL; - for (Index = 0; ArgList[Index] != NULL; Index += 2) { - if (CompareGuid ((EFI_GUID *)ArgList[Index], &gEfiDriverBindingProtocolGuid)) { - CoreDriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)ArgList[Index + 1]; + for (Index = 0; CoreArgList[Index] != NULL; Index += 2) { + if (CompareGuid ((EFI_GUID *)CoreArgList[Index], &gEfiDriverBindingProtocolGuid)) { + CoreDriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)CoreArgList[Index + 1]; mUserDriverBindingSupported = CoreDriverBinding->Supported; mUserDriverBindingStart = CoreDriverBinding->Start; @@ -201,7 +215,12 @@ CallBootService ( } } - Status = gBS->InstallMultipleProtocolInterfaces ((EFI_HANDLE *)ArgList); + Status = CallInstallMultipleProtocolInterfaces ( + &CoreHandle, + CoreArgList, + Index + 1, + (VOID *)gBS->InstallMultipleProtocolInterfaces + ); return Status; diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm index 83508675f2..d3f8f2635c 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm @@ -13,6 +13,13 @@ extern ASM_PFX(gCoreSysCallStackTop) extern ASM_PFX(gRing3CallStackTop) extern ASM_PFX(gRing3EntryPoint) +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; DisableSMAP ( +; VOID +; ); +;------------------------------------------------------------------------------ global ASM_PFX(DisableSMAP) ASM_PFX(DisableSMAP): pushfq @@ -22,6 +29,13 @@ ASM_PFX(DisableSMAP): popfq ret +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableSMAP ( +; VOID +; ); +;------------------------------------------------------------------------------ global ASM_PFX(EnableSMAP) ASM_PFX(EnableSMAP): pushfq @@ -31,6 +45,51 @@ ASM_PFX(EnableSMAP): popfq ret +;------------------------------------------------------------------------------ +; EFI_STATUS +; EFIAPI +; CallInstallMultipleProtocolInterfaces ( +; IN EFI_HANDLE *Handle, +; IN VOID **ArgList, +; IN UINT32 ArgListSize, +; IN VOID *Function +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CallInstallMultipleProtocolInterfaces) +ASM_PFX(CallInstallMultipleProtocolInterfaces): + push r12 + + ; Save funtion input. + mov rax, rdx + mov r10, r8 + mov r11, r9 + + ; Prepare registers for call. + mov rdx, [rax] + mov r8, [rax + 8] + mov r9, [rax + 8*2] + + ; Prepare stack for call. + lea rax, [rax + r10 * 8] + mov r12, r10 +copy: + sub rax, 8 + push qword [rax] + cmp r10, 0 + sub r10, 1 + jne copy + push rcx + + call r11 + + ; Step over Function arguments. + pop rcx + lea rsp, [rsp + r12 * 8] + + pop r12 + + ret + ;------------------------------------------------------------------------------ ; EFI_STATUS ; EFIAPI diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h index 336ee71de7..8f0d6f9a48 100644 --- a/MdePkg/Include/Uefi/UefiSpec.h +++ b/MdePkg/Include/Uefi/UefiSpec.h @@ -1969,6 +1969,8 @@ typedef enum { SysCallMax } SYS_CALL_TYPE; +#define MAX_LIST 32 + /// /// Contains a set of GUID/pointer pairs comprised of the ConfigurationTable field in the /// EFI System Table. diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c index 27f0c39fdd..c5cf04a03e 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c @@ -564,9 +564,31 @@ Ring3InstallMultipleProtocolInterfaces ( ... ) { + VA_LIST Marker; + VOID *Argument; + VOID *ArgList[MAX_LIST]; + UINTN Index; + + VA_START (Marker, Handle); + for (Index = 0; Index < MAX_LIST; ++Index) { + Argument = VA_ARG (Marker, VOID *); + ArgList[Index] = Argument; + + if (Argument == NULL) { + break; + } + } + VA_END (Marker); + + if (Index == MAX_LIST) { + DEBUG ((DEBUG_ERROR, "Ring3: Too many arguments\n")); + return EFI_INVALID_PARAMETER; + } + return SysCall ( SysCallInstallMultipleProtocolInterfaces, - Handle + Handle, + ArgList ); }