From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c0b::242; helo=mail-it0-x242.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it0-x242.google.com (mail-it0-x242.google.com [IPv6:2607:f8b0:4001:c0b::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 22D4921130707 for ; Thu, 13 Sep 2018 23:04:47 -0700 (PDT) Received: by mail-it0-x242.google.com with SMTP id p129-v6so1127605ite.3 for ; Thu, 13 Sep 2018 23:04:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=oLoDZM1pPoZgzuv5jak5VV19CrYf2jA1ao671cyPT2k=; b=L4kWRylQYZ+022GdxUKJAXbjE2cBDds5Gu85RifTM1uWb9sYs0BIbiBTgTs0MAGLHR H/YLrdOpDBbG5dLRyq4ge3S4RdU99/bTHfpIdullQV3XjcW9UBqM2E6KBZhHniHKrdoe htiKPHwESq8Wsr+c8NFy3uyzuNSZV71eMMxc8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=oLoDZM1pPoZgzuv5jak5VV19CrYf2jA1ao671cyPT2k=; b=dQX6SsEZV+fZ6PlFOEXuflHJfLtF/HThQJyChFEQSQJSQg/7WhBDCYlVq07J8JaN6m njFo0UaEOwza9Qvm9WJEXbIKJG2yrWQBzkAdMR20Wn3cUiHolYrCvL7qFmYCJ+prRud0 +OjREY19dKSckgP8OwVv6ygPU6HgtzdtHSMg9UiTzLYBMZ/YXAX0HZdeCpzJ6aFRdglj BZmaA9VgGuZgeBEXWrYh3x5m2ckRb6BgrL1Vl3PAG27+8T9SviaL+YuclPpE5JSTYHan g1l+Puq+VBA9su5Lo5gGnmaFO2VdqiZykewPHFsDAFhlxRdQO29J+TrA7fEfs0wM4iFi zyDA== X-Gm-Message-State: APzg51BPebt1cg/Mrbl1Z+HiqHbib8m8NX9ZwRyLfKw/OivIGU2xsG0c Pxw6vJldmQKpsCs5EfFu73F9S3WKdcfUzzhi6YNBrw== X-Google-Smtp-Source: ANB0VdaAavQotnVMXzBdTVypHvof0MxCerxwtyldFYqb4/pjykeKncCeZll+dfVSwnthViw5swLsJWX3vEhF9P+x4u8= X-Received: by 2002:a24:8309:: with SMTP id d9-v6mr1074422ite.123.1536905087013; Thu, 13 Sep 2018 23:04:47 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a6b:2848:0:0:0:0:0 with HTTP; Thu, 13 Sep 2018 23:04:46 -0700 (PDT) In-Reply-To: <20180914051335.2644-1-jian.j.wang@intel.com> References: <20180914051335.2644-1-jian.j.wang@intel.com> From: Ard Biesheuvel Date: Fri, 14 Sep 2018 08:04:46 +0200 Message-ID: To: Jian J Wang Cc: "edk2-devel@lists.01.org" , Star Zeng , Laszlo Ersek , Ruiyu Ni , Jiewen Yao Subject: Re: [PATCH] MdeModulePkg/DxeIpl: support more NX related PCDs X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Sep 2018 06:04:48 -0000 Content-Type: text/plain; charset="UTF-8" On 14 September 2018 at 07:13, Jian J Wang 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 < > PcdImageProtectionPolicy == 0 && > (PcdDxeNxMemoryProtectionPolicy & (1 << EfiRuntimeServicesData)) != 0 > > PcdImageProtectionPolicy == 0 && > (PcdDxeNxMemoryProtectionPolicy & (1 < > PcdImageProtectionPolicy == 0 && > (PcdDxeNxMemoryProtectionPolicy & (1 < > 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 > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Cc: Ruiyu Ni > Cc: Jiewen Yao > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Jian J Wang > --- > 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 >