diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-20 12:53:01 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-20 16:53:40 +0100 |
commit | d374bf14a5ff18133bd6a6cc00f189949f7ba8fb (patch) | |
tree | d04f40327d5575f5f848695a97099527475a2634 | |
parent | bf4569922b97824f33e5d08d0bbe4b34fe43e4cd (diff) | |
download | lwn-d374bf14a5ff18133bd6a6cc00f189949f7ba8fb.tar.gz lwn-d374bf14a5ff18133bd6a6cc00f189949f7ba8fb.zip |
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 <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mm/fault.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index b8b3bb4423cf..b7ce07d416cd 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 |