aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-03-03 01:55:07 +0000
committerMichael Brown <mcb30@ipxe.org>2021-03-03 01:55:07 +0000
commit1c4917b6a739c887acbf6f7631b1f74084430ee7 (patch)
tree18aec658cbb858f62d63911f9533cb03d77c00a0
parent50d13907c440da96e352979da43f5eea68446db1 (diff)
downloadipxe-1c4917b6a739c887acbf6f7631b1f74084430ee7.zip
ipxe-1c4917b6a739c887acbf6f7631b1f74084430ee7.tar.gz
ipxe-1c4917b6a739c887acbf6f7631b1f74084430ee7.tar.bz2
[linux] Validate length of ACPI table read from sysfs
Consumers of acpi_find() will assume that returned structures include a valid table header and that the length in the table header is correct. These assumptions are necessary when dealing with raw ACPI tables, since there exists no independent source of length information. Ensure that these assumptions are also valid for ACPI tables read from sysfs. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/errfile.h1
-rw-r--r--src/interface/linux/linux_acpi.c10
2 files changed, 11 insertions, 0 deletions
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index 3daf7bd..e3bf9f5 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -389,6 +389,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_efi_autoexec ( ERRFILE_OTHER | 0x00540000 )
#define ERRFILE_efi_cachedhcp ( ERRFILE_OTHER | 0x00550000 )
#define ERRFILE_linux_sysfs ( ERRFILE_OTHER | 0x00560000 )
+#define ERRFILE_linux_acpi ( ERRFILE_OTHER | 0x00570000 )
/** @} */
diff --git a/src/interface/linux/linux_acpi.c b/src/interface/linux/linux_acpi.c
index 851cc54..e658936 100644
--- a/src/interface/linux/linux_acpi.c
+++ b/src/interface/linux/linux_acpi.c
@@ -57,6 +57,7 @@ static LIST_HEAD ( linux_acpi_tables );
*/
static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) {
struct linux_acpi_table *table;
+ struct acpi_header *header;
union {
uint32_t signature;
char filename[5];
@@ -100,6 +101,14 @@ static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) {
filename, strerror ( rc ) );
goto err_read;
}
+ header = user_to_virt ( table->data, 0 );
+ if ( ( ( ( size_t ) len ) < sizeof ( *header ) ) ||
+ ( ( ( size_t ) len ) < le32_to_cpu ( header->length ) ) ) {
+ rc = -ENOENT;
+ DBGC ( &linux_acpi_tables, "ACPI underlength %s (%d bytes)\n",
+ filename, len );
+ goto err_len;
+ }
/* Add to list of tables */
list_add ( &table->list, &linux_acpi_tables );
@@ -107,6 +116,7 @@ static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) {
return table->data;
+ err_len:
ufree ( table->data );
err_read:
free ( table );