public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yao, Jiewen" <jiewen.yao@intel.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
	"afish@apple.com" <afish@apple.com>,
	"leif.lindholm@linaro.org" <leif.lindholm@linaro.org>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>
Cc: "Tian, Feng" <feng.tian@intel.com>,
	"lersek@redhat.com" <lersek@redhat.com>,
	"Zeng, Star" <star.zeng@intel.com>,
	"Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [PATCH v2 0/5] RFC: increased memory protection
Date: Sat, 25 Feb 2017 04:04:25 +0000	[thread overview]
Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A8F539C@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <1487948699-3179-1-git-send-email-ard.biesheuvel@linaro.org>

Thank you Ard. I like this patch - simple and obvious.

I put all my comment together for your consideration.

1) Patch V2 1/5 -- reviewed-by: Jiewen.yao@Intel.com
2) Patch V2 2/5 - reviewed-by: Jiewen.yao@intel.com
3) Patch V2 3/5 - reviewed-by: Jiewen.yao@intel.com

4) Patch V2 4/5 -
4.1) Can we follow the style of other memory type definition? (Such as PcdMemoryProfileMemoryType)

The reason is that people may want to have fine granularity control for loader data or persistent memory.

My proposal is below:
//////////////////////////
  ## Set DXE memory protection policy. The policy is bitwise.
  #  If a bit is set, memory regions of the associated type will be mapped
  #  non-executable.<BR><BR>
  #
  # Below is bit mask for this PCD: (Order is same as UEFI spec)<BR>
  #  EfiReservedMemoryType          0x0001<BR>
  #  EfiLoaderCode                  0x0002<BR>
  #  EfiLoaderData                  0x0004<BR>
  #  EfiBootServicesCode            0x0008<BR>
  #  EfiBootServicesData            0x0010<BR>
  #  EfiRuntimeServicesCode         0x0020<BR>
  #  EfiRuntimeServicesData         0x0040<BR>
  #  EfiConventionalMemory          0x0080<BR>
  #  EfiUnusableMemory              0x0100<BR>
  #  EfiACPIReclaimMemory           0x0200<BR>
  #  EfiACPIMemoryNVS               0x0400<BR>
  #  EfiMemoryMappedIO              0x0800<BR>
  #  EfiMemoryMappedIOPortSpace     0x1000<BR>
  #  EfiPalCode                     0x2000<BR>
  #  EfiPersistentMemory            0x4000<BR>
  #  OEM Reserved       0x4000000000000000<BR>
  #  OS Reserved        0x8000000000000000<BR>
  #
  # NOTE: User must NOT set NX protection for EfiLoaderCode / EfiBootServicesCode / EfiRuntimeServicesCode. <BR>
  #
  # e.g. 0x7FD5 can be used for all memory except Code. <BR>
  # e.g. 0x7BD4 can be used for all memory except Code and ACPINVS/Reserved. <BR>
  #
  # @Prompt Set DXE memory protection policy.
  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeMemoryProtectionPolicy|0x0000000|UINT64|0x00001048
//////////////////////////

Then the C-code can be like below:

//////////////////////////
UINT64
GetPermissionAttributeForMemoryType (
  IN EFI_MEMORY_TYPE    MemoryType
  )
{
  UINT64 TestBit;

  if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
    TestBit = BIT63;
  } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
    TestBit = BIT62;
  } else {
    TestBit = LShiftU64 (1, MemoryType);
  }

  if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
    return EFI_MEMORY_XP;
  } else {
    return 0;
  }
}
//////////////////////////

4.2) I prefer to setting default value to be 0x0 - to keep the compatibility, at least for X86 platform. (I have no strong opinion for ARM.)

4.3) I feel we might use a better name - PcdDxeNxMemoryProtectionPolicy (add "NX" keyword), so that people can know this PCD is to control NX attribute.
Maybe we can apply other protection such as RO or RP later.
What about your idea?

5) Patch V2 5/5 -
5.1) I think we should check the allocation happens IsInSmm, and skip ApplyMemoryProtection() if it is in Smm.

The reason is that SMM maintains its own page table.

Below code is for your reference.

//////////////////////////
BOOLEAN
IsInSmm (
  VOID
  )
{
  BOOLEAN     InSmm;

  InSmm = FALSE;
  if (gSmmBase2 != NULL) {
    gSmmBase2->InSmm (gSmmBase2, &InSmm);
  }
  return InSmm;
}
//////////////////////////

5.2) I think we are not able to call ApplyMemoryProtection() inside of CoreAllocatePoolPages() and CoreFreePoolPages().
The reason is that: X86 CPU page table update algo might  call AllocatePages(), to support page table split from big page to small page.
CoreAcquireMemoryLock() may fail in such case, because the memory map is locked in AllocatePool().

I think a safety way is to call ApplyMemoryProtection() at CoreAllocatePool(), after InstallMemoryAttributesTableOnMemoryAllocation(). We do same thing as CoreAllocatePage().

We can update CoreInternalAllocatePool() to return the necessary parameters back to indicate if CoreAllocatePoolPages() happens, and where is the new pages.
Same thing for CoreFreePool().

5.3) In order to reduce the fragmentation of X86 page table, I recommend we do a little enhancement in ApplyDxeMemoryProtectionPolicy().
Can we can combine the memory need NX together and call SetUefiImageMemoryAttributes() once?

You may refer to MergeMemoryMapForNotPresentEntry() in UefiCpuPkg\PiSmmCpuDxeSmm\SmmCpuMemoryManagement.c,
which combines the memory map entry together, if the adjacent entry requires same not-present attribute.

In this case, we could define MergeMemoryMapForNonExecutable() in MemoryProtection.c, and used by ApplyDxeMemoryProtectionPolicy().
I believe it helps X86 platforms.


Thank you
Yao Jiewen

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard
> Biesheuvel
> Sent: Friday, February 24, 2017 11:05 PM
> To: edk2-devel@lists.01.org; afish@apple.com; leif.lindholm@linaro.org; Kinney,
> Michael D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Yao, Jiewen <jiewen.yao@intel.com>
> Cc: Tian, Feng <feng.tian@intel.com>; lersek@redhat.com; Zeng, Star
> <star.zeng@intel.com>; Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [edk2] [PATCH v2 0/5] RFC: increased memory protection
>
> Hello all,
>
> This is a proof of concept implementation that removes all executable
> permissions from writable memory regions, which greatly enhances security.
> It is based on Jiewen's recent work, which is a step in the right direction,
> but still leaves most of memory exploitable due to the default R+W+X
> permissions.
>
> The idea is that the implementation of the CPU arch protocol goes over the
> memory map and removes exec permissions from all regions that are not already
> marked as 'code. This requires some preparatory work to ensure that the
> DxeCore
> itself is covered by a BootServicesCode region, not a BootServicesData region.
> Exec permissions are re-granted selectively, when the PE/COFF loader allocates
> the space for it. Combined with Jiewen's code/data split, this removes all
> RWX mapped regions.
>
> Changes since v1:
> - allocate code pages for PE/COFF images in PeiCore, so that DxeCore pages have
>   the expected memory type (as suggested by Jiewen)
> - add patch to inhibit page table updates while syncing the GCD memory space
>   map with the page tables
> - add PCD to set memory protection policy, which allows the policy for reserved
>   and ACPI/NVS memory to be configured separately
> - move attribute manipulation into DxeCore page allocation code: this way, we
>   should be able to solve the EBC case by allocating BootServicesCode pool
>   memory explicitly.
>
> Ard Biesheuvel (5):
>   ArmPkg/CpuDxe: ignore attribute changes during SyncCacheConfig()
>   MdeModulePkg/PeiCore: allocate BootServicesCode memory for PE/COFF
>     images
>   MdeModulePkg/DxeCore: pass pool type to CoreFreePoolPages ()
>   MdeModulePkg: define PCD for DXE memory protection policy
>   MdeModulePkg/DxeCore: implement memory protection policy
>
>  ArmPkg/Drivers/CpuDxe/CpuDxe.c                |   3 +
>  ArmPkg/Drivers/CpuDxe/CpuDxe.h                |   1 +
>  ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c          |   4 +
>  MdeModulePkg/Core/Dxe/DxeMain.inf             |   1 +
>  MdeModulePkg/Core/Dxe/Mem/Imem.h              |   2 +
>  MdeModulePkg/Core/Dxe/Mem/Page.c              | 106
> ++++++++++++++++++++
>  MdeModulePkg/Core/Dxe/Mem/Pool.c              |   5 +-
>  MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 104
> ++++++++++++++++++-
>  MdeModulePkg/Core/Pei/Image/Image.c           |  10 +-
>  MdeModulePkg/MdeModulePkg.dec                 |  16 +++
>  10 files changed, 246 insertions(+), 6 deletions(-)
>
> --
> 2.7.4
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


  parent reply	other threads:[~2017-02-25  4:04 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-24 15:04 [PATCH v2 0/5] RFC: increased memory protection Ard Biesheuvel
2017-02-24 15:04 ` [PATCH v2 1/5] ArmPkg/CpuDxe: ignore attribute changes during SyncCacheConfig() Ard Biesheuvel
2017-02-24 15:04 ` [PATCH v2 2/5] MdeModulePkg/PeiCore: allocate BootServicesCode memory for PE/COFF images Ard Biesheuvel
2017-02-24 15:04 ` [PATCH v2 3/5] MdeModulePkg/DxeCore: pass pool type to CoreFreePoolPages () Ard Biesheuvel
2017-02-24 15:04 ` [PATCH v2 4/5] MdeModulePkg: define PCD for DXE memory protection policy Ard Biesheuvel
2017-02-24 15:04 ` [PATCH v2 5/5] MdeModulePkg/DxeCore: implement " Ard Biesheuvel
2017-02-25  4:04 ` Yao, Jiewen [this message]
2017-02-26 15:09   ` [PATCH v2 0/5] RFC: increased memory protection Ard Biesheuvel
2017-02-27  8:56     ` 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=74D8A39837DF1E4DA445A8C0B3885C503A8F539C@shsmsx102.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