All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@linux.ibm.com>
To: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: David Hildenbrand <david@redhat.com>,
	George Kennedy <george.kennedy@oracle.com>,
	Robert Moore <robert.moore@intel.com>,
	Erik Kaneda <erik.kaneda@intel.com>,
	Rafael Wysocki <rafael.j.wysocki@intel.com>,
	Len Brown <lenb@kernel.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	"open list:ACPI COMPONENT ARCHITECTURE (ACPICA)"
	<devel@acpica.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	Dan Carpenter <dan.carpenter@oracle.com>,
	Dhaval Giani <dhaval.giani@oracle.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Vlastimil Babka <vbabka@suse.cz>,
	Oscar Salvador <osalvador@suse.de>,
	Wei Yang <richard.weiyang@linux.alibaba.com>,
	Pankaj Gupta <pankaj.gupta.linux@gmail.com>,
	Michal Hocko <mhocko@suse.com>
Subject: Re: [PATCH 1/1] ACPI: fix acpi table use after free
Date: Sun, 14 Mar 2021 20:59:51 +0200	[thread overview]
Message-ID: <YE5dJ6U3nPWsXY4D@linux.ibm.com> (raw)
In-Reply-To: <CAJZ5v0jOpNJrOt5xn-1YkSB9Q15NZS2cxmsGKAU945YNbs+hOw@mail.gmail.com>

On Thu, Mar 11, 2021 at 04:36:31PM +0100, Rafael J. Wysocki wrote:
> On Wed, Mar 10, 2021 at 8:47 PM David Hildenbrand <david@redhat.com> wrote:
> > >
> > > There is some care that should be taken to make sure we get the order
> > > right, but I don't see a fundamental issue here.
> 
> Me neither.
> 
> > > If I understand correctly, Rafael's concern is about changing the parts of
> > > ACPICA that should be OS agnostic, so I think we just need another place to
> > > call memblock_reserve() rather than acpi_tb_install_table_with_override().
> 
> Something like this.
> 
> There is also the problem that memblock_reserve() needs to be called
> for all of the tables early enough, which will require some reordering
> of the early init code.
> 
> > > Since the reservation should be done early in x86::setup_arch() (and
> > > probably in arm64::setup_arch()) we might just have a function that parses
> > > table headers and reserves them, similarly to how we parse the tables
> > > during KASLR setup.
> 
> Right.

I've looked at it a bit more and we do something like the patch below that
nearly duplicates acpi_tb_parse_root_table() which is not very nice.
Besides, reserving ACPI tables early and then calling acpi_table_init()
(and acpi_tb_parse_root_table() again would mean doing the dance with
early_memremap() twice for no good reason.

I believe the most effective way to deal with this would be to have a
function that does parsing, reservation and installs the tables supplied by
the firmware which can be called really early and then another function
that overrides tables if needed a some later point.

--------------------------------------------------------------

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d883176ef2ce..48bcb1c355ad 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -910,6 +910,8 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	acpi_reserve_tables();
+
 	if (efi_enabled(EFI_BOOT))
 		efi_memblock_x86_reserve_range();
 #ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index e2d0046799a2..6cb5bcf3fb49 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -133,6 +133,9 @@ void
 acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
 				    u8 override, u32 *table_index);
 
+acpi_physical_address
+acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
+
 acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
 
 acpi_status
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 4b9b329a5a92..2ad3c08915d4 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -14,10 +14,6 @@
 #define _COMPONENT          ACPI_TABLES
 ACPI_MODULE_NAME("tbutils")
 
-/* Local prototypes */
-static acpi_physical_address
-acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
-
 #if (!ACPI_REDUCED_HARDWARE)
 /*******************************************************************************
  *
@@ -162,7 +158,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
  *
  ******************************************************************************/
 
-static acpi_physical_address
+acpi_physical_address
 acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
 {
 	u64 address64;
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index e48690a006a4..e4b721bada04 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -23,6 +23,9 @@
 #include <linux/security.h>
 #include "internal.h"
 
+#include "acpica/aclocal.h"
+#include "acpica/actables.h"
+
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
 #include CONFIG_ACPI_CUSTOM_DSDT_FILE
 #endif
@@ -809,6 +812,107 @@ int __init acpi_table_init(void)
 	return 0;
 }
 
+void __init acpi_reserve_tables(void)
+{
+	u32 i, table_count, table_entry_size, length;
+	acpi_physical_address rsdp_address, address;
+	struct acpi_table_header *table, *hdr;
+	struct acpi_table_rsdp *rsdp;
+	u8 *table_entry;
+
+	rsdp_address = acpi_os_get_root_pointer();
+	if (!rsdp_address) {
+		pr_debug("%s: no rsdp_address\n", __func__);
+		return;
+	}
+
+	/* Map the entire RSDP and extract the address of the RSDT or XSDT */
+	rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
+	if (!rsdp) {
+		pr_debug("%s: can't map rsdp\n", __func__);
+		return;
+	}
+
+	memblock_reserve(rsdp_address, sizeof(struct acpi_table_rsdp));
+
+	/* Use XSDT if present and not overridden. Otherwise, use RSDT */
+	if ((rsdp->revision > 1) &&
+	    rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) {
+		address = (acpi_physical_address)rsdp->xsdt_physical_address;
+		table_entry_size = ACPI_XSDT_ENTRY_SIZE;
+	} else {
+		address = (acpi_physical_address)rsdp->rsdt_physical_address;
+		table_entry_size = ACPI_RSDT_ENTRY_SIZE;
+	}
+
+	/*
+	 * It is not possible to map more than one entry in some environments,
+	 * so unmap the RSDP here before mapping other tables
+	 */
+	acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
+
+	/* Map the RSDT/XSDT table header to get the full table length */
+
+	table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+	if (!table) {
+		pr_debug("%s: can't map [RX]SDT header\n", __func__);
+		return;
+	}
+
+	/*
+	 * Validate length of the table, and map entire table.
+	 * Minimum length table must contain at least one entry.
+	 */
+	length = table->length;
+	acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+	if (length < (sizeof(struct acpi_table_header) + table_entry_size)) {
+		pr_debug("Invalid table length 0x%X in RSDT/XSDT", length);
+		return;
+	}
+
+	memblock_reserve(address, length);
+
+	table = acpi_os_map_memory(address, length);
+	if (!table) {
+		pr_debug("%s: can't map [RX]SDT table\n", __func__);
+		return;
+	}
+
+	/* Get the number of entries and pointer to first entry */
+	table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
+			    table_entry_size);
+	table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
+
+	/* reserve tables pointed from the RSDT/XSDT */
+	for (i = 0; i < table_count; i++, table_entry += table_entry_size) {
+
+		/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
+
+		address =
+		    acpi_tb_get_root_table_entry(table_entry, table_entry_size);
+
+		/* Skip NULL entries in RSDT/XSDT */
+
+		if (!address)
+			continue;
+
+		hdr = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+		if (!hdr) {
+			pr_debug("%s: can't map %d header\n", __func__, i);
+			continue;
+		}
+
+		memblock_reserve(address, hdr->length);
+
+		/* FIXME: parse FADT and reserve embedded there tables */
+
+		acpi_os_unmap_memory(hdr, sizeof(struct acpi_table_header));
+	}
+
+	acpi_os_unmap_memory(table, length);
+}
+
 static int __init acpi_parse_apic_instance(char *str)
 {
 	if (!str)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 9f432411e988..d8688e4b6726 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -226,6 +226,8 @@ void acpi_boot_table_init (void);
 int acpi_mps_check (void);
 int acpi_numa_init (void);
 
+void acpi_reserve_tables(void);
+
 int acpi_table_init (void);
 int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
 int __init acpi_table_parse_entries(char *id, unsigned long table_size,

-- 
Sincerely yours,
Mike.

  reply	other threads:[~2021-03-14 19:01 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-03 20:09 [PATCH 1/1] ACPI: fix acpi table use after free George Kennedy
2021-03-04 12:14 ` [Devel] " Rafael J. Wysocki
2021-03-04 12:14   ` Rafael J. Wysocki
2021-03-04 23:14   ` George Kennedy
2021-03-05 13:30     ` [Devel] " Rafael J. Wysocki
2021-03-05 13:30       ` Rafael J. Wysocki
2021-03-05 13:40       ` David Hildenbrand
2021-03-05 15:24         ` George Kennedy
2021-03-10 18:39         ` [Devel] " Rafael J. Wysocki
2021-03-10 18:39           ` Rafael J. Wysocki
2021-03-10 18:54           ` [Devel] " Rafael J. Wysocki
2021-03-10 18:54             ` Rafael J. Wysocki
2021-03-10 19:10             ` David Hildenbrand
2021-03-10 19:38               ` Mike Rapoport
2021-03-10 19:47                 ` David Hildenbrand
2021-03-11 15:36                   ` [Devel] " Rafael J. Wysocki
2021-03-11 15:36                     ` Rafael J. Wysocki
2021-03-14 18:59                     ` Mike Rapoport [this message]
2021-03-15 16:19                       ` [Devel] " Rafael J. Wysocki
2021-03-15 16:19                         ` Rafael J. Wysocki
2021-03-17 20:14                         ` [Devel] " Rafael J. Wysocki
2021-03-17 20:14                           ` Rafael J. Wysocki
2021-03-17 22:28                           ` George Kennedy
2021-03-18  7:25                           ` Mike Rapoport
2021-03-18 10:50                             ` [Devel] " Rafael J. Wysocki
2021-03-18 10:50                               ` Rafael J. Wysocki
2021-03-18 15:22                               ` [Devel] " Rafael J. Wysocki
2021-03-18 15:22                                 ` Rafael J. Wysocki
2021-03-20  8:25                                 ` Mike Rapoport
2021-03-23 19:26                                   ` [PATCH] ACPI: tables: x86: Reserve memory occupied by ACPI tables Rafael J. Wysocki
2021-03-24  8:24                                     ` Mike Rapoport
2021-03-24 13:27                                       ` Rafael J. Wysocki
2021-03-24 13:49                                         ` George Kennedy
2021-03-24 15:42                                         ` George Kennedy
2021-03-24 15:44                                           ` Rafael J. Wysocki
2021-03-07  7:46       ` [PATCH 1/1] ACPI: fix acpi table use after free Mike Rapoport
2021-03-09 17:54         ` Mike Rapoport
2021-03-09 18:29           ` [Devel] " Rafael J. Wysocki
2021-03-09 18:29             ` Rafael J. Wysocki
2021-03-09 20:16             ` Mike Rapoport
  -- strict thread matches above, loose matches on Subject: below --
2021-03-15 18:05 [Devel] " Rafael J. Wysocki
2021-03-15 18:05 ` Rafael J. Wysocki
2021-03-18 15:42 [Devel] " Rafael J. Wysocki
2021-03-18 15:42 ` Rafael J. Wysocki
2021-03-22 16:57 [Devel] " Rafael J. Wysocki
2021-03-22 16:57 ` Rafael J. Wysocki

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-all 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=YE5dJ6U3nPWsXY4D@linux.ibm.com \
    --to=rppt@linux.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=dan.carpenter@oracle.com \
    --cc=david@redhat.com \
    --cc=devel@acpica.org \
    --cc=dhaval.giani@oracle.com \
    --cc=erik.kaneda@intel.com \
    --cc=george.kennedy@oracle.com \
    --cc=konrad.wilk@oracle.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhocko@suse.com \
    --cc=osalvador@suse.de \
    --cc=pankaj.gupta.linux@gmail.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rafael@kernel.org \
    --cc=richard.weiyang@linux.alibaba.com \
    --cc=robert.moore@intel.com \
    --cc=vbabka@suse.cz \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.