diff options
author | Huang Ying <ying.huang@intel.com> | 2012-10-16 17:26:36 +0200 |
---|---|---|
committer | Huang Ying <ying.huang@intel.com> | 2012-10-16 17:26:36 +0200 |
commit | 915ef37d7cc8fcac5b37eb0b40c693754fcd12ab (patch) | |
tree | c396c41fc57983ffabe7079115d8722c0f08a989 /xen/drivers/acpi | |
parent | 02be82737e0659e231d0be71d5d5de1081cef295 (diff) | |
download | xen-915ef37d7cc8fcac5b37eb0b40c693754fcd12ab.tar.gz xen-915ef37d7cc8fcac5b37eb0b40c693754fcd12ab.tar.bz2 xen-915ef37d7cc8fcac5b37eb0b40c693754fcd12ab.zip |
ACPI: fix APEI related table size checking
On Huang Ying's machine:
erst_tab->header_length == sizeof(struct acpi_table_einj)
but Yinghai reported that on his machine,
erst_tab->header_length == sizeof(struct acpi_table_einj) -
sizeof(struct acpi_table_header)
To make erst table size checking code works on all systems, both
testing are treated as PASS.
Same situation applies to einj_tab->header_length, so corresponding
table size checking is changed in similar way too.
Originally-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Huang Ying <ying.huang@intel.com>
- use switch() for better readability
- add comment explaining why a formally invalid size it also being
accepted
- check erst_tab->header.length before even looking at
erst_tab->header_length
- prefer sizeof(*erst_tab) over sizeof(struct acpi_table_erst)
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Committed-by: Jan Beulich <jbeulich@suse.com>
Diffstat (limited to 'xen/drivers/acpi')
-rw-r--r-- | xen/drivers/acpi/apei/erst.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/xen/drivers/acpi/apei/erst.c b/xen/drivers/acpi/apei/erst.c index eb666a6fca..31ce50d73c 100644 --- a/xen/drivers/acpi/apei/erst.c +++ b/xen/drivers/acpi/apei/erst.c @@ -715,12 +715,23 @@ int erst_clear(u64 record_id) static int __init erst_check_table(struct acpi_table_erst *erst_tab) { - if (erst_tab->header_length != sizeof(struct acpi_table_erst)) + if (erst_tab->header.length < sizeof(*erst_tab)) return -EINVAL; - if (erst_tab->header.length < sizeof(struct acpi_table_erst)) + + switch (erst_tab->header_length) { + case sizeof(*erst_tab) - sizeof(erst_tab->header): + /* + * While invalid per specification, there are (early?) systems + * indicating the full header size here, so accept that value too. + */ + case sizeof(*erst_tab): + break; + default: return -EINVAL; + } + if (erst_tab->entries != - (erst_tab->header.length - sizeof(struct acpi_table_erst)) / + (erst_tab->header.length - sizeof(*erst_tab)) / sizeof(struct acpi_erst_entry)) return -EINVAL; |