Commit 2d4712b7 authored by Linus Torvalds's avatar Linus Torvalds

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)
parents 75c53188 db080f9c
...@@ -6,7 +6,7 @@ struct pt_regs; ...@@ -6,7 +6,7 @@ struct pt_regs;
/* traps.c */ /* traps.c */
void parisc_terminate(char *msg, struct pt_regs *regs, void parisc_terminate(char *msg, struct pt_regs *regs,
int code, unsigned long offset); int code, unsigned long offset) __noreturn __cold;
/* mm/fault.c */ /* mm/fault.c */
void do_page_fault(struct pt_regs *regs, unsigned long code, void do_page_fault(struct pt_regs *regs, unsigned long code,
......
...@@ -602,6 +602,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long ...@@ -602,6 +602,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
__flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
} }
} }
EXPORT_SYMBOL_GPL(flush_cache_page);
#ifdef CONFIG_PARISC_TMPALIAS #ifdef CONFIG_PARISC_TMPALIAS
......
...@@ -72,7 +72,6 @@ enum ipi_message_type { ...@@ -72,7 +72,6 @@ enum ipi_message_type {
IPI_NOP=0, IPI_NOP=0,
IPI_RESCHEDULE=1, IPI_RESCHEDULE=1,
IPI_CALL_FUNC, IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE,
IPI_CPU_START, IPI_CPU_START,
IPI_CPU_STOP, IPI_CPU_STOP,
IPI_CPU_TEST IPI_CPU_TEST
...@@ -164,11 +163,6 @@ ipi_interrupt(int irq, void *dev_id) ...@@ -164,11 +163,6 @@ ipi_interrupt(int irq, void *dev_id)
generic_smp_call_function_interrupt(); generic_smp_call_function_interrupt();
break; break;
case IPI_CALL_FUNC_SINGLE:
smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC_SINGLE\n", this_cpu);
generic_smp_call_function_single_interrupt();
break;
case IPI_CPU_START: case IPI_CPU_START:
smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu); smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu);
break; break;
...@@ -260,7 +254,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) ...@@ -260,7 +254,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
void arch_send_call_function_single_ipi(int cpu) void arch_send_call_function_single_ipi(int cpu)
{ {
send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE); send_IPI_single(cpu, IPI_CALL_FUNC);
} }
/* /*
......
...@@ -291,11 +291,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) ...@@ -291,11 +291,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
{
return syscall(regs);
}
/* gdb uses break 4,8 */ /* gdb uses break 4,8 */
#define GDB_BREAK_INSN 0x10004 #define GDB_BREAK_INSN 0x10004
static void handle_gdb_break(struct pt_regs *regs, int wot) static void handle_gdb_break(struct pt_regs *regs, int wot)
...@@ -805,14 +800,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs) ...@@ -805,14 +800,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
else { else {
/* /*
* The kernel should never fault on its own address space. * The kernel should never fault on its own address space,
* unless pagefault_disable() was called before.
*/ */
if (fault_space == 0) if (fault_space == 0 && !in_atomic())
{ {
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
parisc_terminate("Kernel Fault", regs, code, fault_address); parisc_terminate("Kernel Fault", regs, code, fault_address);
} }
} }
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/module.h> #include <linux/module.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#define s_space "%%sr1" #define s_space "%%sr1"
#define d_space "%%sr2" #define d_space "%%sr2"
#else #else
...@@ -524,4 +524,17 @@ EXPORT_SYMBOL(copy_to_user); ...@@ -524,4 +524,17 @@ EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(copy_from_user); EXPORT_SYMBOL(copy_from_user);
EXPORT_SYMBOL(copy_in_user); EXPORT_SYMBOL(copy_in_user);
EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memcpy);
long probe_kernel_read(void *dst, const void *src, size_t size)
{
unsigned long addr = (unsigned long)src;
if (size < 0 || addr < PAGE_SIZE)
return -EFAULT;
/* check for I/O space F_EXTEND(0xfff00000) access as well? */
return __probe_kernel_read(dst, src, size);
}
#endif #endif
...@@ -171,20 +171,25 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, ...@@ -171,20 +171,25 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
unsigned long address) unsigned long address)
{ {
struct vm_area_struct *vma, *prev_vma; struct vm_area_struct *vma, *prev_vma;
struct task_struct *tsk = current; struct task_struct *tsk;
struct mm_struct *mm = tsk->mm; struct mm_struct *mm;
unsigned long acc_type; unsigned long acc_type;
int fault; int fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags;
if (in_atomic() || !mm) if (in_atomic())
goto no_context; goto no_context;
tsk = current;
mm = tsk->mm;
if (!mm)
goto no_context;
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
if (user_mode(regs)) if (user_mode(regs))
flags |= FAULT_FLAG_USER; flags |= FAULT_FLAG_USER;
acc_type = parisc_acctyp(code, regs->iir); acc_type = parisc_acctyp(code, regs->iir);
if (acc_type & VM_WRITE) if (acc_type & VM_WRITE)
flags |= FAULT_FLAG_WRITE; flags |= FAULT_FLAG_WRITE;
retry: retry:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment