From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by mx.groups.io with SMTP id smtpd.web10.25785.1678727870193444924 for ; Mon, 13 Mar 2023 10:17:50 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=McfY8V9g; spf=pass (domain: kernel.org, ip: 139.178.84.217, mailfrom: ardb@kernel.org) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B6CAF61450; Mon, 13 Mar 2023 17:17:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 58B06C4339B; Mon, 13 Mar 2023 17:17:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678727869; bh=LqTp5/X+b2GcLIU9cRLpWYhMwCnTyQtmbpGuzw+P0YA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=McfY8V9gqHGkxVp6Ugd8zRkCh9Psj9EbwHSBfj9kmbgUHf1mWBwQ7t+v73s5fN8ri /ECYoh0urpOglhTPnmKAhpWiCKVTUmV900KbgowSyScQguQCi4EWJlLZN3e3XfQxcT IIVbo1vMyND41boshb4NnL98We5wOJMgnmnpBTW2Wsd6hTBJOeF5DWSetIhLcgJuoy X1rfk0sMchhsB4QwSzU6+8KforSuG/3gAVcivdVxSX02e2bGCxysGuKLneQ1+mUh11 2UoSqHkoOEfpTKbWpPPKiDo66bry52gABbNgiLykiDJA3f+siRru5yEY3UFeY73w9l y1jyZGkcNm78w== From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Michael Kinney , Liming Gao , Jiewen Yao , Michael Kubacki , Sean Brogan , Rebecca Cran , Leif Lindholm , Sami Mujawar , Taylor Beebe Subject: [PATCH v5 06/38] ArmPkg/ArmMmuLib: Implement EFI_MEMORY_RP using access flag Date: Mon, 13 Mar 2023 18:16:42 +0100 Message-Id: <20230313171714.3866151-7-ardb@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230313171714.3866151-1-ardb@kernel.org> References: <20230313171714.3866151-1-ardb@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Implement support for read-protected memory by wiring it up to the access flag in the page table descriptor. The resulting mapping is implicitly non-writable and non-executable as well, but this is good enough for implementing this attribute, as we never rely on write or execute permissions without read permissions. Signed-off-by: Ard Biesheuvel --- ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c | 8 ++- ArmPkg/Include/Library/ArmMmuLib.h | 34 ++++++++++++ ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 58 +++++++++++++++++++- ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c | 48 ++++++++++++++++ 4 files changed, 144 insertions(+), 4 deletions(-) diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c b/ArmPkg/Drivers/CpuDxe/AA= rch64/Mmu.c index 8bb33046e707..8bda11f08a30 100644 --- a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c @@ -64,6 +64,10 @@ PageAttributeToGcdAttribute ( }=0D =0D // Determine protection attributes=0D + if ((PageAttributes & TT_AF) =3D=3D 0) {=0D + GcdAttributes |=3D EFI_MEMORY_RP;=0D + }=0D +=0D if (((PageAttributes & TT_AP_MASK) =3D=3D TT_AP_NO_RO) ||=0D ((PageAttributes & TT_AP_MASK) =3D=3D TT_AP_RO_RO))=0D {=0D @@ -301,7 +305,9 @@ EfiAttributeToArmAttribute ( }=0D =0D // Set the access flag to match the block attributes=0D - ArmAttributes |=3D TT_AF;=0D + if ((EfiAttributes & EFI_MEMORY_RP) =3D=3D 0) {=0D + ArmAttributes |=3D TT_AF;=0D + }=0D =0D // Determine protection attributes=0D if ((EfiAttributes & EFI_MEMORY_RO) !=3D 0) {=0D diff --git a/ArmPkg/Include/Library/ArmMmuLib.h b/ArmPkg/Include/Library/Ar= mMmuLib.h index b745e2230e7e..4cf59a1e376b 100644 --- a/ArmPkg/Include/Library/ArmMmuLib.h +++ b/ArmPkg/Include/Library/ArmMmuLib.h @@ -21,6 +21,40 @@ ArmConfigureMmu ( OUT UINTN *TranslationTableSize OPTIONAL=0D );=0D =0D +/**=0D + Convert a region of memory to read-protected, by clearing the access fla= g.=0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +ArmSetMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + );=0D +=0D +/**=0D + Convert a region of memory to read-enabled, by setting the access flag.= =0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +ArmClearMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + );=0D +=0D EFI_STATUS=0D EFIAPI=0D ArmSetMemoryRegionNoExec (=0D diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Libr= ary/ArmMmuLib/AArch64/ArmMmuLibCore.c index 764c7d362e2e..6d21a2e41dd1 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -438,7 +438,11 @@ GcdAttributeToPageAttribute ( PageAttributes |=3D TT_AP_NO_RO;=0D }=0D =0D - return PageAttributes | TT_AF;=0D + if ((GcdAttributes & EFI_MEMORY_RP) =3D=3D 0) {=0D + PageAttributes |=3D TT_AF;=0D + }=0D +=0D + return PageAttributes;=0D }=0D =0D EFI_STATUS=0D @@ -459,9 +463,9 @@ ArmSetMemoryAttributes ( // No memory type was set in Attributes, so we are going to update the= =0D // permissions only.=0D //=0D - PageAttributes &=3D TT_AP_MASK | TT_UXN_MASK | TT_PXN_MASK;=0D + PageAttributes &=3D TT_AP_MASK | TT_UXN_MASK | TT_PXN_MASK | TT_AF;= =0D PageAttributeMask =3D ~(TT_ADDRESS_MASK_BLOCK_ENTRY | TT_AP_MASK |=0D - TT_PXN_MASK | TT_XN_MASK);=0D + TT_PXN_MASK | TT_XN_MASK | TT_AF);=0D }=0D =0D return UpdateRegionMapping (=0D @@ -534,6 +538,54 @@ ArmClearMemoryRegionNoExec ( );=0D }=0D =0D +/**=0D + Convert a region of memory to read-protected, by clearing the access fla= g.=0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +ArmSetMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + )=0D +{=0D + return SetMemoryRegionAttribute (=0D + BaseAddress,=0D + Length,=0D + 0,=0D + ~(TT_ADDRESS_MASK_BLOCK_ENTRY | TT_AF)=0D + );=0D +}=0D +=0D +/**=0D + Convert a region of memory to read-enabled, by setting the access flag.= =0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +ArmClearMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + )=0D +{=0D + return SetMemoryRegionAttribute (=0D + BaseAddress,=0D + Length,=0D + TT_AF,=0D + ~TT_ADDRESS_MASK_BLOCK_ENTRY=0D + );=0D +}=0D +=0D EFI_STATUS=0D ArmSetMemoryRegionReadOnly (=0D IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D diff --git a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c b/ArmPkg/Librar= y/ArmMmuLib/Arm/ArmMmuLibUpdate.c index 23f613f5dbb0..247cf87bf3d3 100644 --- a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c +++ b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c @@ -523,3 +523,51 @@ ArmClearMemoryRegionReadOnly ( TT_DESCRIPTOR_SECTION_AP_MASK=0D );=0D }=0D +=0D +/**=0D + Convert a region of memory to read-protected, by clearing the access fla= g.=0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +ArmSetMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + )=0D +{=0D + return SetMemoryAttributes (=0D + BaseAddress,=0D + Length,=0D + EFI_MEMORY_RP,=0D + TT_DESCRIPTOR_SECTION_AF=0D + );=0D +}=0D +=0D +/**=0D + Convert a region of memory to read-enabled, by setting the access flag.= =0D +=0D + @param BaseAddress The start of the region.=0D + @param Length The size of the region.=0D +=0D + @retval EFI_SUCCESS The attributes were set successfully.=0D + @retval EFI_OUT_OF_RESOURCES The operation failed due to insufficient m= emory.=0D +=0D +**/=0D +EFI_STATUS=0D +ArmClearMemoryRegionNoAccess (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length=0D + )=0D +{=0D + return SetMemoryAttributes (=0D + BaseAddress,=0D + Length,=0D + 0,=0D + TT_DESCRIPTOR_SECTION_AF=0D + );=0D +}=0D --=20 2.39.2