From d374bf14a5ff18133bd6a6cc00f189949f7ba8fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 20 Sep 2009 12:53:01 +0100 Subject: ARM: Separate out access error checking Since we get notified separately about prefetch aborts, which may be permission faults, we need to check for appropriate access permissions when handling a fault. This patch prepares us for doing this by separating out the access error checking. Signed-off-by: Russell King --- arch/arm/mm/fault.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'arch/arm/mm/fault.c') diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index b8b3bb4423c..b7ce07d416c 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -194,18 +194,33 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs) #define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADACCESS 0x020000 -static int +/* + * Check that the permissions on the VMA allow for the fault which occurred. + * If we encountered a write fault, we must have write permission, otherwise + * we allow any permission. + */ +static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma) +{ + unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; + + if (fsr & FSR_WRITE) + mask = VM_WRITE; + + return vma->vm_flags & mask ? false : true; +} + +static int __kprobes __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct task_struct *tsk) { struct vm_area_struct *vma; - int fault, mask; + int fault; vma = find_vma(mm, addr); fault = VM_FAULT_BADMAP; - if (!vma) + if (unlikely(!vma)) goto out; - if (vma->vm_start > addr) + if (unlikely(vma->vm_start > addr)) goto check_stack; /* @@ -213,14 +228,10 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, * memory access, so we can handle it. */ good_area: - if (fsr & FSR_WRITE) - mask = VM_WRITE; - else - mask = VM_READ|VM_EXEC|VM_WRITE; - - fault = VM_FAULT_BADACCESS; - if (!(vma->vm_flags & mask)) + if (access_error(fsr, vma)) { + fault = VM_FAULT_BADACCESS; goto out; + } /* * If for any reason at all we couldn't handle the fault, make -- cgit v1.2.3-70-g09d2