From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 14904D801DB for ; Mon, 30 Oct 2023 20:31:38 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=u817+V9vl/KvZ+7GgHiIZoHZ10on07j5UHY5oQe9IdU=; c=relaxed/simple; d=groups.io; h=DKIM-Filter:From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1698697897; v=1; b=eKS+x/Qx84voPFwctrN0d5nBN7JNmsfJdsA8GuFDRjc4RErnPRyb5HvUsAeDVkrOiCx3yCR3 VUL3n/cmwXde27avXfm2qmjZEiFxf/htNj/IjFCpZ/b/hwqh40eRBy7D9LAmfZeNbHl3wOsx0qc OVBjqWjT+nhocGN0FARs8NBM= X-Received: by 127.0.0.2 with SMTP id oxHyYY7687511xLMyHIxGWNG; Mon, 30 Oct 2023 13:31:37 -0700 X-Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by mx.groups.io with SMTP id smtpd.web10.169258.1698697897092192386 for ; Mon, 30 Oct 2023 13:31:37 -0700 X-Received: from localhost.localdomain (unknown [47.201.241.95]) by linux.microsoft.com (Postfix) with ESMTPSA id DBCE720B74C1; Mon, 30 Oct 2023 13:31:35 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com DBCE720B74C1 From: "Michael Kubacki" To: devel@edk2.groups.io Cc: Dandan Bi , Hao A Wu , Jian J Wang , Liming Gao , Ard Biesheuvel Subject: [edk2-devel] [PATCH v3 1/4] MdeModulePkg/VariablePolicy: Add more granular variable policy querying Date: Mon, 30 Oct 2023 16:31:09 -0400 Message-ID: <20231030203112.736-2-mikuback@linux.microsoft.com> In-Reply-To: <20231030203112.736-1-mikuback@linux.microsoft.com> References: <20231030203112.736-1-mikuback@linux.microsoft.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,mikuback@linux.microsoft.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: 8kEiCShJeDtcLMZaxC1n5Og1x7686176AA= Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b="eKS+x/Qx"; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=linux.microsoft.com (policy=none) From: Michael Kubacki Introduces two new APIs to EDKII_VARIABLE_POLICY_PROTOCOL: 1. GetVariablePolicyInfo() 2. GetLockOnVariableStateVariablePolicyInfo() These allow a caller to retrieve policy information associated with a UEFI variable given the variable name and vendor GUID. GetVariablePolicyInfo() - Returns the variable policy applied to the UEFI variable. If the variable policy is applied toward an individual UEFI variable, that name can optionally be returned. GetLockOnVariableStateVariablePolicyInfo() - Returns the Lock on Variable State policy applied to the UEFI variable. If the Lock on Variable State policy is applied to a specific variable name, that name can optionally be returned. These functions can be useful for a variety of purposes such as auditing, testing, and functional flows. Also fixed some variable name typos in code touched by the changes. Cc: Dandan Bi Cc: Hao A Wu Cc: Jian J Wang Cc: Liming Gao Signed-off-by: Michael Kubacki Reviewed-by: Ard Biesheuvel Reviewed-by: Liming Gao --- MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c | 174 = ++++++++-- MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c | 304 = +++++++++++++++++ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c | 4 = +- MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c | 346 = +++++++++++++++++++- MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h | 39 = ++- MdeModulePkg/Include/Library/VariablePolicyLib.h | 107 = ++++++ MdeModulePkg/Include/Protocol/VariablePolicy.h | 133 = +++++++- MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf | 1 = + 8 files changed, 1062 insertions(+), 46 deletions(-) diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c b= /MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c index 5de46133bb26..1448af85555a 100644 --- a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c @@ -76,14 +76,20 @@ VarCheckPolicyLibMmiHandler ( VOID *InternalCommBuffer; EFI_STATUS Status; EFI_STATUS SubCommandStatus; - VAR_CHECK_POLICY_COMM_HEADER *PolicyCommmHeader; - VAR_CHECK_POLICY_COMM_HEADER *InternalPolicyCommmHeader; + VAR_CHECK_POLICY_COMM_HEADER *PolicyCommHeader; + VAR_CHECK_POLICY_COMM_HEADER *InternalPolicyCommHeader; VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *IsEnabledParams; VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsIn; VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsOut; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *GetInfoParamsInternal; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *GetInfoParamsExternal; + CHAR16 *InternalCopyOfOutputVariable= Name; + CHAR16 *ExternalCopyOfOutputVariable= Name; UINT8 *DumpInputBuffer; UINT8 *DumpOutputBuffer; + UINTN AllowedOutputVariableNameSize= ; UINTN DumpTotalPages; + UINTN LocalSize; VARIABLE_POLICY_ENTRY *PolicyEntry; UINTN ExpectedSize; UINT32 TempSize; @@ -122,21 +128,21 @@ VarCheckPolicyLibMmiHandler ( // InternalCommBuffer =3D &mSecurityEvalBuffer[0]; CopyMem (InternalCommBuffer, CommBuffer, InternalCommBufferSize); - PolicyCommmHeader =3D CommBuffer; - InternalPolicyCommmHeader =3D InternalCommBuffer; + PolicyCommHeader =3D CommBuffer; + InternalPolicyCommHeader =3D InternalCommBuffer; // Check the revision and the signature of the comm header. - if ((InternalPolicyCommmHeader->Signature !=3D VAR_CHECK_POLICY_COMM_S= IG) || - (InternalPolicyCommmHeader->Revision !=3D VAR_CHECK_POLICY_COMM_RE= VISION)) + if ((InternalPolicyCommHeader->Signature !=3D VAR_CHECK_POLICY_COMM_SI= G) || + (InternalPolicyCommHeader->Revision !=3D VAR_CHECK_POLICY_COMM_REV= ISION)) { DEBUG ((DEBUG_INFO, "%a - Signature or revision are incorrect!\n", _= _func__)); // We have verified the buffer is not null and have enough size to h= old Result field. - PolicyCommmHeader->Result =3D EFI_INVALID_PARAMETER; + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; return EFI_SUCCESS; } =20 // If we're in the middle of a paginated dump and any other command is= sent, // pagination cache must be cleared. - if ((mPaginationCache !=3D NULL) && (InternalPolicyCommmHeader->Comman= d !=3D mCurrentPaginationCommand)) { + if ((mPaginationCache !=3D NULL) && (InternalPolicyCommHeader->Command= !=3D mCurrentPaginationCommand)) { FreePool (mPaginationCache); mPaginationCache =3D NULL; mPaginationCacheSize =3D 0; @@ -146,10 +152,10 @@ VarCheckPolicyLibMmiHandler ( // // Now we can process the command as it was sent. // - PolicyCommmHeader->Result =3D EFI_ABORTED; // Set a default return = for incomplete commands. - switch (InternalPolicyCommmHeader->Command) { + PolicyCommHeader->Result =3D EFI_ABORTED; // Set a default return f= or incomplete commands. + switch (InternalPolicyCommHeader->Command) { case VAR_CHECK_POLICY_COMMAND_DISABLE: - PolicyCommmHeader->Result =3D DisableVariablePolicy (); + PolicyCommHeader->Result =3D DisableVariablePolicy (); break; =20 case VAR_CHECK_POLICY_COMMAND_IS_ENABLED: @@ -158,14 +164,14 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize +=3D sizeof (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS)= ; if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __fu= nc__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result =3D EFI_INVALID_PARAMETER; + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; break; } =20 // Now that we know we've got a valid size, we can fill in the res= t of the data. - IsEnabledParams =3D (VAR_CHECK_POLICY_COMM_IS_ENABLED_PA= RAMS *)((UINT8 *)CommBuffer + sizeof (VAR_CHECK_POLICY_COMM_HEADER)); - IsEnabledParams->State =3D IsVariablePolicyEnabled (); - PolicyCommmHeader->Result =3D EFI_SUCCESS; + IsEnabledParams =3D (VAR_CHECK_POLICY_COMM_IS_ENABLED_PAR= AMS *)((UINT8 *)CommBuffer + sizeof (VAR_CHECK_POLICY_COMM_HEADER)); + IsEnabledParams->State =3D IsVariablePolicyEnabled (); + PolicyCommHeader->Result =3D EFI_SUCCESS; break; =20 case VAR_CHECK_POLICY_COMMAND_REGISTER: @@ -174,7 +180,7 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize +=3D sizeof (VARIABLE_POLICY_ENTRY); if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __fu= nc__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result =3D EFI_INVALID_PARAMETER; + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; break; } =20 @@ -187,11 +193,11 @@ VarCheckPolicyLibMmiHandler ( (InternalCommBufferSize < ExpectedSize)) { DEBUG ((DEBUG_INFO, "%a - Bad policy entry contents!\n", __func_= _)); - PolicyCommmHeader->Result =3D EFI_INVALID_PARAMETER; + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; break; } =20 - PolicyCommmHeader->Result =3D RegisterVariablePolicy (PolicyEntry)= ; + PolicyCommHeader->Result =3D RegisterVariablePolicy (PolicyEntry); break; =20 case VAR_CHECK_POLICY_COMMAND_DUMP: @@ -200,13 +206,13 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize +=3D sizeof (VAR_CHECK_POLICY_COMM_DUMP_PARAMS) + VAR= _CHECK_POLICY_MM_DUMP_BUFFER_SIZE; if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __fu= nc__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result =3D EFI_INVALID_PARAMETER; + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; break; } =20 // Now that we know we've got a valid size, we can fill in the res= t of the data. - DumpParamsIn =3D (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(InternalPo= licyCommmHeader + 1); - DumpParamsOut =3D (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(PolicyComm= mHeader + 1); + DumpParamsIn =3D (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(InternalPo= licyCommHeader + 1); + DumpParamsOut =3D (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(PolicyComm= Header + 1); =20 // If we're requesting the first page, initialize the cache and ge= t the sizes. if (DumpParamsIn->PageRequested =3D=3D 0) { @@ -289,17 +295,131 @@ VarCheckPolicyLibMmiHandler ( } =20 // There's currently no use for this, but it shouldn't be hard to = implement. - PolicyCommmHeader->Result =3D SubCommandStatus; + PolicyCommHeader->Result =3D SubCommandStatus; break; =20 case VAR_CHECK_POLICY_COMMAND_LOCK: - PolicyCommmHeader->Result =3D LockVariablePolicy (); + PolicyCommHeader->Result =3D LockVariablePolicy (); + break; + + case VAR_CHECK_POLICY_COMMAND_GET_INFO: + case VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO: + ExpectedSize +=3D VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END + VAR_= CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE; + + if (InternalCommBufferSize < ExpectedSize) { + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; + break; + } + + GetInfoParamsInternal =3D (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *= )(InternalPolicyCommHeader + 1); + GetInfoParamsExternal =3D (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *= )(PolicyCommHeader + 1); + + SubCommandStatus =3D SafeUintnSub ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE, + GetInfoParamsInternal->InputVariableNameSize= , + &AllowedOutputVariableNameSize + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; + break; + } + + if (GetInfoParamsInternal->OutputVariableNameSize > 0) { + SubCommandStatus =3D SafeUintnAdd ( + ((UINTN)GetInfoParamsInternal + VAR_CHECK_= POLICY_COMM_GET_INFO_PARAMS_END), + (UINTN)GetInfoParamsInternal->InputVariabl= eNameSize, + (UINTN *)&InternalCopyOfOutputVariableName + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; + break; + } + } else { + InternalCopyOfOutputVariableName =3D NULL; + } + + ZeroMem (&GetInfoParamsInternal->OutputPolicyEntry, sizeof (GetInf= oParamsInternal->OutputPolicyEntry)); + ZeroMem (&GetInfoParamsExternal->OutputPolicyEntry, sizeof (GetInf= oParamsExternal->OutputPolicyEntry)); + + LocalSize =3D (UINTN)GetInfoParamsInternal->OutputVariableNameSize= ; + + if (InternalPolicyCommHeader->Command =3D=3D VAR_CHECK_POLICY_COMM= AND_GET_INFO) { + SubCommandStatus =3D GetVariablePolicyInfo ( + GetInfoParamsInternal->InputVariableName, + &GetInfoParamsInternal->InputVendorGuid, + &LocalSize, + &GetInfoParamsInternal->OutputPolicyEntry.= VariablePolicy, + InternalCopyOfOutputVariableName + ); + } else if (InternalPolicyCommHeader->Command =3D=3D VAR_CHECK_POLI= CY_COMMAND_GET_LOCK_VAR_STATE_INFO) { + SubCommandStatus =3D GetLockOnVariableStateVariablePolicyInfo ( + GetInfoParamsInternal->InputVariableName, + &GetInfoParamsInternal->InputVendorGuid, + &LocalSize, + &GetInfoParamsInternal->OutputPolicyEntry.= LockOnVarStatePolicy, + InternalCopyOfOutputVariableName + ); + } else { + PolicyCommHeader->Result =3D EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR (SubCommandStatus) && (SubCommandStatus !=3D EFI_BUF= FER_TOO_SMALL)) { + PolicyCommHeader->Result =3D SubCommandStatus; + break; + } + + if (EFI_ERROR (SafeUintnToUint32 (LocalSize, &GetInfoParamsInterna= l->OutputVariableNameSize))) { + PolicyCommHeader->Result =3D EFI_BAD_BUFFER_SIZE; + break; + } + + ASSERT (sizeof (GetInfoParamsInternal->OutputPolicyEntry) =3D=3D s= izeof (GetInfoParamsExternal->OutputPolicyEntry)); + CopyMem ( + &GetInfoParamsExternal->OutputPolicyEntry, + &GetInfoParamsInternal->OutputPolicyEntry, + sizeof (GetInfoParamsExternal->OutputPolicyEntry) + ); + + GetInfoParamsExternal->OutputVariableNameSize =3D GetInfoParamsInt= ernal->OutputVariableNameSize; + if (SubCommandStatus =3D=3D EFI_BUFFER_TOO_SMALL) { + PolicyCommHeader->Result =3D EFI_BUFFER_TOO_SMALL; + break; + } + + SubCommandStatus =3D SafeUintnAdd ( + ((UINTN)GetInfoParamsExternal + VAR_CHECK_PO= LICY_COMM_GET_INFO_PARAMS_END), + (UINTN)GetInfoParamsInternal->InputVariableN= ameSize, + (UINTN *)&ExternalCopyOfOutputVariableName + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result =3D EFI_BAD_BUFFER_SIZE; + break; + } + + if (GetInfoParamsInternal->OutputVariableNameSize > 0) { + SubCommandStatus =3D StrnCpyS ( + ExternalCopyOfOutputVariableName, + AllowedOutputVariableNameSize, + InternalCopyOfOutputVariableName, + (UINTN)GetInfoParamsInternal->OutputVariab= leNameSize + ); + ASSERT_EFI_ERROR (SubCommandStatus); + } else { + // The comm buffer should always have the space for the variable= policy output + // variable name. Fill it with NULL chars if a variable name is = not present so + // it has a consistent value in the case of variable name absenc= e. + SetMem (ExternalCopyOfOutputVariableName, AllowedOutputVariableN= ameSize, CHAR_NULL); + } + + PolicyCommHeader->Result =3D SubCommandStatus; + break; =20 default: // Mark unknown requested command as EFI_UNSUPPORTED. - DEBUG ((DEBUG_INFO, "%a - Invalid command requested! %d\n", __func= __, PolicyCommmHeader->Command)); - PolicyCommmHeader->Result =3D EFI_UNSUPPORTED; + DEBUG ((DEBUG_INFO, "%a - Invalid command requested! %d\n", __func= __, PolicyCommHeader->Command)); + PolicyCommHeader->Result =3D EFI_UNSUPPORTED; break; } =20 @@ -307,8 +427,8 @@ VarCheckPolicyLibMmiHandler ( DEBUG_VERBOSE, "%a - Command %d returning %r.\n", __func__, - PolicyCommmHeader->Command, - PolicyCommmHeader->Result + PolicyCommHeader->Command, + PolicyCommHeader->Result )); =20 return Status; diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b= /MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c index 214f76ab9626..768662829dbf 100644 --- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #include =20 +#include #include #include #include @@ -684,6 +685,309 @@ DumpVariablePolicy ( return EFI_SUCCESS; } =20 +/** + This function will return variable policy information for a UEFI varia= ble with a + registered variable policy. + + @param[in] VariableName The name of the = variable to use for the policy search. + @param[in] VendorGuid The vendor GUID = of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the si= ze, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the s= ize, in bytes, needed to store the variable + policy variable = name. + + If testing for t= he VariablePolicyVariableName buffer size + needed, set this= value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be= returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buf= fer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buf= fer where the variable name used for the + variable policy = will be written if a variable name is + registered. + + If the variable = policy is not associated with a variable name + (e.g. applied to= variable vendor namespace) and this parameter + is given, this p= arameter will not be modified and + VariablePolicyVa= riableNameBufferSize will be set to zero to + indicate a name = was not present. + + If the pointer g= iven is not NULL, + VariablePolicyVa= riableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found = and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buf= fer value is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariablePolicyVariableName is non-= NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found fo= r the given UEFI variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize O= PTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 MatchPriority; + UINTN LocalVariablePolicyVariableNameBufferSize; + UINTN RequiredVariablePolicyVariableNameBufferSize; + VARIABLE_POLICY_ENTRY *MatchPolicy; + + Status =3D EFI_SUCCESS; + + if (!IsVariablePolicyLibInitialized ()) { + return EFI_NOT_READY; + } + + if ((VariableName =3D=3D NULL) || (VendorGuid =3D=3D NULL) || (Variabl= ePolicy =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + MatchPolicy =3D GetBestPolicyMatch ( + VariableName, + VendorGuid, + &MatchPriority + ); + if (MatchPolicy !=3D NULL) { + CopyMem (VariablePolicy, MatchPolicy, sizeof (*VariablePolicy)); + + if (VariablePolicyVariableNameBufferSize =3D=3D NULL) { + if (VariablePolicyVariableName !=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + return Status; + } + + if (MatchPolicy->Size !=3D MatchPolicy->OffsetToName) { + if (MatchPolicy->Size < MatchPolicy->OffsetToName) { + ASSERT (MatchPolicy->Size > MatchPolicy->OffsetToName); + return EFI_BAD_BUFFER_SIZE; + } + + RequiredVariablePolicyVariableNameBufferSize =3D (UINTN)(MatchPoli= cy->Size - MatchPolicy->OffsetToName); + ASSERT (RequiredVariablePolicyVariableNameBufferSize > 0); + + if (*VariablePolicyVariableNameBufferSize < RequiredVariablePolicy= VariableNameBufferSize) { + // Let the caller get the size needed to hold the policy variabl= e name + *VariablePolicyVariableNameBufferSize =3D RequiredVariablePolicy= VariableNameBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (VariablePolicyVariableName =3D=3D NULL) { + // If the policy variable name size given is valid, then a valid= policy variable name buffer should be provided + *VariablePolicyVariableNameBufferSize =3D RequiredVariablePolicy= VariableNameBufferSize; + return EFI_INVALID_PARAMETER; + } + + LocalVariablePolicyVariableNameBufferSize =3D *VariablePolicyVaria= bleNameBufferSize; + + // Actual string size should match expected string size + if ( + ((StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePol= icyVariableNameBufferSize) + 1) * sizeof (CHAR16)) + !=3D RequiredVariablePolicyVariableNameBufferSize) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + *VariablePolicyVariableNameBufferSize =3D RequiredVariablePolicyVa= riableNameBufferSize; + + Status =3D StrnCpyS ( + VariablePolicyVariableName, + LocalVariablePolicyVariableNameBufferSize / sizeof (CHA= R16), + GET_POLICY_NAME (MatchPolicy), + RequiredVariablePolicyVariableNameBufferSize / sizeof (= CHAR16) + ); + ASSERT_EFI_ERROR (Status); + } else { + // A variable policy variable name is not present. Return values a= ccording to interface. + *VariablePolicyVariableNameBufferSize =3D 0; + } + + return Status; + } + + return EFI_NOT_FOUND; +} + +/** + This function will return the Lock on Variable State policy informatio= n for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of = the variable to use for the policy search. + @param[in] VendorGuid The vendor G= UID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, th= e size, in bytes, of the + VariableLock= PolicyVariableName buffer. + + On output, t= he size, in bytes, needed to store the variable + policy varia= ble name. + + If testing f= or the VariableLockPolicyVariableName buffer + size needed,= set this value to zero so EFI_BUFFER_TOO_SMALL + is guarantee= d to be returned if the variable policy variable + name is foun= d. + @param[out] VariablePolicy Pointer to a= buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a= buffer where the variable name used for the + variable loc= k on variable state policy will be written if + a variable n= ame is registered. + + If the lock = on variable policy is not associated with a + variable nam= e (e.g. applied to variable vendor namespace) + and this par= ameter is given, this parameter will not be + modified and= VariableLockPolicyVariableNameBufferSize will + be set to ze= ro to indicate a name was not present. + + If the point= er given is not NULL, + VariableLock= PolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable = policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName= buffer is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariableLockPolicyVariableName is = non-NULL and + VariableLockPolicyVariableNameBuff= erSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable = policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariable= NameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariable= Name OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 MatchPriority; + UINTN RequiredVariablePolicyVariableNameB= ufferSize; + UINTN RequiredVariableLockPolicyVariableN= ameBufferSize; + UINTN LocalVariablePolicyLockVariableName= BufferSize; + UINTN LockOnVarStatePolicyEndOffset; + CHAR16 *LocalVariableLockPolicyVariableNam= e; + VARIABLE_LOCK_ON_VAR_STATE_POLICY *LocalLockOnVarStatePolicy; + VARIABLE_POLICY_ENTRY *MatchPolicy; + + Status =3D EFI_SUCCESS; + + if (!IsVariablePolicyLibInitialized ()) { + return EFI_NOT_READY; + } + + if ((VariableName =3D=3D NULL) || (VendorGuid =3D=3D NULL) || (Variabl= ePolicy =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + MatchPolicy =3D GetBestPolicyMatch ( + VariableName, + VendorGuid, + &MatchPriority + ); + if (MatchPolicy !=3D NULL) { + if (MatchPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_ON_VA= R_STATE) { + return EFI_NOT_FOUND; + } + + Status =3D SafeUintnAdd ( + sizeof (VARIABLE_POLICY_ENTRY), + sizeof (VARIABLE_LOCK_ON_VAR_STATE_POLICY), + &LockOnVarStatePolicyEndOffset + ); + if (EFI_ERROR (Status) || (LockOnVarStatePolicyEndOffset > (UINTN)Ma= tchPolicy->Size)) { + return EFI_BAD_BUFFER_SIZE; + } + + LocalLockOnVarStatePolicy =3D (VARIABLE_LOCK_ON_VAR_STATE_POLICY *)(= MatchPolicy + 1); + CopyMem (VariablePolicy, LocalLockOnVarStatePolicy, sizeof (*LocalLo= ckOnVarStatePolicy)); + + if ((VariableLockPolicyVariableNameBufferSize =3D=3D NULL)) { + if (VariableLockPolicyVariableName !=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + return Status; + } + + // The name offset should be less than or equal to the total policy = size. + if (MatchPolicy->Size < MatchPolicy->OffsetToName) { + return EFI_BAD_BUFFER_SIZE; + } + + RequiredVariablePolicyVariableNameBufferSize =3D (UINTN)(MatchPo= licy->Size - MatchPolicy->OffsetToName); + RequiredVariableLockPolicyVariableNameBufferSize =3D MatchPolicy->S= ize - + (LockOnVarStatePo= licyEndOffset + RequiredVariablePolicyVariableNameBufferSize); + + LocalVariablePolicyLockVariableNameBufferSize =3D *VariableLockPolic= yVariableNameBufferSize; + *VariableLockPolicyVariableNameBufferSize =3D RequiredVariableLo= ckPolicyVariableNameBufferSize; + + if (LocalVariablePolicyLockVariableNameBufferSize < RequiredVariable= LockPolicyVariableNameBufferSize) { + // Let the caller get the size needed to hold the policy variable = name + return EFI_BUFFER_TOO_SMALL; + } + + if (VariableLockPolicyVariableName =3D=3D NULL) { + // If the policy variable name size given is valid, then a valid p= olicy variable name buffer should be provided + return EFI_INVALID_PARAMETER; + } + + if (RequiredVariableLockPolicyVariableNameBufferSize =3D=3D 0) { + return Status; + } + + LocalVariableLockPolicyVariableName =3D (CHAR16 *)((UINT8 *)Lo= calLockOnVarStatePolicy + sizeof (*LocalLockOnVarStatePolicy)); + *VariableLockPolicyVariableNameBufferSize =3D RequiredVariableLockPo= licyVariableNameBufferSize; + + // Actual string size should match expected string size (if a variab= le name is present) + if ( + (RequiredVariablePolicyVariableNameBufferSize > 0) && + (((StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePoli= cyVariableNameBufferSize) + 1) * sizeof (CHAR16)) !=3D + RequiredVariablePolicyVariableNameBufferSize)) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + // Actual string size should match expected string size (if here, va= riable lock variable name is present) + if ( + ((StrnLenS (LocalVariableLockPolicyVariableName, RequiredVariabl= eLockPolicyVariableNameBufferSize) + 1) * sizeof (CHAR16)) !=3D + RequiredVariableLockPolicyVariableNameBufferSize) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + Status =3D StrnCpyS ( + VariableLockPolicyVariableName, + LocalVariablePolicyLockVariableNameBufferSize / sizeof (= CHAR16), + LocalVariableLockPolicyVariableName, + RequiredVariableLockPolicyVariableNameBufferSize / sizeo= f (CHAR16) + ); + ASSERT_EFI_ERROR (Status); + + return Status; + } + + return EFI_NOT_FOUND; +} + /** This API function returns whether or not the policy engine is currently being enforced. diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/M= deModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c index d5c409c914d1..c4ccdfd20f74 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c @@ -33,7 +33,9 @@ EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol= =3D { ProtocolIsVariablePolicyEnabled, RegisterVariablePolicy, DumpVariablePolicy, - LockVariablePolicy + LockVariablePolicy, + GetVariablePolicyInfo, + GetLockOnVariableStateVariablePolicyInfo }; EDKII_VAR_CHECK_PROTOCOL mVarCheck =3D { VarCheckRegisterSetVariableCheckHandler, diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmm= Dxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c index 6151a2ba0b18..0dd72dde27ce 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c @@ -410,6 +410,338 @@ ProtocolLockVariablePolicy ( return (EFI_ERROR (Status)) ? Status : PolicyHeader->Result; } =20 +/** + Internal implementation to retrieve variable information for a given U= EFI variable that is shared + between different policy types. + + Currently, the two policy structure types supported (and all that is d= efined) are VARIABLE_POLICY_ENTRY + and VARIABLE_LOCK_ON_VAR_STATE_POLICY. + + @param[in] Command The command valu= e to use in the communicate call. + @param[in] VariableName The name of the = variable to use for the policy search. + @param[in] VendorGuid The vendor GUID = of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the si= ze, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the s= ize, in bytes, needed to store the variable + policy variable = name. + + If testing for t= he VariablePolicyVariableName buffer size + needed, set this= value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be= returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buf= fer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buf= fer where the variable name used for the + variable policy = will be written if a variable name is + registered. + + If the variable = policy is not associated with a variable name + (e.g. applied to= variable vendor namespace) and this parameter + is given, this p= arameter will not be modified and + VariablePolicyVa= riableNameBufferSize will be set to zero to + indicate a name = was not present. + + If the pointer g= iven is not NULL, + VariablePolicyVa= riableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found = and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buf= fer value is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariablePolicyVariableName is non-= NULL and VariablePolicyVariableNameBufferSize + is NULL. It can also be returned i= f the Command value provided is invalid. + @retval EFI_NOT_FOUND A variable policy was not found fo= r the given UEFI variable name and vendor GUID. + + +**/ +STATIC +EFI_STATUS +InternalProtocolGetVariablePolicyInfo ( + IN UINT32 Command, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize, OPTIONAL + OUT VOID *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName = OPTIONAL + ) +{ + EFI_STATUS Status; + CHAR16 *OutputVariableName; + EFI_MM_COMMUNICATE_HEADER *CommHeader; + VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *CommandParams; + UINTN AllowedOutputVariableNameSize; + UINTN BufferSize; + UINTN VariableNameSize; + + if ((VariableName =3D=3D NULL) || (VendorGuid =3D=3D NULL) || (Variabl= ePolicy =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (Command) { + case VAR_CHECK_POLICY_COMMAND_GET_INFO: + case VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO: + break; + default: + return EFI_INVALID_PARAMETER; + } + + AcquireLockOnlyAtBootTime (&mMmCommunicationLock); + + VariableNameSize =3D StrnSizeS ( + VariableName, + (VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE - VAR_C= HECK_POLICY_COMM_GET_INFO_PARAMS_END) + ); + if (VariableNameSize >=3D (VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE - = VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END)) { + Status =3D EFI_INVALID_PARAMETER; + goto Done; + } + + if ((VariablePolicyVariableName !=3D NULL) && (VariablePolicyVariableN= ameBufferSize =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + goto Done; + } + + BufferSize =3D mMmCommunicationBufferSize; + CommHeader =3D mMmCommunicationBuffer; + + Status =3D SafeUintnSub ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE, + VariableNameSize, + &AllowedOutputVariableNameSize + ); + if (EFI_ERROR (Status)) { + Status =3D EFI_INVALID_PARAMETER; + goto Done; + } + + if (VariablePolicyVariableNameBufferSize !=3D NULL) { + AllowedOutputVariableNameSize =3D MIN (AllowedOutputVariableNameSize= , *VariablePolicyVariableNameBufferSize); + } else { + AllowedOutputVariableNameSize =3D 0; + } + + PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER *)&CommHeader->Data; + CommandParams =3D (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *)(PolicyHead= er + 1); + + CopyGuid (&CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid); + CommHeader->MessageLength =3D BufferSize - OFFSET_OF (EFI_MM_COMMUNICA= TE_HEADER, Data); + PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG; + PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION; + PolicyHeader->Command =3D Command; + + ZeroMem ((VOID *)&CommandParams->OutputPolicyEntry, sizeof (CommandPar= ams->OutputPolicyEntry)); + CopyGuid (&CommandParams->InputVendorGuid, VendorGuid); + Status =3D SafeUintnToUint32 (VariableNameSize, &CommandParams->InputV= ariableNameSize); + if (EFI_ERROR (Status)) { + Status =3D EFI_INVALID_PARAMETER; + goto Done; + } + + Status =3D SafeUintnToUint32 (AllowedOutputVariableNameSize, &CommandP= arams->OutputVariableNameSize); + if (EFI_ERROR (Status)) { + Status =3D EFI_INVALID_PARAMETER; + goto Done; + } + + if (AllowedOutputVariableNameSize > 0) { + Status =3D StrnCpyS ( + CommandParams->InputVariableName, + AllowedOutputVariableNameSize / sizeof (CHAR16), + VariableName, + (UINTN)CommandParams->InputVariableNameSize / sizeof (CH= AR16) + ); + ASSERT_EFI_ERROR (Status); + } + + Status =3D InternalMmCommunicate (CommHeader, &BufferSize); + if (Status =3D=3D EFI_SUCCESS) { + CopyMem ( + VariablePolicy, + (VOID *)&CommandParams->OutputPolicyEntry, + (Command =3D=3D VAR_CHECK_POLICY_COMMAND_GET_INFO) ? + sizeof (CommandParams->OutputPolicyEntry.VariablePolicy) : + sizeof (CommandParams->OutputPolicyEntry.LockOnVarStatePolicy) + ); + + if (VariablePolicyVariableNameBufferSize =3D=3D NULL) { + if (VariablePolicyVariableName !=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + } + + goto Done; + } + + if (PolicyHeader->Result =3D=3D EFI_BUFFER_TOO_SMALL) { + *VariablePolicyVariableNameBufferSize =3D (UINTN)CommandParams->Ou= tputVariableNameSize; + goto Done; + } + + if (PolicyHeader->Result =3D=3D EFI_SUCCESS) { + if (CommandParams->OutputVariableNameSize > 0) { + Status =3D SafeUintnAdd ( + ((UINTN)CommandParams + VAR_CHECK_POLICY_COMM_GET_IN= FO_PARAMS_END), + (UINTN)CommandParams->InputVariableNameSize, + (UINTN *)&OutputVariableName + ); + if (EFI_ERROR (Status)) { + Status =3D EFI_BAD_BUFFER_SIZE; + goto Done; + } + + Status =3D StrnCpyS ( + VariablePolicyVariableName, + *VariablePolicyVariableNameBufferSize / sizeof (CHAR= 16), + OutputVariableName, + (UINTN)CommandParams->OutputVariableNameSize + ); + ASSERT_EFI_ERROR (Status); + *VariablePolicyVariableNameBufferSize =3D (UINTN)CommandParams->= OutputVariableNameSize; + } else { + // A variable policy variable name is not present. Return values= according to interface. + *VariablePolicyVariableNameBufferSize =3D 0; + } + } + } + +Done: + ReleaseLockOnlyAtBootTime (&mMmCommunicationLock); + + return (EFI_ERROR (Status)) ? Status : PolicyHeader->Result; +} + +/** + This function will return variable policy information for a UEFI varia= ble with a + registered variable policy. + + @param[in] VariableName The name of the = variable to use for the policy search. + @param[in] VendorGuid The vendor GUID = of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the si= ze, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the s= ize, in bytes, needed to store the variable + policy variable = name. + + If testing for t= he VariablePolicyVariableName buffer size + needed, set this= value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be= returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buf= fer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buf= fer where the variable name used for the + variable policy = will be written if a variable name is + registered. + + If the variable = policy is not associated with a variable name + (e.g. applied to= variable vendor namespace) and this parameter + is given, this p= arameter will not be modified and + VariablePolicyVa= riableNameBufferSize will be set to zero to + indicate a name = was not present. + + If the pointer g= iven is not NULL, + VariablePolicyVa= riableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found = and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buf= fer value is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariablePolicyVariableName is non-= NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found fo= r the given UEFI variable name and vendor GUID. + +**/ +STATIC +EFI_STATUS +EFIAPI +ProtocolGetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize, OPTIONAL + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName = OPTIONAL + ) +{ + return InternalProtocolGetVariablePolicyInfo ( + VAR_CHECK_POLICY_COMMAND_GET_INFO, + VariableName, + VendorGuid, + VariablePolicyVariableNameBufferSize, + VariablePolicy, + VariablePolicyVariableName + ); +} + +/** + This function will return the Lock on Variable State policy informatio= n for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of = the variable to use for the policy search. + @param[in] VendorGuid The vendor G= UID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, th= e size, in bytes, of the + VariableLock= PolicyVariableName buffer. + + On output, t= he size, in bytes, needed to store the variable + policy varia= ble name. + + If testing f= or the VariableLockPolicyVariableName buffer + P size needed= , set this value to zero so EFI_BUFFER_TOO_SMALL + is guarantee= d to be returned if the variable policy variable + name is foun= d. + @param[out] VariablePolicy Pointer to a= buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a= buffer where the variable name used for the + variable loc= k on variable state policy will be written if + a variable n= ame is registered. + + If the lock = on variable policy is not associated with a + variable nam= e (e.g. applied to variable vendor namespace) + and this par= ameter is given, this parameter will not be + modified and= VariableLockPolicyVariableNameBufferSize will + be set to ze= ro to indicate a name was not present. + + If the point= er given is not NULL, + VariableLock= PolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable = policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName= buffer is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariableLockPolicyVariableName is = non-NULL and + VariableLockPolicyVariableNameBuff= erSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable = policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +STATIC +EFI_STATUS +EFIAPI +ProtocolGetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariableNameBufferSize, OPTIONAL + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariabl= eName OPTIONAL + ) +{ + return InternalProtocolGetVariablePolicyInfo ( + VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO, + VariableName, + VendorGuid, + VariableLockPolicyVariableNameBufferSize, + VariablePolicy, + VariableLockPolicyVariableName + ); +} + /** This helper function locates the shared comm buffer and assigns it to = input pointers. =20 @@ -514,12 +846,14 @@ VariablePolicySmmDxeMain ( } =20 // Configure the VariablePolicy protocol structure. - mVariablePolicyProtocol.Revision =3D EDKII_VARIABLE_POL= ICY_PROTOCOL_REVISION; - mVariablePolicyProtocol.DisableVariablePolicy =3D ProtocolDisableVar= iablePolicy; - mVariablePolicyProtocol.IsVariablePolicyEnabled =3D ProtocolIsVariable= PolicyEnabled; - mVariablePolicyProtocol.RegisterVariablePolicy =3D ProtocolRegisterVa= riablePolicy; - mVariablePolicyProtocol.DumpVariablePolicy =3D ProtocolDumpVariab= lePolicy; - mVariablePolicyProtocol.LockVariablePolicy =3D ProtocolLockVariab= lePolicy; + mVariablePolicyProtocol.Revision =3D E= DKII_VARIABLE_POLICY_PROTOCOL_REVISION; + mVariablePolicyProtocol.DisableVariablePolicy =3D P= rotocolDisableVariablePolicy; + mVariablePolicyProtocol.IsVariablePolicyEnabled =3D P= rotocolIsVariablePolicyEnabled; + mVariablePolicyProtocol.RegisterVariablePolicy =3D P= rotocolRegisterVariablePolicy; + mVariablePolicyProtocol.DumpVariablePolicy =3D P= rotocolDumpVariablePolicy; + mVariablePolicyProtocol.LockVariablePolicy =3D P= rotocolLockVariablePolicy; + mVariablePolicyProtocol.GetVariablePolicyInfo =3D P= rotocolGetVariablePolicyInfo; + mVariablePolicyProtocol.GetLockOnVariableStateVariablePolicyInfo =3D P= rotocolGetLockOnVariableStateVariablePolicyInfo; =20 // Register all the protocols and return the status. Status =3D gBS->InstallMultipleProtocolInterfaces ( diff --git a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h b/MdeModulePkg= /Include/Guid/VarCheckPolicyMmi.h index ff3d4a1fd68a..a692fa40c946 100644 --- a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h +++ b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h @@ -32,23 +32,52 @@ typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS { BOOLEAN HasMore; } VAR_CHECK_POLICY_COMM_DUMP_PARAMS; =20 +typedef union { + VARIABLE_POLICY_ENTRY VariablePolicy; + VARIABLE_LOCK_ON_VAR_STATE_POLICY LockOnVarStatePolicy; +} VAR_CHECK_POLICY_OUTPUT_POLICY_ENTRY; + +typedef struct _VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS { + EFI_GUID InputVendorGuid; + UINT32 InputVariableNameSize; + UINT32 OutputVariableNameSize; + VAR_CHECK_POLICY_OUTPUT_POLICY_ENTRY OutputPolicyEntry; + CHAR16 InputVariableName[1]; +} VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS; + #pragma pack(pop) =20 +#define VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END \ + (OFFSET_OF(VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS, InputVaria= bleName)) + // Make sure that we will hold at least the headers. #define VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE MAX((OFFSET_OF(EFI_MM_CO= MMUNICATE_HEADER, Data) + sizeof (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAG= ES_TO_SIZE(1)), EFI_PAGES_TO_SIZE(4)) #define VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE (VAR_CHECK_POLICY_MM_COM= M_BUFFER_SIZE - \ (OFFSET_OF(EFI_MM_CO= MMUNICATE_HEADER, Data) + \ sizeof(VAR_CHECK_P= OLICY_COMM_HEADER) + \ sizeof(VAR_CHECK_P= OLICY_COMM_DUMP_PARAMS))) + +#define VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE (VAR_CHECK_POLICY_MM= _COMM_BUFFER_SIZE - \ + (OFFSET_OF(EFI_MM_= COMMUNICATE_HEADER, Data) + \ + sizeof(VAR_CHECK= _POLICY_COMM_HEADER) + \ + OFFSET_OF(VAR_CH= ECK_POLICY_COMM_GET_INFO_PARAMS, InputVariableName))) + STATIC_ASSERT ( VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BUFFER= _SIZE, "an integer underflow may have occurred calculating VAR_CHECK_POLICY_M= M_DUMP_BUFFER_SIZE" ); =20 -#define VAR_CHECK_POLICY_COMMAND_DISABLE 0x0001 -#define VAR_CHECK_POLICY_COMMAND_IS_ENABLED 0x0002 -#define VAR_CHECK_POLICY_COMMAND_REGISTER 0x0003 -#define VAR_CHECK_POLICY_COMMAND_DUMP 0x0004 -#define VAR_CHECK_POLICY_COMMAND_LOCK 0x0005 +STATIC_ASSERT ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BU= FFER_SIZE, + "an integer underflow may have occurred calculating VAR_CHECK_POLICY_M= M_GET_INFO_BUFFER_SIZE" + ); + +#define VAR_CHECK_POLICY_COMMAND_DISABLE 0x0001 +#define VAR_CHECK_POLICY_COMMAND_IS_ENABLED 0x0002 +#define VAR_CHECK_POLICY_COMMAND_REGISTER 0x0003 +#define VAR_CHECK_POLICY_COMMAND_DUMP 0x0004 +#define VAR_CHECK_POLICY_COMMAND_LOCK 0x0005 +#define VAR_CHECK_POLICY_COMMAND_GET_INFO 0x0006 +#define VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO 0x0007 =20 #endif // _VAR_CHECK_POLICY_MMI_COMMON_H_ diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h b/MdeModule= Pkg/Include/Library/VariablePolicyLib.h index 63c49fbca1ed..bc4e26b2d434 100644 --- a/MdeModulePkg/Include/Library/VariablePolicyLib.h +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h @@ -102,6 +102,113 @@ DumpVariablePolicy ( IN OUT UINT32 *Size ); =20 +/** + This function will return variable policy information for a UEFI varia= ble with a + registered variable policy. + + @param[in] VariableName The name of the = variable to use for the policy search. + @param[in] VendorGuid The vendor GUID = of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the si= ze, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the s= ize, in bytes, needed to store the variable + policy variable = name. + + If testing for t= he VariablePolicyVariableName buffer size + needed, set this= value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be= returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buf= fer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buf= fer where the variable name used for the + variable policy = will be written if a variable name is + registered. + + If the variable = policy is not associated with a variable name + (e.g. applied to= variable vendor namespace) and this parameter + is given, this p= arameter will not be modified and + VariablePolicyVa= riableNameBufferSize will be set to zero to + indicate a name = was not present. + + If the pointer g= iven is not NULL, + VariablePolicyVa= riableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found = and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buf= fer value is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariablePolicyVariableName is non-= NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found fo= r the given UEFI variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize O= PTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ); + +/** + This function will return the Lock on Variable State policy informatio= n for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of = the variable to use for the policy search. + @param[in] VendorGuid The vendor G= UID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, th= e size, in bytes, of the + VariableLock= PolicyVariableName buffer. + + On output, t= he size, in bytes, needed to store the variable + policy varia= ble name. + + If testing f= or the VariableLockPolicyVariableName buffer + size needed,= set this value to zero so EFI_BUFFER_TOO_SMALL + is guarantee= d to be returned if the variable policy variable + name is foun= d. + @param[out] VariablePolicy Pointer to a= buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a= buffer where the variable name used for the + variable loc= k on variable state policy will be written if + a variable n= ame is registered. + + If the lock = on variable policy is not associated with a + variable nam= e (e.g. applied to variable vendor namespace) + and this par= ameter is given, this parameter will not be + modified and= VariableLockPolicyVariableNameBufferSize will + be set to ze= ro to indicate a name was not present. + + If the point= er given is not NULL, + VariableLock= PolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable = policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName= buffer is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariableLockPolicyVariableName is = non-NULL and + VariableLockPolicyVariableNameBuff= erSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable = policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariable= NameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariable= Name OPTIONAL + ); + /** This API function returns whether or not the policy engine is currently being enforced. diff --git a/MdeModulePkg/Include/Protocol/VariablePolicy.h b/MdeModulePk= g/Include/Protocol/VariablePolicy.h index 98d739401f83..4b57f70a9da8 100644 --- a/MdeModulePkg/Include/Protocol/VariablePolicy.h +++ b/MdeModulePkg/Include/Protocol/VariablePolicy.h @@ -9,7 +9,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef __EDKII_VARIABLE_POLICY_PROTOCOL__ #define __EDKII_VARIABLE_POLICY_PROTOCOL__ =20 -#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000010000 +#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000020000 + +/* + Rev 0x0000000000010000: + - Initial protocol definition + + Rev 0x0000000000020000: + - Add GetVariablePolicyInfo() API + - Add GetLockOnVariableStateVariablePolicyInfo() API + +*/ =20 #define EDKII_VARIABLE_POLICY_PROTOCOL_GUID \ { \ @@ -141,13 +151,122 @@ EFI_STATUS VOID ); =20 +/** + This function will return variable policy information for a UEFI varia= ble with a + registered variable policy. + + @param[in] VariableName The name of the = variable to use for the policy search. + @param[in] VendorGuid The vendor GUID = of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the si= ze, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the s= ize, in bytes, needed to store the variable + policy variable = name. + + If testing for t= he VariablePolicyVariableName buffer size + needed, set this= value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be= returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buf= fer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buf= fer where the variable name used for the + variable policy = will be written if a variable name is + registered. + + If the variable = policy is not associated with a variable name + (e.g. applied to= variable vendor namespace) and this parameter + is given, this p= arameter will not be modified and + VariablePolicyVa= riableNameBufferSize will be set to zero to + indicate a name = was not present. + + If the pointer g= iven is not NULL, + VariablePolicyVa= riableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found = and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buf= fer value is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariablePolicyVariableName is non-= NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found fo= r the given UEFI variable name and vendor GUID. + +**/ +typedef +EFI_STATUS +(EFIAPI *GET_VARIABLE_POLICY_INFO)( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferS= ize OPTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTION= AL + ); + +/** + This function will return the Lock on Variable State policy informatio= n for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of = the variable to use for the policy search. + @param[in] VendorGuid The vendor G= UID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, th= e size, in bytes, of the + VariableLock= PolicyVariableName buffer. + + On output, t= he size, in bytes, needed to store the variable + policy varia= ble name. + + If testing f= or the VariableLockPolicyVariableName buffer + size needed,= set this value to zero so EFI_BUFFER_TOO_SMALL + is guarantee= d to be returned if the variable policy variable + name is foun= d. + @param[out] VariablePolicy Pointer to a= buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a= buffer where the variable name used for the + variable loc= k on variable state policy will be written if + a variable n= ame is registered. + + If the lock = on variable policy is not associated with a + variable nam= e (e.g. applied to variable vendor namespace) + and this par= ameter is given, this parameter will not be + modified and= VariableLockPolicyVariableNameBufferSize will + be set to ze= ro to indicate a name was not present. + + If the point= er given is not NULL, + VariableLock= PolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable = policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a c= alculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName= buffer is too small for the size needed. + The buffer should now point to the= size needed. + @retval EFI_NOT_READY Variable policy has not yet been i= nitialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed= is NULL. This will be returned if + VariableLockPolicyVariableName is = non-NULL and + VariableLockPolicyVariableNameBuff= erSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable = policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +typedef +EFI_STATUS +(EFIAPI *GET_LOCK_ON_VARIABLE_STATE_VARIABLE_POLICY_INFO)( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariabl= eNameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariabl= eName OPTIONAL + ); + typedef struct { - UINT64 Revision; - DISABLE_VARIABLE_POLICY DisableVariablePolicy; - IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled; - REGISTER_VARIABLE_POLICY RegisterVariablePolicy; - DUMP_VARIABLE_POLICY DumpVariablePolicy; - LOCK_VARIABLE_POLICY LockVariablePolicy; + UINT64 Revision; + DISABLE_VARIABLE_POLICY DisableVariablePoli= cy; + IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEna= bled; + REGISTER_VARIABLE_POLICY RegisterVariablePol= icy; + DUMP_VARIABLE_POLICY DumpVariablePolicy; + LOCK_VARIABLE_POLICY LockVariablePolicy; + GET_VARIABLE_POLICY_INFO GetVariablePolicyIn= fo; + GET_LOCK_ON_VARIABLE_STATE_VARIABLE_POLICY_INFO GetLockOnVariableSt= ateVariablePolicyInfo; } _EDKII_VARIABLE_POLICY_PROTOCOL; =20 typedef _EDKII_VARIABLE_POLICY_PROTOCOL EDKII_VARIABLE_POLICY_PROTOCOL; diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf= b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf index 3fe6043bf631..7048d555f0a9 100644 --- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf @@ -32,6 +32,7 @@ [Packages] =20 =20 [LibraryClasses] + BaseLib DebugLib BaseMemoryLib MemoryAllocationLib --=20 2.42.0.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110340): https://edk2.groups.io/g/devel/message/110340 Mute This Topic: https://groups.io/mt/102284381/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-