diff options
Diffstat (limited to 'arch/arm64/mm/fault.c')
-rw-r--r-- | arch/arm64/mm/fault.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index c8beaa0da7df..05d2bd776c69 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
@@ -153,6 +153,11 @@ int ptep_set_access_flags(struct vm_area_struct *vma, | |||
153 | } | 153 | } |
154 | #endif | 154 | #endif |
155 | 155 | ||
156 | static bool is_el1_instruction_abort(unsigned int esr) | ||
157 | { | ||
158 | return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR; | ||
159 | } | ||
160 | |||
156 | /* | 161 | /* |
157 | * The kernel tried to access some page that wasn't present. | 162 | * The kernel tried to access some page that wasn't present. |
158 | */ | 163 | */ |
@@ -161,8 +166,9 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, | |||
161 | { | 166 | { |
162 | /* | 167 | /* |
163 | * Are we prepared to handle this kernel fault? | 168 | * Are we prepared to handle this kernel fault? |
169 | * We are almost certainly not prepared to handle instruction faults. | ||
164 | */ | 170 | */ |
165 | if (fixup_exception(regs)) | 171 | if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) |
166 | return; | 172 | return; |
167 | 173 | ||
168 | /* | 174 | /* |
@@ -267,7 +273,8 @@ static inline bool is_permission_fault(unsigned int esr) | |||
267 | unsigned int ec = ESR_ELx_EC(esr); | 273 | unsigned int ec = ESR_ELx_EC(esr); |
268 | unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; | 274 | unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; |
269 | 275 | ||
270 | return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM); | 276 | return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) || |
277 | (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM); | ||
271 | } | 278 | } |
272 | 279 | ||
273 | static bool is_el0_instruction_abort(unsigned int esr) | 280 | static bool is_el0_instruction_abort(unsigned int esr) |
@@ -312,6 +319,9 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, | |||
312 | if (regs->orig_addr_limit == KERNEL_DS) | 319 | if (regs->orig_addr_limit == KERNEL_DS) |
313 | die("Accessing user space memory with fs=KERNEL_DS", regs, esr); | 320 | die("Accessing user space memory with fs=KERNEL_DS", regs, esr); |
314 | 321 | ||
322 | if (is_el1_instruction_abort(esr)) | ||
323 | die("Attempting to execute userspace memory", regs, esr); | ||
324 | |||
315 | if (!search_exception_tables(regs->pc)) | 325 | if (!search_exception_tables(regs->pc)) |
316 | die("Accessing user space memory outside uaccess.h routines", regs, esr); | 326 | die("Accessing user space memory outside uaccess.h routines", regs, esr); |
317 | } | 327 | } |