diff options
-rw-r--r-- | arch/arc/mm/fault.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index a3a292c58e50..8c7c81ce7f6a 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c | |||
@@ -64,9 +64,9 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) | |||
64 | struct task_struct *tsk = current; | 64 | struct task_struct *tsk = current; |
65 | struct mm_struct *mm = tsk->mm; | 65 | struct mm_struct *mm = tsk->mm; |
66 | int si_code = SEGV_MAPERR; | 66 | int si_code = SEGV_MAPERR; |
67 | unsigned int write = 0, exec = 0, mask; | ||
67 | vm_fault_t fault; | 68 | vm_fault_t fault; |
68 | int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ | 69 | unsigned int flags; |
69 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | ||
70 | 70 | ||
71 | /* | 71 | /* |
72 | * NOTE! We MUST NOT take any locks for this case. We may | 72 | * NOTE! We MUST NOT take any locks for this case. We may |
@@ -88,8 +88,18 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) | |||
88 | if (faulthandler_disabled() || !mm) | 88 | if (faulthandler_disabled() || !mm) |
89 | goto no_context; | 89 | goto no_context; |
90 | 90 | ||
91 | if (regs->ecr_cause & ECR_C_PROTV_STORE) /* ST/EX */ | ||
92 | write = 1; | ||
93 | else if ((regs->ecr_vec == ECR_V_PROTV) && | ||
94 | (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) | ||
95 | exec = 1; | ||
96 | |||
97 | flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | ||
91 | if (user_mode(regs)) | 98 | if (user_mode(regs)) |
92 | flags |= FAULT_FLAG_USER; | 99 | flags |= FAULT_FLAG_USER; |
100 | if (write) | ||
101 | flags |= FAULT_FLAG_WRITE; | ||
102 | |||
93 | retry: | 103 | retry: |
94 | down_read(&mm->mmap_sem); | 104 | down_read(&mm->mmap_sem); |
95 | 105 | ||
@@ -102,24 +112,17 @@ retry: | |||
102 | } | 112 | } |
103 | 113 | ||
104 | /* | 114 | /* |
105 | * Ok, we have a good vm_area for this memory access, so | 115 | * vm_area is good, now check permissions for this memory access |
106 | * we can handle it.. | ||
107 | */ | 116 | */ |
108 | si_code = SEGV_ACCERR; | 117 | mask = VM_READ; |
109 | 118 | if (write) | |
110 | /* Handle protection violation, execute on heap or stack */ | 119 | mask = VM_WRITE; |
111 | 120 | if (exec) | |
112 | if ((regs->ecr_vec == ECR_V_PROTV) && | 121 | mask = VM_EXEC; |
113 | (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) | 122 | |
123 | if (!(vma->vm_flags & mask)) { | ||
124 | si_code = SEGV_ACCERR; | ||
114 | goto bad_area; | 125 | goto bad_area; |
115 | |||
116 | if (write) { | ||
117 | if (!(vma->vm_flags & VM_WRITE)) | ||
118 | goto bad_area; | ||
119 | flags |= FAULT_FLAG_WRITE; | ||
120 | } else { | ||
121 | if (!(vma->vm_flags & (VM_READ | VM_EXEC))) | ||
122 | goto bad_area; | ||
123 | } | 126 | } |
124 | 127 | ||
125 | /* | 128 | /* |