diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 27 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mkcapflags.pl | 25 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/scattered.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/kgdb.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/reboot.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/vsyscall_64.c | 39 |
6 files changed, 83 insertions, 26 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8afb69319815..b2297e58c6ed 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -422,12 +422,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, | |||
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | if (intsrc->source_irq == 0 && intsrc->global_irq == 2) { | 425 | if (intsrc->source_irq == 0) { |
426 | if (acpi_skip_timer_override) { | 426 | if (acpi_skip_timer_override) { |
427 | printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); | 427 | printk(PREFIX "BIOS IRQ0 override ignored.\n"); |
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { | 430 | |
431 | if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity | ||
432 | && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { | ||
431 | intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK; | 433 | intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK; |
432 | printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n"); | 434 | printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n"); |
433 | } | 435 | } |
@@ -1334,17 +1336,12 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d) | |||
1334 | } | 1336 | } |
1335 | 1337 | ||
1336 | /* | 1338 | /* |
1337 | * Force ignoring BIOS IRQ0 pin2 override | 1339 | * Force ignoring BIOS IRQ0 override |
1338 | */ | 1340 | */ |
1339 | static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) | 1341 | static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) |
1340 | { | 1342 | { |
1341 | /* | ||
1342 | * The ati_ixp4x0_rev() early PCI quirk should have set | ||
1343 | * the acpi_skip_timer_override flag already: | ||
1344 | */ | ||
1345 | if (!acpi_skip_timer_override) { | 1343 | if (!acpi_skip_timer_override) { |
1346 | WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); | 1344 | pr_notice("%s detected: Ignoring BIOS IRQ0 override\n", |
1347 | pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", | ||
1348 | d->ident); | 1345 | d->ident); |
1349 | acpi_skip_timer_override = 1; | 1346 | acpi_skip_timer_override = 1; |
1350 | } | 1347 | } |
@@ -1438,7 +1435,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { | |||
1438 | * is enabled. This input is incorrectly designated the | 1435 | * is enabled. This input is incorrectly designated the |
1439 | * ISA IRQ 0 via an interrupt source override even though | 1436 | * ISA IRQ 0 via an interrupt source override even though |
1440 | * it is wired to the output of the master 8259A and INTIN0 | 1437 | * it is wired to the output of the master 8259A and INTIN0 |
1441 | * is not connected at all. Force ignoring BIOS IRQ0 pin2 | 1438 | * is not connected at all. Force ignoring BIOS IRQ0 |
1442 | * override in that cases. | 1439 | * override in that cases. |
1443 | */ | 1440 | */ |
1444 | { | 1441 | { |
@@ -1473,6 +1470,14 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { | |||
1473 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), | 1470 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), |
1474 | }, | 1471 | }, |
1475 | }, | 1472 | }, |
1473 | { | ||
1474 | .callback = dmi_ignore_irq0_timer_override, | ||
1475 | .ident = "FUJITSU SIEMENS", | ||
1476 | .matches = { | ||
1477 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
1478 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), | ||
1479 | }, | ||
1480 | }, | ||
1476 | {} | 1481 | {} |
1477 | }; | 1482 | }; |
1478 | 1483 | ||
diff --git a/arch/x86/kernel/cpu/mkcapflags.pl b/arch/x86/kernel/cpu/mkcapflags.pl index dfea390e1608..c7b3fe2d72e0 100644 --- a/arch/x86/kernel/cpu/mkcapflags.pl +++ b/arch/x86/kernel/cpu/mkcapflags.pl | |||
@@ -1,4 +1,4 @@ | |||
1 | #!/usr/bin/perl | 1 | #!/usr/bin/perl -w |
2 | # | 2 | # |
3 | # Generate the x86_cap_flags[] array from include/asm-x86/cpufeature.h | 3 | # Generate the x86_cap_flags[] array from include/asm-x86/cpufeature.h |
4 | # | 4 | # |
@@ -11,22 +11,35 @@ open(OUT, "> $out\0") or die "$0: cannot create: $out: $!\n"; | |||
11 | print OUT "#include <asm/cpufeature.h>\n\n"; | 11 | print OUT "#include <asm/cpufeature.h>\n\n"; |
12 | print OUT "const char * const x86_cap_flags[NCAPINTS*32] = {\n"; | 12 | print OUT "const char * const x86_cap_flags[NCAPINTS*32] = {\n"; |
13 | 13 | ||
14 | %features = (); | ||
15 | $err = 0; | ||
16 | |||
14 | while (defined($line = <IN>)) { | 17 | while (defined($line = <IN>)) { |
15 | if ($line =~ /^\s*\#\s*define\s+(X86_FEATURE_(\S+))\s+(.*)$/) { | 18 | if ($line =~ /^\s*\#\s*define\s+(X86_FEATURE_(\S+))\s+(.*)$/) { |
16 | $macro = $1; | 19 | $macro = $1; |
17 | $feature = $2; | 20 | $feature = "\L$2"; |
18 | $tail = $3; | 21 | $tail = $3; |
19 | if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) { | 22 | if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) { |
20 | $feature = $1; | 23 | $feature = "\L$1"; |
21 | } | 24 | } |
22 | 25 | ||
23 | if ($feature ne '') { | 26 | next if ($feature eq ''); |
24 | printf OUT "\t%-32s = \"%s\",\n", | 27 | |
25 | "[$macro]", "\L$feature"; | 28 | if ($features{$feature}++) { |
29 | print STDERR "$in: duplicate feature name: $feature\n"; | ||
30 | $err++; | ||
26 | } | 31 | } |
32 | printf OUT "\t%-32s = \"%s\",\n", "[$macro]", $feature; | ||
27 | } | 33 | } |
28 | } | 34 | } |
29 | print OUT "};\n"; | 35 | print OUT "};\n"; |
30 | 36 | ||
31 | close(IN); | 37 | close(IN); |
32 | close(OUT); | 38 | close(OUT); |
39 | |||
40 | if ($err) { | ||
41 | unlink($out); | ||
42 | exit(1); | ||
43 | } | ||
44 | |||
45 | exit(0); | ||
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index addf9e82a7f2..ee8e9abc859f 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c | |||
@@ -31,7 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
31 | const struct cpuid_bit *cb; | 31 | const struct cpuid_bit *cb; |
32 | 32 | ||
33 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { | 33 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { |
34 | { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, | 34 | { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 }, |
35 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, | 35 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, |
36 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, | 36 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, |
37 | { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, | 37 | { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, |
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 8bfb6146f753..3f61904365cf 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -444,12 +444,12 @@ void kgdb_roundup_cpus(unsigned long flags) | |||
444 | 444 | ||
445 | /** | 445 | /** |
446 | * kgdb_arch_handle_exception - Handle architecture specific GDB packets. | 446 | * kgdb_arch_handle_exception - Handle architecture specific GDB packets. |
447 | * @vector: The error vector of the exception that happened. | 447 | * @e_vector: The error vector of the exception that happened. |
448 | * @signo: The signal number of the exception that happened. | 448 | * @signo: The signal number of the exception that happened. |
449 | * @err_code: The error code of the exception that happened. | 449 | * @err_code: The error code of the exception that happened. |
450 | * @remcom_in_buffer: The buffer of the packet we have read. | 450 | * @remcomInBuffer: The buffer of the packet we have read. |
451 | * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into. | 451 | * @remcomOutBuffer: The buffer of %BUFMAX bytes to write a packet into. |
452 | * @regs: The &struct pt_regs of the current process. | 452 | * @linux_regs: The &struct pt_regs of the current process. |
453 | * | 453 | * |
454 | * This function MUST handle the 'c' and 's' command packets, | 454 | * This function MUST handle the 'c' and 's' command packets, |
455 | * as well packets to set / remove a hardware breakpoint, if used. | 455 | * as well packets to set / remove a hardware breakpoint, if used. |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 25b48edb847c..5de92f1abd76 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -451,6 +451,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { | |||
451 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), | 451 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), |
452 | }, | 452 | }, |
453 | }, | 453 | }, |
454 | { /* Handle problems with rebooting on the Precision M6600. */ | ||
455 | .callback = set_pci_reboot, | ||
456 | .ident = "Dell OptiPlex 990", | ||
457 | .matches = { | ||
458 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
459 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), | ||
460 | }, | ||
461 | }, | ||
454 | { } | 462 | { } |
455 | }; | 463 | }; |
456 | 464 | ||
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 7515cf0e1805..5db36caf4289 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c | |||
@@ -139,6 +139,19 @@ static int addr_to_vsyscall_nr(unsigned long addr) | |||
139 | return nr; | 139 | return nr; |
140 | } | 140 | } |
141 | 141 | ||
142 | #ifdef CONFIG_SECCOMP | ||
143 | static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr) | ||
144 | { | ||
145 | if (!seccomp_mode(&tsk->seccomp)) | ||
146 | return 0; | ||
147 | task_pt_regs(tsk)->orig_ax = syscall_nr; | ||
148 | task_pt_regs(tsk)->ax = syscall_nr; | ||
149 | return __secure_computing(syscall_nr); | ||
150 | } | ||
151 | #else | ||
152 | #define vsyscall_seccomp(_tsk, _nr) 0 | ||
153 | #endif | ||
154 | |||
142 | static bool write_ok_or_segv(unsigned long ptr, size_t size) | 155 | static bool write_ok_or_segv(unsigned long ptr, size_t size) |
143 | { | 156 | { |
144 | /* | 157 | /* |
@@ -174,6 +187,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
174 | int vsyscall_nr; | 187 | int vsyscall_nr; |
175 | int prev_sig_on_uaccess_error; | 188 | int prev_sig_on_uaccess_error; |
176 | long ret; | 189 | long ret; |
190 | int skip; | ||
177 | 191 | ||
178 | /* | 192 | /* |
179 | * No point in checking CS -- the only way to get here is a user mode | 193 | * No point in checking CS -- the only way to get here is a user mode |
@@ -205,9 +219,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
205 | } | 219 | } |
206 | 220 | ||
207 | tsk = current; | 221 | tsk = current; |
208 | if (seccomp_mode(&tsk->seccomp)) | ||
209 | do_exit(SIGKILL); | ||
210 | |||
211 | /* | 222 | /* |
212 | * With a real vsyscall, page faults cause SIGSEGV. We want to | 223 | * With a real vsyscall, page faults cause SIGSEGV. We want to |
213 | * preserve that behavior to make writing exploits harder. | 224 | * preserve that behavior to make writing exploits harder. |
@@ -222,8 +233,13 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
222 | * address 0". | 233 | * address 0". |
223 | */ | 234 | */ |
224 | ret = -EFAULT; | 235 | ret = -EFAULT; |
236 | skip = 0; | ||
225 | switch (vsyscall_nr) { | 237 | switch (vsyscall_nr) { |
226 | case 0: | 238 | case 0: |
239 | skip = vsyscall_seccomp(tsk, __NR_gettimeofday); | ||
240 | if (skip) | ||
241 | break; | ||
242 | |||
227 | if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || | 243 | if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || |
228 | !write_ok_or_segv(regs->si, sizeof(struct timezone))) | 244 | !write_ok_or_segv(regs->si, sizeof(struct timezone))) |
229 | break; | 245 | break; |
@@ -234,6 +250,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
234 | break; | 250 | break; |
235 | 251 | ||
236 | case 1: | 252 | case 1: |
253 | skip = vsyscall_seccomp(tsk, __NR_time); | ||
254 | if (skip) | ||
255 | break; | ||
256 | |||
237 | if (!write_ok_or_segv(regs->di, sizeof(time_t))) | 257 | if (!write_ok_or_segv(regs->di, sizeof(time_t))) |
238 | break; | 258 | break; |
239 | 259 | ||
@@ -241,6 +261,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
241 | break; | 261 | break; |
242 | 262 | ||
243 | case 2: | 263 | case 2: |
264 | skip = vsyscall_seccomp(tsk, __NR_getcpu); | ||
265 | if (skip) | ||
266 | break; | ||
267 | |||
244 | if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || | 268 | if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || |
245 | !write_ok_or_segv(regs->si, sizeof(unsigned))) | 269 | !write_ok_or_segv(regs->si, sizeof(unsigned))) |
246 | break; | 270 | break; |
@@ -253,6 +277,12 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
253 | 277 | ||
254 | current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; | 278 | current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; |
255 | 279 | ||
280 | if (skip) { | ||
281 | if ((long)regs->ax <= 0L) /* seccomp errno emulation */ | ||
282 | goto do_ret; | ||
283 | goto done; /* seccomp trace/trap */ | ||
284 | } | ||
285 | |||
256 | if (ret == -EFAULT) { | 286 | if (ret == -EFAULT) { |
257 | /* Bad news -- userspace fed a bad pointer to a vsyscall. */ | 287 | /* Bad news -- userspace fed a bad pointer to a vsyscall. */ |
258 | warn_bad_vsyscall(KERN_INFO, regs, | 288 | warn_bad_vsyscall(KERN_INFO, regs, |
@@ -271,10 +301,11 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
271 | 301 | ||
272 | regs->ax = ret; | 302 | regs->ax = ret; |
273 | 303 | ||
304 | do_ret: | ||
274 | /* Emulate a ret instruction. */ | 305 | /* Emulate a ret instruction. */ |
275 | regs->ip = caller; | 306 | regs->ip = caller; |
276 | regs->sp += 8; | 307 | regs->sp += 8; |
277 | 308 | done: | |
278 | return true; | 309 | return true; |
279 | 310 | ||
280 | sigsegv: | 311 | sigsegv: |