diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/mm/fault.c | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 0dcfcfb5b5be..5a9e9a77dc16 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -286,7 +286,7 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, | |||
286 | * 11 Page translation -> Not present (nullification) | 286 | * 11 Page translation -> Not present (nullification) |
287 | * 3b Region third trans. -> Not present (nullification) | 287 | * 3b Region third trans. -> Not present (nullification) |
288 | */ | 288 | */ |
289 | static inline int do_exception(struct pt_regs *regs, int write, | 289 | static inline int do_exception(struct pt_regs *regs, int access, |
290 | unsigned long trans_exc_code) | 290 | unsigned long trans_exc_code) |
291 | { | 291 | { |
292 | struct task_struct *tsk; | 292 | struct task_struct *tsk; |
@@ -337,19 +337,8 @@ static inline int do_exception(struct pt_regs *regs, int write, | |||
337 | * we can handle it.. | 337 | * we can handle it.. |
338 | */ | 338 | */ |
339 | fault = VM_FAULT_BADACCESS; | 339 | fault = VM_FAULT_BADACCESS; |
340 | #ifdef CONFIG_S390_EXEC_PROTECT | 340 | if (unlikely(!(vma->vm_flags & access))) |
341 | if (unlikely((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && | ||
342 | (trans_exc_code & 3) == 0 && !(vma->vm_flags & VM_EXEC))) | ||
343 | goto out_up; | 341 | goto out_up; |
344 | #endif | ||
345 | if (!write) { | ||
346 | /* page not present, check vm flags */ | ||
347 | if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) | ||
348 | goto out_up; | ||
349 | } else { | ||
350 | if (!(vma->vm_flags & VM_WRITE)) | ||
351 | goto out_up; | ||
352 | } | ||
353 | 342 | ||
354 | if (is_vm_hugetlb_page(vma)) | 343 | if (is_vm_hugetlb_page(vma)) |
355 | address &= HPAGE_MASK; | 344 | address &= HPAGE_MASK; |
@@ -358,7 +347,8 @@ static inline int do_exception(struct pt_regs *regs, int write, | |||
358 | * make sure we exit gracefully rather than endlessly redo | 347 | * make sure we exit gracefully rather than endlessly redo |
359 | * the fault. | 348 | * the fault. |
360 | */ | 349 | */ |
361 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); | 350 | fault = handle_mm_fault(mm, vma, address, |
351 | (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0); | ||
362 | if (unlikely(fault & VM_FAULT_ERROR)) | 352 | if (unlikely(fault & VM_FAULT_ERROR)) |
363 | goto out_up; | 353 | goto out_up; |
364 | 354 | ||
@@ -399,7 +389,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code) | |||
399 | do_low_address(regs, int_code, trans_exc_code); | 389 | do_low_address(regs, int_code, trans_exc_code); |
400 | return; | 390 | return; |
401 | } | 391 | } |
402 | fault = do_exception(regs, 1, trans_exc_code); | 392 | fault = do_exception(regs, VM_WRITE, trans_exc_code); |
403 | if (unlikely(fault)) | 393 | if (unlikely(fault)) |
404 | do_fault_error(regs, 4, trans_exc_code, fault); | 394 | do_fault_error(regs, 4, trans_exc_code, fault); |
405 | } | 395 | } |
@@ -407,9 +397,15 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code) | |||
407 | void __kprobes do_dat_exception(struct pt_regs *regs, long int_code) | 397 | void __kprobes do_dat_exception(struct pt_regs *regs, long int_code) |
408 | { | 398 | { |
409 | unsigned long trans_exc_code = S390_lowcore.trans_exc_code; | 399 | unsigned long trans_exc_code = S390_lowcore.trans_exc_code; |
410 | int fault; | 400 | int access, fault; |
411 | 401 | ||
412 | fault = do_exception(regs, 0, trans_exc_code); | 402 | access = VM_READ | VM_EXEC | VM_WRITE; |
403 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
404 | if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && | ||
405 | (trans_exc_code & 3) == 0) | ||
406 | access = VM_EXEC; | ||
407 | #endif | ||
408 | fault = do_exception(regs, access, trans_exc_code); | ||
413 | if (unlikely(fault)) | 409 | if (unlikely(fault)) |
414 | do_fault_error(regs, int_code & 255, trans_exc_code, fault); | 410 | do_fault_error(regs, int_code & 255, trans_exc_code, fault); |
415 | } | 411 | } |