OOPS in identify_cpu() on CPUs without CPUID
PATCH RESEND v2 1/1 OOPS in identify_cpu() on CPUs without CPUID
Kernel is broken for x86 CPUs without CPUID since 2.6.28. It crashes with NULL pointer dereference in identify_cpu():
766 generic_identify(c);
767
768--> if (this_cpu->c_identify)
769 this_cpu->c_identify(c);
this_cpu is NULL. This is because it's only initialized in get_cpu_vendor() function, which is not called if the CPU has no CPUID instruction.
arch/x86/kernel/cpu/common.c +24 -24
@@ -58,7 +58,30 @@alloc_bootmem_cpumask_var (&cpu_sibling_setup_mask); } -static const struct cpu_dev *this_cpu__cpuinitdata ; +static void __cpuinit default_init (struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_64 +display_cacheinfo (c); +#else +/* Not much we can do here... */ +/* Check if at least it has cpuid */ +if (c->cpuid_level ==-1 ) { +/* No cpuid. It must be an ancient CPU */ +if (c->x86 ==4 ) +strcpy (c->x86_model_id,"486" ); +else if (c->x86 ==3 ) +strcpy (c->x86_model_id,"386" ); + } +#endif +} + +static const struct cpu_dev __cpuinitconst default_cpu = { + .c_init = default_init, + .c_vendor ="Unknown" , + .c_x86_vendor =X86_VENDOR_UNKNOWN , +}; + +static const struct cpu_dev *this_cpu__cpuinitdata = &default_cpu; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64
@@ -330,29 +353,6 @@static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM ] = {}; -static void __cpuinit default_init (struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_64 -display_cacheinfo (c); -#else -/* Not much we can do here... */ -/* Check if at least it has cpuid */ -if (c->cpuid_level ==-1 ) { -/* No cpuid. It must be an ancient CPU */ -if (c->x86 ==4 ) -strcpy (c->x86_model_id,"486" ); -else if (c->x86 ==3 ) -strcpy (c->x86_model_id,"386" ); - } -#endif -} - -static const struct cpu_dev __cpuinitconst default_cpu = { - .c_init = default_init, - .c_vendor ="Unknown" , - .c_x86_vendor =X86_VENDOR_UNKNOWN , -}; -static void __cpuinit get_model_name (struct cpuinfo_x86 *c) {unsigned int *v;
Signature · 1 line
Ondrej Zary
[tip:x86/urgent] x86: Fix oops in identify_cpu() on CPUs without CPUID
Commit-ID: e8055139d996e85722984968472868d6dccb1490 Gitweb: http://git.kernel.org/tip/e8055139d996e85722984968472868d6dccb1490 Author: Ondrej Zary <[email protected]> AuthorDate: Tue, 11 Aug 2009 20:00:11 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 12 Aug 2009 11:49:41 +0200
x86: Fix oops in identify_cpu() on CPUs without CPUID
Kernel is broken for x86 CPUs without CPUID since 2.6.28. It crashes with NULL pointer dereference in identify_cpu():
766 generic_identify(c);
767
768--> if (this_cpu->c_identify)
769 this_cpu->c_identify(c);
this_cpu is NULL. This is because it's only initialized in get_cpu_vendor() function, which is not called if the CPU has no CPUID instruction.
LKML-Reference: <[email protected]>
--- arch/x86/kernel/cpu/common.c | 48 +++++++++++++++++++++--------------------- 1 files changed, 24 insertions(+), 24 deletions(-)
arch/x86/kernel/cpu/common.c +24 -24
@@ -59,7 +59,30 @@ void __init setup_cpu_local_masks(void)alloc_bootmem_cpumask_var (&cpu_sibling_setup_mask); } -static const struct cpu_dev *this_cpu__cpuinitdata ; +static void __cpuinit default_init (struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_64 +display_cacheinfo (c); +#else +/* Not much we can do here... */ +/* Check if at least it has cpuid */ +if (c->cpuid_level ==-1 ) { +/* No cpuid. It must be an ancient CPU */ +if (c->x86 ==4 ) +strcpy (c->x86_model_id,"486" ); +else if (c->x86 ==3 ) +strcpy (c->x86_model_id,"386" ); + } +#endif +} + +static const struct cpu_dev __cpuinitconst default_cpu = { + .c_init = default_init, + .c_vendor ="Unknown" , + .c_x86_vendor =X86_VENDOR_UNKNOWN , +}; + +static const struct cpu_dev *this_cpu__cpuinitdata = &default_cpu; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64
@@ -332,29 +355,6 @@ void switch_to_new_gdt(int cpu)static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM ] = {}; -static void __cpuinit default_init (struct cpuinfo_x86 *c) -{ -#ifdef CONFIG_X86_64 -display_cacheinfo (c); -#else -/* Not much we can do here... */ -/* Check if at least it has cpuid */ -if (c->cpuid_level ==-1 ) { -/* No cpuid. It must be an ancient CPU */ -if (c->x86 ==4 ) -strcpy (c->x86_model_id,"486" ); -else if (c->x86 ==3 ) -strcpy (c->x86_model_id,"386" ); - } -#endif -} - -static const struct cpu_dev __cpuinitconst default_cpu = { - .c_init = default_init, - .c_vendor ="Unknown" , - .c_x86_vendor =X86_VENDOR_UNKNOWN , -}; -static void __cpuinit get_model_name (struct cpuinfo_x86 *c) {unsigned int *v;