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)
This commit is contained in:
commit
2d4712b7a6
6 changed files with 30 additions and 22 deletions
|
@ -6,7 +6,7 @@ struct pt_regs;
|
|||
|
||||
/* traps.c */
|
||||
void parisc_terminate(char *msg, struct pt_regs *regs,
|
||||
int code, unsigned long offset);
|
||||
int code, unsigned long offset) __noreturn __cold;
|
||||
|
||||
/* mm/fault.c */
|
||||
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
|
|||
__flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flush_cache_page);
|
||||
|
||||
#ifdef CONFIG_PARISC_TMPALIAS
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ enum ipi_message_type {
|
|||
IPI_NOP=0,
|
||||
IPI_RESCHEDULE=1,
|
||||
IPI_CALL_FUNC,
|
||||
IPI_CALL_FUNC_SINGLE,
|
||||
IPI_CPU_START,
|
||||
IPI_CPU_STOP,
|
||||
IPI_CPU_TEST
|
||||
|
@ -164,11 +163,6 @@ ipi_interrupt(int irq, void *dev_id)
|
|||
generic_smp_call_function_interrupt();
|
||||
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:
|
||||
smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu);
|
||||
break;
|
||||
|
@ -260,7 +254,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
|||
|
||||
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)
|
|||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
|
||||
{
|
||||
return syscall(regs);
|
||||
}
|
||||
|
||||
/* gdb uses break 4,8 */
|
||||
#define GDB_BREAK_INSN 0x10004
|
||||
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)
|
|||
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);
|
||||
parisc_terminate("Kernel Fault", regs, code, fault_address);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#ifdef __KERNEL__
|
||||
#include <linux/module.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#define s_space "%%sr1"
|
||||
#define d_space "%%sr2"
|
||||
#else
|
||||
|
@ -524,4 +524,17 @@ EXPORT_SYMBOL(copy_to_user);
|
|||
EXPORT_SYMBOL(copy_from_user);
|
||||
EXPORT_SYMBOL(copy_in_user);
|
||||
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
|
||||
|
|
|
@ -171,20 +171,25 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|||
unsigned long address)
|
||||
{
|
||||
struct vm_area_struct *vma, *prev_vma;
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
unsigned long acc_type;
|
||||
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;
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
if (!mm)
|
||||
goto no_context;
|
||||
|
||||
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
acc_type = parisc_acctyp(code, regs->iir);
|
||||
|
||||
if (acc_type & VM_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
retry:
|
||||
|
|
Loading…
Reference in a new issue