Commit 2d4712b7a615e5db3eb9a427f1722eec79681b4b
Exists in
master
and in
20 other branches
Merge branch 'parisc-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc fixes from Helge Deller: "This patchset includes a bugfix to prevent a kernel crash when memory in page zero is accessed by the kernel itself, e.g. via probe_kernel_read(). Furthermore we now export flush_cache_page() which is needed (indirectly) by the lustre filesystem. The other patches remove unused functions and optimizes the page fault handler to only evaluate variables if needed, which again protects against possible kernel crashes" * 'parisc-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: let probe_kernel_read() capture access to page zero parisc: optimize variable initialization in do_page_fault parisc: fix interruption handler to respect pagefault_disable() parisc: mark parisc_terminate() noreturn and cold. parisc: remove unused syscall_ipi() function. parisc: kill SMP single function call interrupt parisc: Export flush_cache_page() (needed by lustre)
Showing 6 changed files Side-by-side Diff
arch/parisc/include/asm/traps.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/smp.c
... | ... | @@ -72,7 +72,6 @@ |
72 | 72 | IPI_NOP=0, |
73 | 73 | IPI_RESCHEDULE=1, |
74 | 74 | IPI_CALL_FUNC, |
75 | - IPI_CALL_FUNC_SINGLE, | |
76 | 75 | IPI_CPU_START, |
77 | 76 | IPI_CPU_STOP, |
78 | 77 | IPI_CPU_TEST |
... | ... | @@ -164,11 +163,6 @@ |
164 | 163 | generic_smp_call_function_interrupt(); |
165 | 164 | break; |
166 | 165 | |
167 | - case IPI_CALL_FUNC_SINGLE: | |
168 | - smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC_SINGLE\n", this_cpu); | |
169 | - generic_smp_call_function_single_interrupt(); | |
170 | - break; | |
171 | - | |
172 | 166 | case IPI_CPU_START: |
173 | 167 | smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu); |
174 | 168 | break; |
... | ... | @@ -260,7 +254,7 @@ |
260 | 254 | |
261 | 255 | void arch_send_call_function_single_ipi(int cpu) |
262 | 256 | { |
263 | - send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE); | |
257 | + send_IPI_single(cpu, IPI_CALL_FUNC); | |
264 | 258 | } |
265 | 259 | |
266 | 260 | /* |
arch/parisc/kernel/traps.c
... | ... | @@ -291,11 +291,6 @@ |
291 | 291 | do_exit(SIGSEGV); |
292 | 292 | } |
293 | 293 | |
294 | -int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) | |
295 | -{ | |
296 | - return syscall(regs); | |
297 | -} | |
298 | - | |
299 | 294 | /* gdb uses break 4,8 */ |
300 | 295 | #define GDB_BREAK_INSN 0x10004 |
301 | 296 | static void handle_gdb_break(struct pt_regs *regs, int wot) |
302 | 297 | |
303 | 298 | |
... | ... | @@ -805,14 +800,14 @@ |
805 | 800 | else { |
806 | 801 | |
807 | 802 | /* |
808 | - * The kernel should never fault on its own address space. | |
803 | + * The kernel should never fault on its own address space, | |
804 | + * unless pagefault_disable() was called before. | |
809 | 805 | */ |
810 | 806 | |
811 | - if (fault_space == 0) | |
807 | + if (fault_space == 0 && !in_atomic()) | |
812 | 808 | { |
813 | 809 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); |
814 | 810 | parisc_terminate("Kernel Fault", regs, code, fault_address); |
815 | - | |
816 | 811 | } |
817 | 812 | } |
818 | 813 |
arch/parisc/lib/memcpy.c
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 | #ifdef __KERNEL__ |
57 | 57 | #include <linux/module.h> |
58 | 58 | #include <linux/compiler.h> |
59 | -#include <asm/uaccess.h> | |
59 | +#include <linux/uaccess.h> | |
60 | 60 | #define s_space "%%sr1" |
61 | 61 | #define d_space "%%sr2" |
62 | 62 | #else |
... | ... | @@ -524,5 +524,18 @@ |
524 | 524 | EXPORT_SYMBOL(copy_from_user); |
525 | 525 | EXPORT_SYMBOL(copy_in_user); |
526 | 526 | EXPORT_SYMBOL(memcpy); |
527 | + | |
528 | +long probe_kernel_read(void *dst, const void *src, size_t size) | |
529 | +{ | |
530 | + unsigned long addr = (unsigned long)src; | |
531 | + | |
532 | + if (size < 0 || addr < PAGE_SIZE) | |
533 | + return -EFAULT; | |
534 | + | |
535 | + /* check for I/O space F_EXTEND(0xfff00000) access as well? */ | |
536 | + | |
537 | + return __probe_kernel_read(dst, src, size); | |
538 | +} | |
539 | + | |
527 | 540 | #endif |
arch/parisc/mm/fault.c
... | ... | @@ -171,20 +171,25 @@ |
171 | 171 | unsigned long address) |
172 | 172 | { |
173 | 173 | struct vm_area_struct *vma, *prev_vma; |
174 | - struct task_struct *tsk = current; | |
175 | - struct mm_struct *mm = tsk->mm; | |
174 | + struct task_struct *tsk; | |
175 | + struct mm_struct *mm; | |
176 | 176 | unsigned long acc_type; |
177 | 177 | int fault; |
178 | - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | |
178 | + unsigned int flags; | |
179 | 179 | |
180 | - if (in_atomic() || !mm) | |
180 | + if (in_atomic()) | |
181 | 181 | goto no_context; |
182 | 182 | |
183 | + tsk = current; | |
184 | + mm = tsk->mm; | |
185 | + if (!mm) | |
186 | + goto no_context; | |
187 | + | |
188 | + flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | |
183 | 189 | if (user_mode(regs)) |
184 | 190 | flags |= FAULT_FLAG_USER; |
185 | 191 | |
186 | 192 | acc_type = parisc_acctyp(code, regs->iir); |
187 | - | |
188 | 193 | if (acc_type & VM_WRITE) |
189 | 194 | flags |= FAULT_FLAG_WRITE; |
190 | 195 | retry: |