diff options
author | Linn Crosetto <linn@hp.com> | 2013-08-13 15:46:41 -0600 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-08-13 23:29:19 -0700 |
commit | 30e46b574a1db7d14404e52dca8e1aa5f5155fd2 (patch) | |
tree | 830c013b0e1bc37b77590df2998e664c89974571 /arch/x86/kernel/setup.c | |
parent | 2449f343e4adc778de1c3d45b5aa14fe788663f5 (diff) | |
download | op-kernel-dev-30e46b574a1db7d14404e52dca8e1aa5f5155fd2.zip op-kernel-dev-30e46b574a1db7d14404e52dca8e1aa5f5155fd2.tar.gz |
x86: avoid remapping data in parse_setup_data()
Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size
larger than early_memremap() is able to handle, which is currently
limited to 256kB. If this occurs it leads to a NULL dereference in
parse_setup_data().
To avoid this, remap the setup_data header and allow parsing functions
for individual types to handle their own data remapping.
Signed-off-by: Linn Crosetto <linn@hp.com>
Link: http://lkml.kernel.org/r/1376430401-67445-1-git-send-email-linn@hp.com
Acked-by: Yinghai Lu <yinghai@kernel.org>
Reviewed-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index de33798..b6b45e4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) static void __init parse_setup_data(void) { struct setup_data *data; - u64 pa_data; + u64 pa_data, pa_next; pa_data = boot_params.hdr.setup_data; while (pa_data) { - u32 data_len, map_len; + u32 data_len, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); - if (data_len > map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } + data_type = data->type; + pa_next = data->next; + early_iounmap(data, map_len); - switch (data->type) { + switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) default: break; } - pa_data = data->next; - early_iounmap(data, map_len); + pa_data = pa_next; } } |