From: "Wang, Jian J" <jian.j.wang@intel.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
"Zeng, Star" <star.zeng@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
"Ni, Ruiyu" <ruiyu.ni@intel.com>,
"Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [PATCH] MdeModulePkg/DxeIpl: support more NX related PCDs
Date: Fri, 14 Sep 2018 06:50:14 +0000 [thread overview]
Message-ID: <D827630B58408649ACB04F44C510003624E340DE@SHSMSX103.ccr.corp.intel.com> (raw)
In-Reply-To: <CAKv+Gu80PpgiW-Ft2HyLasJVCsYuvgyAYNBc6KZ=mQh_pmjKCQ@mail.gmail.com>
Ard,
> Why? Is it unreasonable to protect the stack but not other
> EfiBootServicesData regions?
I think you got me wrong. It's reasonable to protect stack but not
other EfiBootServicesData regions. What I want to express in the
commit message is the contrary one is not: not to protect stack but
protect all EfiBootServicesData regions. I have one statement at
the end of message saying "PcdSetNxForStack and PcdImageProtectionPolicy
have priority over PcdDxeNxMemoryProtectionPolicy". Do you agree
with it?
The examples I gave are unreasonable ones. I can't image any
reason to try those combinations on purpose. But if there's really
good reason to do it, it's ok to remove those checks.
> I am trying to understand if you think these are fundamentally
> incompatible, or whether it is simply too complicated in the code to
> support it. (I can see how the first example would force you to
> explicitly map the stack executable, for instance, which is perhaps a
> bit of a stretch)
I might not get your point here. If I understand correctly, I think the
purpose I want to do here is to avoid any unexpected NX behavior from BIOS.
For example, if one don't want NX for stack and set PcdSetNxForStack to
FALSE but accidently enabled NX for EfiBootServicesData, it's hard for him
to find out why stack is still not executable. This usually happen if one is trying
different configurations to debug the system.
Or do you mean if one set PcdSetNxForStack to FALSE, the BIOS should
automatically disable NX for all EfiBootServicesData regions? This is a bit
confuse to me because, if PcdSetNxForStack is TRUE, we only enable NX
for stack memory only (suppose PcdDxeNxMemoryProtectionPolicy is all zero).
Regards,
Jian
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
Sent: Friday, September 14, 2018 2:05 PM
To: Wang, Jian J <jian.j.wang@intel.com>
Cc: edk2-devel@lists.01.org; Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: Re: [PATCH] MdeModulePkg/DxeIpl: support more NX related PCDs
On 14 September 2018 at 07:13, Jian J Wang <jian.j.wang@intel.com> wrote:
> BZ#1116: https://bugzilla.tianocore.org/show_bug.cgi?id=1116
>
> Currently IA32_EFER.NXE is only set against PcdSetNxForStack. This
> confuses developers because following two other PCDs also need NXE
> to be set, but actually not.
>
> PcdDxeNxMemoryProtectionPolicy
> PcdImageProtectionPolicy
>
> This patch solves this issue by adding logic to enable IA32_EFER.NXE
> if any of those PCDs have anything enabled.
>
> Due to the fact that NX memory type of stack (enabled by PcdSetNxForStack)
> and image data section (enabled by PcdImageProtectionPolicy) are also
> part of PcdDxeNxMemoryProtectionPolicy, this patch also add more checks
> to warn (ASSERT) users any unreasonable setting combinations. For example,
>
> PcdSetNxForStack == FALSE &&
> (PcdDxeNxMemoryProtectionPolicy & (1 <<EfiBootServicesData)) != 0
>
> PcdImageProtectionPolicy == 0 &&
> (PcdDxeNxMemoryProtectionPolicy & (1 << EfiRuntimeServicesData)) != 0
>
> PcdImageProtectionPolicy == 0 &&
> (PcdDxeNxMemoryProtectionPolicy & (1 <<EfiBootServicesData)) != 0
>
> PcdImageProtectionPolicy == 0 &&
> (PcdDxeNxMemoryProtectionPolicy & (1 <<EfiLoaderData)) != 0
>
> In other words, PcdSetNxForStack and PcdImageProtectionPolicy have
> priority over PcdDxeNxMemoryProtectionPolicy.
>
Why? Is it unreasonable to protect the stack but not other
EfiBootServicesData regions?
I am trying to understand if you think these are fundamentally
incompatible, or whether it is simply too complicated in the code to
support it. (I can see how the first example would force you to
explicitly map the stack executable, for instance, which is perhaps a
bit of a stretch)
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> ---
> MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 2 +
> MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 4 +-
> MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 55 +++++++++++++++++++++++-
> MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h | 33 ++++++++++++++
> 4 files changed, 91 insertions(+), 3 deletions(-)
>
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> index fd82657404..068e700074 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> @@ -117,6 +117,8 @@
>
> [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]
> gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
> + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
> + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
>
> [Depex]
> gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid
> diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> index d28baa3615..9a97205ef8 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> @@ -245,7 +245,7 @@ ToBuildPageTable (
> return TRUE;
> }
>
> - if (PcdGetBool (PcdSetNxForStack) && IsExecuteDisableBitAvailable ()) {
> + if (ToEnableExecuteDisableFeature ()) {
> return TRUE;
> }
>
> @@ -436,7 +436,7 @@ HandOffToDxeCore (
> BuildPageTablesIa32Pae = ToBuildPageTable ();
> if (BuildPageTablesIa32Pae) {
> PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
> - if (IsExecuteDisableBitAvailable ()) {
> + if (ToEnableExecuteDisableFeature ()) {
> EnableExecuteDisableBit();
> }
> }
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> index 496e219913..253fe84223 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> @@ -106,6 +106,56 @@ IsNullDetectionEnabled (
> return ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0);
> }
>
> +/**
> + Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not.
> +
> + @retval TRUE IA32_EFER.NXE should be enabled.
> + @retval FALSE IA32_EFER.NXE should not be enabled.
> +
> +**/
> +BOOLEAN
> +ToEnableExecuteDisableFeature (
> + VOID
> + )
> +{
> + if (!IsExecuteDisableBitAvailable ()) {
> + return FALSE;
> + }
> +
> + //
> + // Normally stack is type of EfiBootServicesData. Disabling NX for stack
> + // but enabling NX for EfiBootServicesData doesn't make any sense.
> + //
> + if (PcdGetBool (PcdSetNxForStack) == FALSE &&
> + (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & STACK_MEMORY_TYPE) != 0) {
> + DEBUG ((DEBUG_ERROR,
> + "ERROR: NX for stack is disabled but NX for its memory type is enabled!\r\n"));
> + ASSERT(!(PcdGetBool (PcdSetNxForStack) == FALSE &&
> + (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & STACK_MEMORY_TYPE) != 0));
> + }
> +
> + //
> + // Image data section could be type of EfiLoaderData, EfiBootServicesData
> + // or EfiRuntimeServicesData. Disabling NX for image data but enabling NX
> + // for any those memory types doesn't make any sense.
> + //
> + if (PcdGet32 (PcdImageProtectionPolicy) == 0 &&
> + (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & IMAGE_DATA_MEMORY_TYPE) != 0) {
> + DEBUG ((DEBUG_ERROR,
> + "ERROR: NX for image data is disabled but NX for its memory type(s) is enabled!\r\n"));
> + ASSERT (!(PcdGet32 (PcdImageProtectionPolicy) == 0 &&
> + (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & IMAGE_DATA_MEMORY_TYPE) != 0));
> + }
> +
> + //
> + // XD flag (BIT63) in page table entry is only valid if IA32_EFER.NXE is set.
> + // Features controlled by Following PCDs need this feature to be enabled.
> + //
> + return (PcdGetBool (PcdSetNxForStack) ||
> + PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0 ||
> + PcdGet32 (PcdImageProtectionPolicy) != 0);
> +}
> +
> /**
> Enable Execute Disable Bit.
>
> @@ -755,7 +805,10 @@ CreateIdentityMappingPageTables (
> //
> EnablePageTableProtection ((UINTN)PageMap, TRUE);
>
> - if (PcdGetBool (PcdSetNxForStack)) {
> + //
> + // Set IA32_EFER.NXE if necessary.
> + //
> + if (ToEnableExecuteDisableFeature ()) {
> EnableExecuteDisableBit ();
> }
>
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> index 85457ff937..9f152e6531 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> @@ -179,6 +179,39 @@ typedef struct {
> UINTN FreePages;
> } PAGE_TABLE_POOL;
>
> +//
> +// Bit field repsentations of some EFI_MEMORY_TYPE, for page table initialization.
> +//
> +#define STACK_MEMORY_TYPE (1 << EfiBootServicesData) /* 0x10 */
> +#define IMAGE_DATA_MEMORY_TYPE ((1 << EfiLoaderData) | /* 0x04 */\
> + (1 << EfiBootServicesData) | /* 0x10 */\
> + (1 << EfiRuntimeServicesData)/* 0x40 */\
> + ) /* 0x54 */
> +
> +/**
> + Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not.
> +
> + @retval TRUE IA32_EFER.NXE should be enabled.
> + @retval FALSE IA32_EFER.NXE should not be enabled.
> +
> +**/
> +BOOLEAN
> +ToEnableExecuteDisableFeature (
> + VOID
> + );
> +
> +/**
> + The function will check if Execute Disable Bit is available.
> +
> + @retval TRUE Execute Disable Bit is available.
> + @retval FALSE Execute Disable Bit is not available.
> +
> +**/
> +BOOLEAN
> +IsExecuteDisableBitAvailable (
> + VOID
> + );
> +
> /**
> Enable Execute Disable Bit.
>
> --
> 2.16.2.windows.1
>
next prev parent reply other threads:[~2018-09-14 6:50 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-14 5:13 [PATCH] MdeModulePkg/DxeIpl: support more NX related PCDs Jian J Wang
2018-09-14 5:46 ` Wang, Jian J
2018-09-14 6:04 ` Ard Biesheuvel
2018-09-14 6:50 ` Wang, Jian J [this message]
2018-09-14 9:27 ` Laszlo Ersek
2018-09-17 1:00 ` Wang, Jian J
2018-09-14 9:50 ` Laszlo Ersek
2018-09-17 2:11 ` Wang, Jian J
2018-09-17 5:57 ` Zeng, Star
2018-09-17 10:13 ` Laszlo Ersek
2018-09-18 1:21 ` Wang, Jian J
2018-09-18 8:46 ` Zeng, Star
2018-09-19 9:13 ` Wang, Jian J
2018-09-19 11:39 ` Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=D827630B58408649ACB04F44C510003624E340DE@SHSMSX103.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox