linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access
@ 2020-06-26 15:58 Ard Biesheuvel
  2020-06-26 15:58 ` [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory Ard Biesheuvel
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-06-26 15:58 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-acpi, will, catalin.marinas, lorenzo.pieralisi,
	sudeep.holla, kernel-hardening, Ard Biesheuvel

v2:
- do a more elaborate check on the region, against the EFI memory map

v3:
- split into two patches
- fallback to __ioremap() for ACPI reclaim memory, in case it is not covered
  by the linear mapping (e.g., when booting a kdump kernel)

Ard Biesheuvel (2):
  arm64/acpi: disallow AML memory opregions to access kernel memory
  arm64/acpi: disallow writeable AML opregion mapping for EFI code
    regions

 arch/arm64/include/asm/acpi.h | 15 +---
 arch/arm64/kernel/acpi.c      | 75 ++++++++++++++++++++
 2 files changed, 76 insertions(+), 14 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
@ 2020-06-26 15:58 ` Ard Biesheuvel
  2020-09-28 16:02   ` Jonathan Cameron
  2020-06-26 15:58 ` [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions Ard Biesheuvel
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-06-26 15:58 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-acpi, will, catalin.marinas, lorenzo.pieralisi,
	sudeep.holla, kernel-hardening, Ard Biesheuvel,
	Jason A . Donenfeld

AML uses SystemMemory opregions to allow AML handlers to access MMIO
registers of, e.g., GPIO controllers, or access reserved regions of
memory that are owned by the firmware.

Currently, we also allow AML access to memory that is owned by the
kernel and mapped via the linear region, which does not seem to be
supported by a valid use case, and exposes the kernel's internal
state to AML methods that may be buggy and exploitable.

On arm64, ACPI support requires booting in EFI mode, and so we can cross
reference the requested region against the EFI memory map, rather than
just do a minimal check on the first page. So let's only permit regions
to be remapped by the ACPI core if
- they don't appear in the EFI memory map at all (which is the case for
  most MMIO), or
- they are covered by a single region in the EFI memory map, which is not
  of a type that describes memory that is given to the kernel at boot.

Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/acpi.h | 15 +----
 arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
 2 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index a45366c3909b..bd68e1b7f29f 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -47,20 +47,7 @@
 pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
 
 /* ACPI table mapping after acpi_permanent_mmap is set */
-static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
-					    acpi_size size)
-{
-	/* For normal memory we already have a cacheable mapping. */
-	if (memblock_is_map_memory(phys))
-		return (void __iomem *)__phys_to_virt(phys);
-
-	/*
-	 * We should still honor the memory's attribute here because
-	 * crash dump kernel possibly excludes some ACPI (reclaim)
-	 * regions from memblock list.
-	 */
-	return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
-}
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
 #define acpi_os_ioremap acpi_os_ioremap
 
 typedef u64 phys_cpuid_t;
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index a7586a4db142..01b861e225b0 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
 	return __pgprot(PROT_DEVICE_nGnRnE);
 }
 
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
+{
+	efi_memory_desc_t *md, *region = NULL;
+	pgprot_t prot;
+
+	if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
+		return NULL;
+
+	for_each_efi_memory_desc(md) {
+		u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+		if (phys < md->phys_addr || phys >= end)
+			continue;
+
+		if (phys + size > end) {
+			pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
+			return NULL;
+		}
+		region = md;
+		break;
+	}
+
+	/*
+	 * It is fine for AML to remap regions that are not represented in the
+	 * EFI memory map at all, as it only describes normal memory, and MMIO
+	 * regions that require a virtual mapping to make them accessible to
+	 * the EFI runtime services.
+	 */
+	prot = __pgprot(PROT_DEVICE_nGnRnE);
+	if (region) {
+		switch (region->type) {
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
+		case EFI_BOOT_SERVICES_CODE:
+		case EFI_BOOT_SERVICES_DATA:
+		case EFI_CONVENTIONAL_MEMORY:
+		case EFI_PERSISTENT_MEMORY:
+			pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
+			return NULL;
+
+		case EFI_ACPI_RECLAIM_MEMORY:
+			/*
+			 * ACPI reclaim memory is used to pass firmware tables
+			 * and other data that is intended for consumption by
+			 * the OS only, which may decide it wants to reclaim
+			 * that memory and use it for something else. We never
+			 * do that, but we usually add it to the linear map
+			 * anyway, in which case we should use the existing
+			 * mapping.
+			 */
+			if (memblock_is_map_memory(phys))
+				return (void __iomem *)__phys_to_virt(phys);
+			/* fall through */
+
+		default:
+			if (region->attribute & EFI_MEMORY_WB)
+				prot = PAGE_KERNEL;
+			else if (region->attribute & EFI_MEMORY_WT)
+				prot = __pgprot(PROT_NORMAL_WT);
+			else if (region->attribute & EFI_MEMORY_WC)
+				prot = __pgprot(PROT_NORMAL_NC);
+		}
+	}
+	return __ioremap(phys, size, prot);
+}
+
 /*
  * Claim Synchronous External Aborts as a firmware first notification.
  *
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
  2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
  2020-06-26 15:58 ` [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory Ard Biesheuvel
@ 2020-06-26 15:58 ` Ard Biesheuvel
  2021-02-06  3:11   ` Shawn Guo
  2020-07-08 16:17 ` [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-06-26 15:58 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-acpi, will, catalin.marinas, lorenzo.pieralisi,
	sudeep.holla, kernel-hardening, Ard Biesheuvel

Given that the contents of EFI runtime code and data regions are
provided by the firmware, as well as the DSDT, it is not unimaginable
that AML code exists today that accesses EFI runtime code regions using
a SystemMemory OpRegion. There is nothing fundamentally wrong with that,
but since we take great care to ensure that executable code is never
mapped writeable and executable at the same time, we should not permit
AML to create writable mapping.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/kernel/acpi.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 01b861e225b0..455966401102 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -301,6 +301,15 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
 			pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
 			return NULL;
 
+		case EFI_RUNTIME_SERVICES_CODE:
+			/*
+			 * This would be unusual, but not problematic per se,
+			 * as long as we take care not to create a writable
+			 * mapping for executable code.
+			 */
+			prot = PAGE_KERNEL_RO;
+			break;
+
 		case EFI_ACPI_RECLAIM_MEMORY:
 			/*
 			 * ACPI reclaim memory is used to pass firmware tables
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access
  2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
  2020-06-26 15:58 ` [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory Ard Biesheuvel
  2020-06-26 15:58 ` [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions Ard Biesheuvel
@ 2020-07-08 16:17 ` Ard Biesheuvel
  2020-07-09  8:42 ` Lorenzo Pieralisi
  2020-07-14 19:52 ` Catalin Marinas
  4 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-07-08 16:17 UTC (permalink / raw)
  To: Linux ARM, James Morse
  Cc: ACPI Devel Maling List, Will Deacon, Catalin Marinas,
	Lorenzo Pieralisi, Sudeep Holla, Kernel Hardening

(+ James)

On Fri, 26 Jun 2020 at 18:58, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> v2:
> - do a more elaborate check on the region, against the EFI memory map
>
> v3:
> - split into two patches
> - fallback to __ioremap() for ACPI reclaim memory, in case it is not covered
>   by the linear mapping (e.g., when booting a kdump kernel)
>
> Ard Biesheuvel (2):
>   arm64/acpi: disallow AML memory opregions to access kernel memory
>   arm64/acpi: disallow writeable AML opregion mapping for EFI code
>     regions
>

With some adult supervision from James (thanks!), I have given this a
spin myself with kexec under QEMU/kvm, to boot a crashkernel, and
everything works as expected.


>  arch/arm64/include/asm/acpi.h | 15 +---
>  arch/arm64/kernel/acpi.c      | 75 ++++++++++++++++++++
>  2 files changed, 76 insertions(+), 14 deletions(-)
>
> --
> 2.27.0
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access
  2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2020-07-08 16:17 ` [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
@ 2020-07-09  8:42 ` Lorenzo Pieralisi
  2020-07-14 19:52 ` Catalin Marinas
  4 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Pieralisi @ 2020-07-09  8:42 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-acpi, will, catalin.marinas,
	sudeep.holla, kernel-hardening

On Fri, Jun 26, 2020 at 05:58:30PM +0200, Ard Biesheuvel wrote:
> v2:
> - do a more elaborate check on the region, against the EFI memory map
> 
> v3:
> - split into two patches
> - fallback to __ioremap() for ACPI reclaim memory, in case it is not covered
>   by the linear mapping (e.g., when booting a kdump kernel)
> 
> Ard Biesheuvel (2):
>   arm64/acpi: disallow AML memory opregions to access kernel memory
>   arm64/acpi: disallow writeable AML opregion mapping for EFI code
>     regions
> 
>  arch/arm64/include/asm/acpi.h | 15 +---
>  arch/arm64/kernel/acpi.c      | 75 ++++++++++++++++++++
>  2 files changed, 76 insertions(+), 14 deletions(-)

Thanks Ard for fixing this, for the series:

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access
  2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2020-07-09  8:42 ` Lorenzo Pieralisi
@ 2020-07-14 19:52 ` Catalin Marinas
  4 siblings, 0 replies; 16+ messages in thread
From: Catalin Marinas @ 2020-07-14 19:52 UTC (permalink / raw)
  To: Ard Biesheuvel, linux-arm-kernel
  Cc: Will Deacon, sudeep.holla, kernel-hardening, linux-acpi,
	lorenzo.pieralisi

On Fri, 26 Jun 2020 17:58:30 +0200, Ard Biesheuvel wrote:
> v2:
> - do a more elaborate check on the region, against the EFI memory map
> 
> v3:
> - split into two patches
> - fallback to __ioremap() for ACPI reclaim memory, in case it is not covered
>   by the linear mapping (e.g., when booting a kdump kernel)
> 
> [...]

Applied to arm64 (for-next/acpi), thanks!

[1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
      https://git.kernel.org/arm64/c/1583052d111f
[2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
      https://git.kernel.org/arm64/c/325f5585ec36

-- 
Catalin


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-06-26 15:58 ` [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory Ard Biesheuvel
@ 2020-09-28 16:02   ` Jonathan Cameron
  2020-09-28 16:49     ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2020-09-28 16:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, Jason A . Donenfeld, lorenzo.pieralisi,
	kernel-hardening, catalin.marinas, linux-acpi, sudeep.holla,
	will, linuxarm

On Fri, 26 Jun 2020 17:58:31 +0200
Ard Biesheuvel <ardb@kernel.org> wrote:

> AML uses SystemMemory opregions to allow AML handlers to access MMIO
> registers of, e.g., GPIO controllers, or access reserved regions of
> memory that are owned by the firmware.
> 
> Currently, we also allow AML access to memory that is owned by the
> kernel and mapped via the linear region, which does not seem to be
> supported by a valid use case, and exposes the kernel's internal
> state to AML methods that may be buggy and exploitable.
> 
> On arm64, ACPI support requires booting in EFI mode, and so we can cross
> reference the requested region against the EFI memory map, rather than
> just do a minimal check on the first page. So let's only permit regions
> to be remapped by the ACPI core if
> - they don't appear in the EFI memory map at all (which is the case for
>   most MMIO), or
> - they are covered by a single region in the EFI memory map, which is not
>   of a type that describes memory that is given to the kernel at boot.
> 
> Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

Hi Ard,

Ran into a problem with this one. See below

> ---
>  arch/arm64/include/asm/acpi.h | 15 +----
>  arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
>  2 files changed, 67 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index a45366c3909b..bd68e1b7f29f 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -47,20 +47,7 @@
>  pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
>  
>  /* ACPI table mapping after acpi_permanent_mmap is set */
> -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> -					    acpi_size size)
> -{
> -	/* For normal memory we already have a cacheable mapping. */
> -	if (memblock_is_map_memory(phys))
> -		return (void __iomem *)__phys_to_virt(phys);
> -
> -	/*
> -	 * We should still honor the memory's attribute here because
> -	 * crash dump kernel possibly excludes some ACPI (reclaim)
> -	 * regions from memblock list.
> -	 */
> -	return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> -}
> +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
>  #define acpi_os_ioremap acpi_os_ioremap
>  
>  typedef u64 phys_cpuid_t;
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index a7586a4db142..01b861e225b0 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
>  	return __pgprot(PROT_DEVICE_nGnRnE);
>  }
>  
> +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> +{
> +	efi_memory_desc_t *md, *region = NULL;
> +	pgprot_t prot;
> +
> +	if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
> +		return NULL;
> +
> +	for_each_efi_memory_desc(md) {
> +		u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> +
> +		if (phys < md->phys_addr || phys >= end)
> +			continue;
> +
> +		if (phys + size > end) {
> +			pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
> +			return NULL;
> +		}
> +		region = md;
> +		break;
> +	}
> +
> +	/*
> +	 * It is fine for AML to remap regions that are not represented in the
> +	 * EFI memory map at all, as it only describes normal memory, and MMIO
> +	 * regions that require a virtual mapping to make them accessible to
> +	 * the EFI runtime services.
> +	 */
> +	prot = __pgprot(PROT_DEVICE_nGnRnE);
> +	if (region) {
> +		switch (region->type) {
> +		case EFI_LOADER_CODE:
> +		case EFI_LOADER_DATA:

Unfortunately this seems to have broken overriding of ACPI tables from an initrd.
My particular test environment is qemu + EDK2.

It only has obvious visible affect on tables that are used late in the boot such as PPTT
as they get dropped before they are used.

These are read after ACPICA is initialized and acpi_reallocate_root_table()
has been called.  The back trace is:

acpi_os_ioremap+0xfc/0x288
acpi_os_map_iomem+0xc4/0x188
acpi_os_map_memory+0x18/0x28
acpi_tb_acquire_table+0x54/0x8c
acpi_tb_validate_table+0x34/0x5c
acpi_tb_validate_temp_table+0x34/0x40
acpi_tb_verify_temp_table+0x48/0x250
acpi_reallocate_root_table+0x12c/0x160

Seems that the table is in a region of type EFI_LOADER_DATA.

I don't really know enough about this area to be sure what the right fix is or
even whether this is a kernel issue, or one that should be fixed elsewhere in
the stack.

For now I'm just carry a hack that treats EFI_LOADER_DATA in the same fashion as
EFI_ACPI_RECLAIM_MEMORY below.

What's the right way to fix this?

Jonathan


> +		case EFI_BOOT_SERVICES_CODE:
> +		case EFI_BOOT_SERVICES_DATA:
> +		case EFI_CONVENTIONAL_MEMORY:
> +		case EFI_PERSISTENT_MEMORY:
> +			pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
> +			return NULL;
> +
> +		case EFI_ACPI_RECLAIM_MEMORY:
> +			/*
> +			 * ACPI reclaim memory is used to pass firmware tables
> +			 * and other data that is intended for consumption by
> +			 * the OS only, which may decide it wants to reclaim
> +			 * that memory and use it for something else. We never
> +			 * do that, but we usually add it to the linear map
> +			 * anyway, in which case we should use the existing
> +			 * mapping.
> +			 */
> +			if (memblock_is_map_memory(phys))
> +				return (void __iomem *)__phys_to_virt(phys);
> +			/* fall through */
> +
> +		default:
> +			if (region->attribute & EFI_MEMORY_WB)
> +				prot = PAGE_KERNEL;
> +			else if (region->attribute & EFI_MEMORY_WT)
> +				prot = __pgprot(PROT_NORMAL_WT);
> +			else if (region->attribute & EFI_MEMORY_WC)
> +				prot = __pgprot(PROT_NORMAL_NC);
> +		}
> +	}
> +	return __ioremap(phys, size, prot);
> +}
> +
>  /*
>   * Claim Synchronous External Aborts as a firmware first notification.
>   *


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-09-28 16:02   ` Jonathan Cameron
@ 2020-09-28 16:49     ` Ard Biesheuvel
  2020-09-28 17:17       ` Jonathan Cameron
  0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-09-28 16:49 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Linux ARM, Jason A . Donenfeld, Lorenzo Pieralisi,
	Kernel Hardening, Catalin Marinas, ACPI Devel Maling List,
	Sudeep Holla, Will Deacon, Linuxarm

On Mon, 28 Sep 2020 at 18:02, Jonathan Cameron
<Jonathan.Cameron@huawei.com> wrote:
>
> On Fri, 26 Jun 2020 17:58:31 +0200
> Ard Biesheuvel <ardb@kernel.org> wrote:
>
> > AML uses SystemMemory opregions to allow AML handlers to access MMIO
> > registers of, e.g., GPIO controllers, or access reserved regions of
> > memory that are owned by the firmware.
> >
> > Currently, we also allow AML access to memory that is owned by the
> > kernel and mapped via the linear region, which does not seem to be
> > supported by a valid use case, and exposes the kernel's internal
> > state to AML methods that may be buggy and exploitable.
> >
> > On arm64, ACPI support requires booting in EFI mode, and so we can cross
> > reference the requested region against the EFI memory map, rather than
> > just do a minimal check on the first page. So let's only permit regions
> > to be remapped by the ACPI core if
> > - they don't appear in the EFI memory map at all (which is the case for
> >   most MMIO), or
> > - they are covered by a single region in the EFI memory map, which is not
> >   of a type that describes memory that is given to the kernel at boot.
> >
> > Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> Hi Ard,
>
> Ran into a problem with this one. See below
>
> > ---
> >  arch/arm64/include/asm/acpi.h | 15 +----
> >  arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
> >  2 files changed, 67 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> > index a45366c3909b..bd68e1b7f29f 100644
> > --- a/arch/arm64/include/asm/acpi.h
> > +++ b/arch/arm64/include/asm/acpi.h
> > @@ -47,20 +47,7 @@
> >  pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
> >
> >  /* ACPI table mapping after acpi_permanent_mmap is set */
> > -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> > -                                         acpi_size size)
> > -{
> > -     /* For normal memory we already have a cacheable mapping. */
> > -     if (memblock_is_map_memory(phys))
> > -             return (void __iomem *)__phys_to_virt(phys);
> > -
> > -     /*
> > -      * We should still honor the memory's attribute here because
> > -      * crash dump kernel possibly excludes some ACPI (reclaim)
> > -      * regions from memblock list.
> > -      */
> > -     return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> > -}
> > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
> >  #define acpi_os_ioremap acpi_os_ioremap
> >
> >  typedef u64 phys_cpuid_t;
> > diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> > index a7586a4db142..01b861e225b0 100644
> > --- a/arch/arm64/kernel/acpi.c
> > +++ b/arch/arm64/kernel/acpi.c
> > @@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
> >       return __pgprot(PROT_DEVICE_nGnRnE);
> >  }
> >
> > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> > +{
> > +     efi_memory_desc_t *md, *region = NULL;
> > +     pgprot_t prot;
> > +
> > +     if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
> > +             return NULL;
> > +
> > +     for_each_efi_memory_desc(md) {
> > +             u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> > +
> > +             if (phys < md->phys_addr || phys >= end)
> > +                     continue;
> > +
> > +             if (phys + size > end) {
> > +                     pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
> > +                     return NULL;
> > +             }
> > +             region = md;
> > +             break;
> > +     }
> > +
> > +     /*
> > +      * It is fine for AML to remap regions that are not represented in the
> > +      * EFI memory map at all, as it only describes normal memory, and MMIO
> > +      * regions that require a virtual mapping to make them accessible to
> > +      * the EFI runtime services.
> > +      */
> > +     prot = __pgprot(PROT_DEVICE_nGnRnE);
> > +     if (region) {
> > +             switch (region->type) {
> > +             case EFI_LOADER_CODE:
> > +             case EFI_LOADER_DATA:
>
> Unfortunately this seems to have broken overriding of ACPI tables from an initrd.
> My particular test environment is qemu + EDK2.
>
> It only has obvious visible affect on tables that are used late in the boot such as PPTT
> as they get dropped before they are used.
>
> These are read after ACPICA is initialized and acpi_reallocate_root_table()
> has been called.  The back trace is:
>
> acpi_os_ioremap+0xfc/0x288
> acpi_os_map_iomem+0xc4/0x188
> acpi_os_map_memory+0x18/0x28
> acpi_tb_acquire_table+0x54/0x8c
> acpi_tb_validate_table+0x34/0x5c
> acpi_tb_validate_temp_table+0x34/0x40
> acpi_tb_verify_temp_table+0x48/0x250
> acpi_reallocate_root_table+0x12c/0x160
>
> Seems that the table is in a region of type EFI_LOADER_DATA.
>
> I don't really know enough about this area to be sure what the right fix is or
> even whether this is a kernel issue, or one that should be fixed elsewhere in
> the stack.
>
> For now I'm just carry a hack that treats EFI_LOADER_DATA in the same fashion as
> EFI_ACPI_RECLAIM_MEMORY below.
>
> What's the right way to fix this?
>

Hi Jonathan,

That is an excellent question.

The purpose of this change is to ensure that firmware cannot
manipulate the internal state of the kernel. So as long as we can
ensure that this memory is not claimed by the kernel's memory
subsystem, we should be fine.

Since this is an obvious debug feature, what we could do is reserve
this memory permanently in some way, and make the test take this into
account.

Do you have a full stack trace? How early does this run?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-09-28 16:49     ` Ard Biesheuvel
@ 2020-09-28 17:17       ` Jonathan Cameron
  2020-09-29  9:29         ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2020-09-28 17:17 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux ARM, Jason A . Donenfeld, Lorenzo Pieralisi,
	Kernel Hardening, Catalin Marinas, ACPI Devel Maling List,
	Sudeep Holla, Will Deacon, Linuxarm

On Mon, 28 Sep 2020 18:49:35 +0200
Ard Biesheuvel <ardb@kernel.org> wrote:

> On Mon, 28 Sep 2020 at 18:02, Jonathan Cameron
> <Jonathan.Cameron@huawei.com> wrote:
> >
> > On Fri, 26 Jun 2020 17:58:31 +0200
> > Ard Biesheuvel <ardb@kernel.org> wrote:
> >  
> > > AML uses SystemMemory opregions to allow AML handlers to access MMIO
> > > registers of, e.g., GPIO controllers, or access reserved regions of
> > > memory that are owned by the firmware.
> > >
> > > Currently, we also allow AML access to memory that is owned by the
> > > kernel and mapped via the linear region, which does not seem to be
> > > supported by a valid use case, and exposes the kernel's internal
> > > state to AML methods that may be buggy and exploitable.
> > >
> > > On arm64, ACPI support requires booting in EFI mode, and so we can cross
> > > reference the requested region against the EFI memory map, rather than
> > > just do a minimal check on the first page. So let's only permit regions
> > > to be remapped by the ACPI core if
> > > - they don't appear in the EFI memory map at all (which is the case for
> > >   most MMIO), or
> > > - they are covered by a single region in the EFI memory map, which is not
> > >   of a type that describes memory that is given to the kernel at boot.
> > >
> > > Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>  
> >
> > Hi Ard,
> >
> > Ran into a problem with this one. See below
> >  
> > > ---
> > >  arch/arm64/include/asm/acpi.h | 15 +----
> > >  arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
> > >  2 files changed, 67 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> > > index a45366c3909b..bd68e1b7f29f 100644
> > > --- a/arch/arm64/include/asm/acpi.h
> > > +++ b/arch/arm64/include/asm/acpi.h
> > > @@ -47,20 +47,7 @@
> > >  pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
> > >
> > >  /* ACPI table mapping after acpi_permanent_mmap is set */
> > > -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> > > -                                         acpi_size size)
> > > -{
> > > -     /* For normal memory we already have a cacheable mapping. */
> > > -     if (memblock_is_map_memory(phys))
> > > -             return (void __iomem *)__phys_to_virt(phys);
> > > -
> > > -     /*
> > > -      * We should still honor the memory's attribute here because
> > > -      * crash dump kernel possibly excludes some ACPI (reclaim)
> > > -      * regions from memblock list.
> > > -      */
> > > -     return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> > > -}
> > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
> > >  #define acpi_os_ioremap acpi_os_ioremap
> > >
> > >  typedef u64 phys_cpuid_t;
> > > diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> > > index a7586a4db142..01b861e225b0 100644
> > > --- a/arch/arm64/kernel/acpi.c
> > > +++ b/arch/arm64/kernel/acpi.c
> > > @@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
> > >       return __pgprot(PROT_DEVICE_nGnRnE);
> > >  }
> > >
> > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> > > +{
> > > +     efi_memory_desc_t *md, *region = NULL;
> > > +     pgprot_t prot;
> > > +
> > > +     if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
> > > +             return NULL;
> > > +
> > > +     for_each_efi_memory_desc(md) {
> > > +             u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> > > +
> > > +             if (phys < md->phys_addr || phys >= end)
> > > +                     continue;
> > > +
> > > +             if (phys + size > end) {
> > > +                     pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
> > > +                     return NULL;
> > > +             }
> > > +             region = md;
> > > +             break;
> > > +     }
> > > +
> > > +     /*
> > > +      * It is fine for AML to remap regions that are not represented in the
> > > +      * EFI memory map at all, as it only describes normal memory, and MMIO
> > > +      * regions that require a virtual mapping to make them accessible to
> > > +      * the EFI runtime services.
> > > +      */
> > > +     prot = __pgprot(PROT_DEVICE_nGnRnE);
> > > +     if (region) {
> > > +             switch (region->type) {
> > > +             case EFI_LOADER_CODE:
> > > +             case EFI_LOADER_DATA:  
> >
> > Unfortunately this seems to have broken overriding of ACPI tables from an initrd.
> > My particular test environment is qemu + EDK2.
> >
> > It only has obvious visible affect on tables that are used late in the boot such as PPTT
> > as they get dropped before they are used.
> >
> > These are read after ACPICA is initialized and acpi_reallocate_root_table()
> > has been called.  The back trace is:
> >
> > acpi_os_ioremap+0xfc/0x288
> > acpi_os_map_iomem+0xc4/0x188
> > acpi_os_map_memory+0x18/0x28
> > acpi_tb_acquire_table+0x54/0x8c
> > acpi_tb_validate_table+0x34/0x5c
> > acpi_tb_validate_temp_table+0x34/0x40
> > acpi_tb_verify_temp_table+0x48/0x250
> > acpi_reallocate_root_table+0x12c/0x160
> >
> > Seems that the table is in a region of type EFI_LOADER_DATA.
> >
> > I don't really know enough about this area to be sure what the right fix is or
> > even whether this is a kernel issue, or one that should be fixed elsewhere in
> > the stack.
> >
> > For now I'm just carry a hack that treats EFI_LOADER_DATA in the same fashion as
> > EFI_ACPI_RECLAIM_MEMORY below.
> >
> > What's the right way to fix this?
> >  
> 
> Hi Jonathan,
> 
> That is an excellent question.
> 
> The purpose of this change is to ensure that firmware cannot
> manipulate the internal state of the kernel. So as long as we can
> ensure that this memory is not claimed by the kernel's memory
> subsystem, we should be fine.
> 
> Since this is an obvious debug feature, what we could do is reserve
> this memory permanently in some way, and make the test take this into
> account.

Whilst it is a debug feature, I wonder if it gets shipped in production
hardware.  If not, could be we cynical and just drop the check if the
relevant config option is enabled?

Perhaps just don't release the EFI_LOADER_DATA for other use? (if
this option is enabled only)

> 
> Do you have a full stack trace? How early does this run?

For the place where it first occurs, ie the trace above, the acpi_reallocate_root_table() is
the call from acpi_early_init() from start_kernel().

We hit the table a lot during later calls though and hence would run into the
same problem.

Jonathan



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-09-28 17:17       ` Jonathan Cameron
@ 2020-09-29  9:29         ` Ard Biesheuvel
  2020-09-30  9:27           ` Jonathan Cameron
  0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-09-29  9:29 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Linux ARM, Jason A . Donenfeld, Lorenzo Pieralisi,
	Kernel Hardening, Catalin Marinas, ACPI Devel Maling List,
	Sudeep Holla, Will Deacon, Linuxarm

On Mon, 28 Sep 2020 at 19:18, Jonathan Cameron
<Jonathan.Cameron@huawei.com> wrote:
>
> On Mon, 28 Sep 2020 18:49:35 +0200
> Ard Biesheuvel <ardb@kernel.org> wrote:
>
> > On Mon, 28 Sep 2020 at 18:02, Jonathan Cameron
> > <Jonathan.Cameron@huawei.com> wrote:
> > >
> > > On Fri, 26 Jun 2020 17:58:31 +0200
> > > Ard Biesheuvel <ardb@kernel.org> wrote:
> > >
> > > > AML uses SystemMemory opregions to allow AML handlers to access MMIO
> > > > registers of, e.g., GPIO controllers, or access reserved regions of
> > > > memory that are owned by the firmware.
> > > >
> > > > Currently, we also allow AML access to memory that is owned by the
> > > > kernel and mapped via the linear region, which does not seem to be
> > > > supported by a valid use case, and exposes the kernel's internal
> > > > state to AML methods that may be buggy and exploitable.
> > > >
> > > > On arm64, ACPI support requires booting in EFI mode, and so we can cross
> > > > reference the requested region against the EFI memory map, rather than
> > > > just do a minimal check on the first page. So let's only permit regions
> > > > to be remapped by the ACPI core if
> > > > - they don't appear in the EFI memory map at all (which is the case for
> > > >   most MMIO), or
> > > > - they are covered by a single region in the EFI memory map, which is not
> > > >   of a type that describes memory that is given to the kernel at boot.
> > > >
> > > > Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
> > > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > >
> > > Hi Ard,
> > >
> > > Ran into a problem with this one. See below
> > >
> > > > ---
> > > >  arch/arm64/include/asm/acpi.h | 15 +----
> > > >  arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
> > > >  2 files changed, 67 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> > > > index a45366c3909b..bd68e1b7f29f 100644
> > > > --- a/arch/arm64/include/asm/acpi.h
> > > > +++ b/arch/arm64/include/asm/acpi.h
> > > > @@ -47,20 +47,7 @@
> > > >  pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
> > > >
> > > >  /* ACPI table mapping after acpi_permanent_mmap is set */
> > > > -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> > > > -                                         acpi_size size)
> > > > -{
> > > > -     /* For normal memory we already have a cacheable mapping. */
> > > > -     if (memblock_is_map_memory(phys))
> > > > -             return (void __iomem *)__phys_to_virt(phys);
> > > > -
> > > > -     /*
> > > > -      * We should still honor the memory's attribute here because
> > > > -      * crash dump kernel possibly excludes some ACPI (reclaim)
> > > > -      * regions from memblock list.
> > > > -      */
> > > > -     return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> > > > -}
> > > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
> > > >  #define acpi_os_ioremap acpi_os_ioremap
> > > >
> > > >  typedef u64 phys_cpuid_t;
> > > > diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> > > > index a7586a4db142..01b861e225b0 100644
> > > > --- a/arch/arm64/kernel/acpi.c
> > > > +++ b/arch/arm64/kernel/acpi.c
> > > > @@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
> > > >       return __pgprot(PROT_DEVICE_nGnRnE);
> > > >  }
> > > >
> > > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> > > > +{
> > > > +     efi_memory_desc_t *md, *region = NULL;
> > > > +     pgprot_t prot;
> > > > +
> > > > +     if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
> > > > +             return NULL;
> > > > +
> > > > +     for_each_efi_memory_desc(md) {
> > > > +             u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> > > > +
> > > > +             if (phys < md->phys_addr || phys >= end)
> > > > +                     continue;
> > > > +
> > > > +             if (phys + size > end) {
> > > > +                     pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
> > > > +                     return NULL;
> > > > +             }
> > > > +             region = md;
> > > > +             break;
> > > > +     }
> > > > +
> > > > +     /*
> > > > +      * It is fine for AML to remap regions that are not represented in the
> > > > +      * EFI memory map at all, as it only describes normal memory, and MMIO
> > > > +      * regions that require a virtual mapping to make them accessible to
> > > > +      * the EFI runtime services.
> > > > +      */
> > > > +     prot = __pgprot(PROT_DEVICE_nGnRnE);
> > > > +     if (region) {
> > > > +             switch (region->type) {
> > > > +             case EFI_LOADER_CODE:
> > > > +             case EFI_LOADER_DATA:
> > >
> > > Unfortunately this seems to have broken overriding of ACPI tables from an initrd.
> > > My particular test environment is qemu + EDK2.
> > >
> > > It only has obvious visible affect on tables that are used late in the boot such as PPTT
> > > as they get dropped before they are used.
> > >
> > > These are read after ACPICA is initialized and acpi_reallocate_root_table()
> > > has been called.  The back trace is:
> > >
> > > acpi_os_ioremap+0xfc/0x288
> > > acpi_os_map_iomem+0xc4/0x188
> > > acpi_os_map_memory+0x18/0x28
> > > acpi_tb_acquire_table+0x54/0x8c
> > > acpi_tb_validate_table+0x34/0x5c
> > > acpi_tb_validate_temp_table+0x34/0x40
> > > acpi_tb_verify_temp_table+0x48/0x250
> > > acpi_reallocate_root_table+0x12c/0x160
> > >
> > > Seems that the table is in a region of type EFI_LOADER_DATA.
> > >
> > > I don't really know enough about this area to be sure what the right fix is or
> > > even whether this is a kernel issue, or one that should be fixed elsewhere in
> > > the stack.
> > >
> > > For now I'm just carry a hack that treats EFI_LOADER_DATA in the same fashion as
> > > EFI_ACPI_RECLAIM_MEMORY below.
> > >
> > > What's the right way to fix this?
> > >
> >
> > Hi Jonathan,
> >
> > That is an excellent question.
> >
> > The purpose of this change is to ensure that firmware cannot
> > manipulate the internal state of the kernel. So as long as we can
> > ensure that this memory is not claimed by the kernel's memory
> > subsystem, we should be fine.
> >
> > Since this is an obvious debug feature, what we could do is reserve
> > this memory permanently in some way, and make the test take this into
> > account.
>
> Whilst it is a debug feature, I wonder if it gets shipped in production
> hardware.  If not, could be we cynical and just drop the check if the
> relevant config option is enabled?
>
> Perhaps just don't release the EFI_LOADER_DATA for other use? (if
> this option is enabled only)
>
> >
> > Do you have a full stack trace? How early does this run?
>
> For the place where it first occurs, ie the trace above, the acpi_reallocate_root_table() is
> the call from acpi_early_init() from start_kernel().
>
> We hit the table a lot during later calls though and hence would run into the
> same problem.
>

Could you try the patch below? Since the memory holding the tables is
already memblock_reserve()d, we can just mark it NOMAP, and permit r/o
remapping of NOMAP regions.

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index a85174d05473..84da869c5ac4 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -298,8 +298,11 @@ void __iomem
*acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
                case EFI_BOOT_SERVICES_DATA:
                case EFI_CONVENTIONAL_MEMORY:
                case EFI_PERSISTENT_MEMORY:
-                       pr_warn(FW_BUG "requested region covers kernel
memory @ %pa\n", &phys);
-                       return NULL;
+                       if (memblock_is_map_memory(phys)) {
+                               pr_warn(FW_BUG "requested region
covers kernel memory @ %pa\n", &phys);
+                               return NULL;
+                       }
+                       fallthrough;

                case EFI_RUNTIME_SERVICES_CODE:
                        /*
@@ -388,3 +391,8 @@ int apei_claim_sea(struct pt_regs *regs)

        return err;
 }
+
+void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
+{
+       memblock_mark_nomap(addr, size);
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 1e4cdc6c7ae2..64ae25c59d55 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -958,7 +958,7 @@ void acpi_os_set_prepare_extended_sleep(int
(*func)(u8 sleep_state,
 acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
                                           u32 val_a, u32 val_b);

-#ifdef CONFIG_X86
+#ifndef CONFIG_IA64
 void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
 #else
 static inline void arch_reserve_mem_area(acpi_physical_address addr,

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-09-29  9:29         ` Ard Biesheuvel
@ 2020-09-30  9:27           ` Jonathan Cameron
  2020-09-30 17:19             ` Catalin Marinas
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2020-09-30  9:27 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux ARM, Jason A . Donenfeld, Lorenzo Pieralisi,
	Kernel Hardening, Catalin Marinas, ACPI Devel Maling List,
	Sudeep Holla, Will Deacon, Linuxarm

On Tue, 29 Sep 2020 11:29:48 +0200
Ard Biesheuvel <ardb@kernel.org> wrote:

> On Mon, 28 Sep 2020 at 19:18, Jonathan Cameron
> <Jonathan.Cameron@huawei.com> wrote:
> >
> > On Mon, 28 Sep 2020 18:49:35 +0200
> > Ard Biesheuvel <ardb@kernel.org> wrote:
> >  
> > > On Mon, 28 Sep 2020 at 18:02, Jonathan Cameron
> > > <Jonathan.Cameron@huawei.com> wrote:  
> > > >
> > > > On Fri, 26 Jun 2020 17:58:31 +0200
> > > > Ard Biesheuvel <ardb@kernel.org> wrote:
> > > >  
> > > > > AML uses SystemMemory opregions to allow AML handlers to access MMIO
> > > > > registers of, e.g., GPIO controllers, or access reserved regions of
> > > > > memory that are owned by the firmware.
> > > > >
> > > > > Currently, we also allow AML access to memory that is owned by the
> > > > > kernel and mapped via the linear region, which does not seem to be
> > > > > supported by a valid use case, and exposes the kernel's internal
> > > > > state to AML methods that may be buggy and exploitable.
> > > > >
> > > > > On arm64, ACPI support requires booting in EFI mode, and so we can cross
> > > > > reference the requested region against the EFI memory map, rather than
> > > > > just do a minimal check on the first page. So let's only permit regions
> > > > > to be remapped by the ACPI core if
> > > > > - they don't appear in the EFI memory map at all (which is the case for
> > > > >   most MMIO), or
> > > > > - they are covered by a single region in the EFI memory map, which is not
> > > > >   of a type that describes memory that is given to the kernel at boot.
> > > > >
> > > > > Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
> > > > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>  
> > > >
> > > > Hi Ard,
> > > >
> > > > Ran into a problem with this one. See below
> > > >  
> > > > > ---
> > > > >  arch/arm64/include/asm/acpi.h | 15 +----
> > > > >  arch/arm64/kernel/acpi.c      | 66 ++++++++++++++++++++
> > > > >  2 files changed, 67 insertions(+), 14 deletions(-)
> > > > >
> > > > > diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> > > > > index a45366c3909b..bd68e1b7f29f 100644
> > > > > --- a/arch/arm64/include/asm/acpi.h
> > > > > +++ b/arch/arm64/include/asm/acpi.h
> > > > > @@ -47,20 +47,7 @@
> > > > >  pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
> > > > >
> > > > >  /* ACPI table mapping after acpi_permanent_mmap is set */
> > > > > -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> > > > > -                                         acpi_size size)
> > > > > -{
> > > > > -     /* For normal memory we already have a cacheable mapping. */
> > > > > -     if (memblock_is_map_memory(phys))
> > > > > -             return (void __iomem *)__phys_to_virt(phys);
> > > > > -
> > > > > -     /*
> > > > > -      * We should still honor the memory's attribute here because
> > > > > -      * crash dump kernel possibly excludes some ACPI (reclaim)
> > > > > -      * regions from memblock list.
> > > > > -      */
> > > > > -     return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> > > > > -}
> > > > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
> > > > >  #define acpi_os_ioremap acpi_os_ioremap
> > > > >
> > > > >  typedef u64 phys_cpuid_t;
> > > > > diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> > > > > index a7586a4db142..01b861e225b0 100644
> > > > > --- a/arch/arm64/kernel/acpi.c
> > > > > +++ b/arch/arm64/kernel/acpi.c
> > > > > @@ -261,6 +261,72 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
> > > > >       return __pgprot(PROT_DEVICE_nGnRnE);
> > > > >  }
> > > > >
> > > > > +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> > > > > +{
> > > > > +     efi_memory_desc_t *md, *region = NULL;
> > > > > +     pgprot_t prot;
> > > > > +
> > > > > +     if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
> > > > > +             return NULL;
> > > > > +
> > > > > +     for_each_efi_memory_desc(md) {
> > > > > +             u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> > > > > +
> > > > > +             if (phys < md->phys_addr || phys >= end)
> > > > > +                     continue;
> > > > > +
> > > > > +             if (phys + size > end) {
> > > > > +                     pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
> > > > > +                     return NULL;
> > > > > +             }
> > > > > +             region = md;
> > > > > +             break;
> > > > > +     }
> > > > > +
> > > > > +     /*
> > > > > +      * It is fine for AML to remap regions that are not represented in the
> > > > > +      * EFI memory map at all, as it only describes normal memory, and MMIO
> > > > > +      * regions that require a virtual mapping to make them accessible to
> > > > > +      * the EFI runtime services.
> > > > > +      */
> > > > > +     prot = __pgprot(PROT_DEVICE_nGnRnE);
> > > > > +     if (region) {
> > > > > +             switch (region->type) {
> > > > > +             case EFI_LOADER_CODE:
> > > > > +             case EFI_LOADER_DATA:  
> > > >
> > > > Unfortunately this seems to have broken overriding of ACPI tables from an initrd.
> > > > My particular test environment is qemu + EDK2.
> > > >
> > > > It only has obvious visible affect on tables that are used late in the boot such as PPTT
> > > > as they get dropped before they are used.
> > > >
> > > > These are read after ACPICA is initialized and acpi_reallocate_root_table()
> > > > has been called.  The back trace is:
> > > >
> > > > acpi_os_ioremap+0xfc/0x288
> > > > acpi_os_map_iomem+0xc4/0x188
> > > > acpi_os_map_memory+0x18/0x28
> > > > acpi_tb_acquire_table+0x54/0x8c
> > > > acpi_tb_validate_table+0x34/0x5c
> > > > acpi_tb_validate_temp_table+0x34/0x40
> > > > acpi_tb_verify_temp_table+0x48/0x250
> > > > acpi_reallocate_root_table+0x12c/0x160
> > > >
> > > > Seems that the table is in a region of type EFI_LOADER_DATA.
> > > >
> > > > I don't really know enough about this area to be sure what the right fix is or
> > > > even whether this is a kernel issue, or one that should be fixed elsewhere in
> > > > the stack.
> > > >
> > > > For now I'm just carry a hack that treats EFI_LOADER_DATA in the same fashion as
> > > > EFI_ACPI_RECLAIM_MEMORY below.
> > > >
> > > > What's the right way to fix this?
> > > >  
> > >
> > > Hi Jonathan,
> > >
> > > That is an excellent question.
> > >
> > > The purpose of this change is to ensure that firmware cannot
> > > manipulate the internal state of the kernel. So as long as we can
> > > ensure that this memory is not claimed by the kernel's memory
> > > subsystem, we should be fine.
> > >
> > > Since this is an obvious debug feature, what we could do is reserve
> > > this memory permanently in some way, and make the test take this into
> > > account.  
> >
> > Whilst it is a debug feature, I wonder if it gets shipped in production
> > hardware.  If not, could be we cynical and just drop the check if the
> > relevant config option is enabled?
> >
> > Perhaps just don't release the EFI_LOADER_DATA for other use? (if
> > this option is enabled only)
> >  
> > >
> > > Do you have a full stack trace? How early does this run?  
> >
> > For the place where it first occurs, ie the trace above, the acpi_reallocate_root_table() is
> > the call from acpi_early_init() from start_kernel().
> >
> > We hit the table a lot during later calls though and hence would run into the
> > same problem.
> >  
> 
> Could you try the patch below? Since the memory holding the tables is
> already memblock_reserve()d, we can just mark it NOMAP, and permit r/o
> remapping of NOMAP regions.

Looks good.  Thanks.

Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>


> 
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index a85174d05473..84da869c5ac4 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -298,8 +298,11 @@ void __iomem
> *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
>                 case EFI_BOOT_SERVICES_DATA:
>                 case EFI_CONVENTIONAL_MEMORY:
>                 case EFI_PERSISTENT_MEMORY:
> -                       pr_warn(FW_BUG "requested region covers kernel
> memory @ %pa\n", &phys);
> -                       return NULL;
> +                       if (memblock_is_map_memory(phys)) {
> +                               pr_warn(FW_BUG "requested region
> covers kernel memory @ %pa\n", &phys);
> +                               return NULL;
> +                       }
> +                       fallthrough;
> 
>                 case EFI_RUNTIME_SERVICES_CODE:
>                         /*
> @@ -388,3 +391,8 @@ int apei_claim_sea(struct pt_regs *regs)
> 
>         return err;
>  }
> +
> +void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
> +{
> +       memblock_mark_nomap(addr, size);
> +}
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 1e4cdc6c7ae2..64ae25c59d55 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -958,7 +958,7 @@ void acpi_os_set_prepare_extended_sleep(int
> (*func)(u8 sleep_state,
>  acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
>                                            u32 val_a, u32 val_b);
> 
> -#ifdef CONFIG_X86
> +#ifndef CONFIG_IA64
>  void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
>  #else
>  static inline void arch_reserve_mem_area(acpi_physical_address addr,


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory
  2020-09-30  9:27           ` Jonathan Cameron
@ 2020-09-30 17:19             ` Catalin Marinas
  0 siblings, 0 replies; 16+ messages in thread
From: Catalin Marinas @ 2020-09-30 17:19 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Ard Biesheuvel, Linux ARM, Jason A . Donenfeld,
	Lorenzo Pieralisi, Kernel Hardening, ACPI Devel Maling List,
	Sudeep Holla, Will Deacon, Linuxarm

Hi Jonathan,

On Wed, Sep 30, 2020 at 10:27:22AM +0100, Jonathan Cameron wrote:
> On Tue, 29 Sep 2020 11:29:48 +0200 Ard Biesheuvel <ardb@kernel.org> wrote:
> > Could you try the patch below? Since the memory holding the tables is
> > already memblock_reserve()d, we can just mark it NOMAP, and permit r/o
> > remapping of NOMAP regions.
> 
> Looks good.  Thanks.
> 
> Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

Could you please try the updated patch that Ard posted. There are a few
minor differences:

https://lore.kernel.org/linux-acpi/20200929132522.18067-1-ardb@kernel.org/

Thanks.

-- 
Catalin

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
  2020-06-26 15:58 ` [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions Ard Biesheuvel
@ 2021-02-06  3:11   ` Shawn Guo
  2021-02-06  8:10     ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Shawn Guo @ 2021-02-06  3:11 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, lorenzo.pieralisi, kernel-hardening,
	catalin.marinas, linux-acpi, sudeep.holla, will, linux-arm-msm

Hi Ard,

On Fri, Jun 26, 2020 at 05:58:32PM +0200, Ard Biesheuvel wrote:
> Given that the contents of EFI runtime code and data regions are
> provided by the firmware, as well as the DSDT, it is not unimaginable
> that AML code exists today that accesses EFI runtime code regions using
> a SystemMemory OpRegion. There is nothing fundamentally wrong with that,
> but since we take great care to ensure that executable code is never
> mapped writeable and executable at the same time, we should not permit
> AML to create writable mapping.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

I'm booting Lenovo Flex 5G laptop with ACPI, and seeing this change
causes a memory abort[1] when upgrading ACPI tables via initrd[2].
Dropping this change seems to fix the issue for me.  But does that
looks like a correct fix to you?

Shawn

[1] https://fileserver.linaro.org/s/iDe9SaZeNNkyNxG
[2] Documentation/admin-guide/acpi/initrd_table_override.rst

> ---
>  arch/arm64/kernel/acpi.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index 01b861e225b0..455966401102 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -301,6 +301,15 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
>  			pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
>  			return NULL;
>  
> +		case EFI_RUNTIME_SERVICES_CODE:
> +			/*
> +			 * This would be unusual, but not problematic per se,
> +			 * as long as we take care not to create a writable
> +			 * mapping for executable code.
> +			 */
> +			prot = PAGE_KERNEL_RO;
> +			break;
> +
>  		case EFI_ACPI_RECLAIM_MEMORY:
>  			/*
>  			 * ACPI reclaim memory is used to pass firmware tables
> -- 
> 2.27.0

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
  2021-02-06  3:11   ` Shawn Guo
@ 2021-02-06  8:10     ` Ard Biesheuvel
  2021-02-06 10:17       ` Ard Biesheuvel
  2021-02-06 10:45       ` Shawn Guo
  0 siblings, 2 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2021-02-06  8:10 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Linux ARM, Lorenzo Pieralisi, Kernel Hardening, Catalin Marinas,
	ACPI Devel Maling List, Sudeep Holla, Will Deacon, linux-arm-msm

On Sat, 6 Feb 2021 at 04:11, Shawn Guo <shawn.guo@linaro.org> wrote:
>
> Hi Ard,
>
> On Fri, Jun 26, 2020 at 05:58:32PM +0200, Ard Biesheuvel wrote:
> > Given that the contents of EFI runtime code and data regions are
> > provided by the firmware, as well as the DSDT, it is not unimaginable
> > that AML code exists today that accesses EFI runtime code regions using
> > a SystemMemory OpRegion. There is nothing fundamentally wrong with that,
> > but since we take great care to ensure that executable code is never
> > mapped writeable and executable at the same time, we should not permit
> > AML to create writable mapping.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> I'm booting Lenovo Flex 5G laptop with ACPI, and seeing this change
> causes a memory abort[1] when upgrading ACPI tables via initrd[2].
> Dropping this change seems to fix the issue for me.  But does that
> looks like a correct fix to you?
>
> Shawn
>
> [1] https://fileserver.linaro.org/s/iDe9SaZeNNkyNxG
> [2] Documentation/admin-guide/acpi/initrd_table_override.rst
>

Can you check whether reverting

32cf1a12cad43358e47dac8014379c2f33dfbed4

fixes the issue too?

If it does, please report this as a regression. The OS should not
modify firmware provided tables in-place, regardless of how they were
delivered.

BTW I recently started using my Yoga C630 with Debian, and I am quite
happy with it! Thanks a lot for spending the time on the installer
etc.

I have observed some issues while using mine - I'm happy to share
them, on a mailing list or anywhere else.



> > ---
> >  arch/arm64/kernel/acpi.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> >
> > diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> > index 01b861e225b0..455966401102 100644
> > --- a/arch/arm64/kernel/acpi.c
> > +++ b/arch/arm64/kernel/acpi.c
> > @@ -301,6 +301,15 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
> >                       pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
> >                       return NULL;
> >
> > +             case EFI_RUNTIME_SERVICES_CODE:
> > +                     /*
> > +                      * This would be unusual, but not problematic per se,
> > +                      * as long as we take care not to create a writable
> > +                      * mapping for executable code.
> > +                      */
> > +                     prot = PAGE_KERNEL_RO;
> > +                     break;
> > +
> >               case EFI_ACPI_RECLAIM_MEMORY:
> >                       /*
> >                        * ACPI reclaim memory is used to pass firmware tables
> > --
> > 2.27.0

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
  2021-02-06  8:10     ` Ard Biesheuvel
@ 2021-02-06 10:17       ` Ard Biesheuvel
  2021-02-06 10:45       ` Shawn Guo
  1 sibling, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2021-02-06 10:17 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Linux ARM, Lorenzo Pieralisi, Kernel Hardening, Catalin Marinas,
	ACPI Devel Maling List, Sudeep Holla, Will Deacon, linux-arm-msm

On Sat, 6 Feb 2021 at 09:10, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Sat, 6 Feb 2021 at 04:11, Shawn Guo <shawn.guo@linaro.org> wrote:
> >
> > Hi Ard,
> >
> > On Fri, Jun 26, 2020 at 05:58:32PM +0200, Ard Biesheuvel wrote:
> > > Given that the contents of EFI runtime code and data regions are
> > > provided by the firmware, as well as the DSDT, it is not unimaginable
> > > that AML code exists today that accesses EFI runtime code regions using
> > > a SystemMemory OpRegion. There is nothing fundamentally wrong with that,
> > > but since we take great care to ensure that executable code is never
> > > mapped writeable and executable at the same time, we should not permit
> > > AML to create writable mapping.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >
> > I'm booting Lenovo Flex 5G laptop with ACPI, and seeing this change
> > causes a memory abort[1] when upgrading ACPI tables via initrd[2].
> > Dropping this change seems to fix the issue for me.  But does that
> > looks like a correct fix to you?
> >
> > Shawn
> >
> > [1] https://fileserver.linaro.org/s/iDe9SaZeNNkyNxG
> > [2] Documentation/admin-guide/acpi/initrd_table_override.rst
> >
>
> Can you check whether reverting
>
> 32cf1a12cad43358e47dac8014379c2f33dfbed4
>
> fixes the issue too?
>
> If it does, please report this as a regression. The OS should not
> modify firmware provided tables in-place, regardless of how they were
> delivered.
>

That patch modifies firmware provided tables in-place, which
invalidates checksums and TPM measurements, so it needs to be reverted
in any case, and I have already sent out  the patch for doing so.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions
  2021-02-06  8:10     ` Ard Biesheuvel
  2021-02-06 10:17       ` Ard Biesheuvel
@ 2021-02-06 10:45       ` Shawn Guo
  1 sibling, 0 replies; 16+ messages in thread
From: Shawn Guo @ 2021-02-06 10:45 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux ARM, Lorenzo Pieralisi, Kernel Hardening, Catalin Marinas,
	ACPI Devel Maling List, Sudeep Holla, Will Deacon, linux-arm-msm

On Sat, Feb 06, 2021 at 09:10:19AM +0100, Ard Biesheuvel wrote:
> On Sat, 6 Feb 2021 at 04:11, Shawn Guo <shawn.guo@linaro.org> wrote:
> >
> > Hi Ard,
> >
> > On Fri, Jun 26, 2020 at 05:58:32PM +0200, Ard Biesheuvel wrote:
> > > Given that the contents of EFI runtime code and data regions are
> > > provided by the firmware, as well as the DSDT, it is not unimaginable
> > > that AML code exists today that accesses EFI runtime code regions using
> > > a SystemMemory OpRegion. There is nothing fundamentally wrong with that,
> > > but since we take great care to ensure that executable code is never
> > > mapped writeable and executable at the same time, we should not permit
> > > AML to create writable mapping.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >
> > I'm booting Lenovo Flex 5G laptop with ACPI, and seeing this change
> > causes a memory abort[1] when upgrading ACPI tables via initrd[2].
> > Dropping this change seems to fix the issue for me.  But does that
> > looks like a correct fix to you?
> >
> > Shawn
> >
> > [1] https://fileserver.linaro.org/s/iDe9SaZeNNkyNxG
> > [2] Documentation/admin-guide/acpi/initrd_table_override.rst
> >
> 
> Can you check whether reverting
> 
> 32cf1a12cad43358e47dac8014379c2f33dfbed4
> 
> fixes the issue too?

Yes, it does.

> If it does, please report this as a regression. The OS should not
> modify firmware provided tables in-place, regardless of how they were
> delivered.
> 
> BTW I recently started using my Yoga C630 with Debian, and I am quite
> happy with it! Thanks a lot for spending the time on the installer
> etc.

Cool, glad to hear that!

Shawn

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2021-02-06 10:46 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-26 15:58 [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
2020-06-26 15:58 ` [PATCH v3 1/2] arm64/acpi: disallow AML memory opregions to access kernel memory Ard Biesheuvel
2020-09-28 16:02   ` Jonathan Cameron
2020-09-28 16:49     ` Ard Biesheuvel
2020-09-28 17:17       ` Jonathan Cameron
2020-09-29  9:29         ` Ard Biesheuvel
2020-09-30  9:27           ` Jonathan Cameron
2020-09-30 17:19             ` Catalin Marinas
2020-06-26 15:58 ` [PATCH v3 2/2] arm64/acpi: disallow writeable AML opregion mapping for EFI code regions Ard Biesheuvel
2021-02-06  3:11   ` Shawn Guo
2021-02-06  8:10     ` Ard Biesheuvel
2021-02-06 10:17       ` Ard Biesheuvel
2021-02-06 10:45       ` Shawn Guo
2020-07-08 16:17 ` [PATCH v3 0/2] arm64/acpi: restrict AML opregion memory access Ard Biesheuvel
2020-07-09  8:42 ` Lorenzo Pieralisi
2020-07-14 19:52 ` Catalin Marinas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).