diff options
| -rw-r--r-- | arch/powerpc/mm/fault.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 76d8e7cc7805..2dd69bf4af46 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -206,7 +206,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
| 206 | int trap = TRAP(regs); | 206 | int trap = TRAP(regs); |
| 207 | int is_exec = trap == 0x400; | 207 | int is_exec = trap == 0x400; |
| 208 | int fault; | 208 | int fault; |
| 209 | int rc = 0; | 209 | int rc = 0, store_update_sp = 0; |
| 210 | 210 | ||
| 211 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | 211 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) |
| 212 | /* | 212 | /* |
| @@ -280,6 +280,14 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
| 280 | 280 | ||
| 281 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 281 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); |
| 282 | 282 | ||
| 283 | /* | ||
| 284 | * We want to do this outside mmap_sem, because reading code around nip | ||
| 285 | * can result in fault, which will cause a deadlock when called with | ||
| 286 | * mmap_sem held | ||
| 287 | */ | ||
| 288 | if (user_mode(regs)) | ||
| 289 | store_update_sp = store_updates_sp(regs); | ||
| 290 | |||
| 283 | /* When running in the kernel we expect faults to occur only to | 291 | /* When running in the kernel we expect faults to occur only to |
| 284 | * addresses in user space. All other faults represent errors in the | 292 | * addresses in user space. All other faults represent errors in the |
| 285 | * kernel and should generate an OOPS. Unfortunately, in the case of an | 293 | * kernel and should generate an OOPS. Unfortunately, in the case of an |
| @@ -345,8 +353,7 @@ retry: | |||
| 345 | * between the last mapped region and the stack will | 353 | * between the last mapped region and the stack will |
| 346 | * expand the stack rather than segfaulting. | 354 | * expand the stack rather than segfaulting. |
| 347 | */ | 355 | */ |
| 348 | if (address + 2048 < uregs->gpr[1] | 356 | if (address + 2048 < uregs->gpr[1] && !store_update_sp) |
| 349 | && (!user_mode(regs) || !store_updates_sp(regs))) | ||
| 350 | goto bad_area; | 357 | goto bad_area; |
| 351 | } | 358 | } |
| 352 | if (expand_stack(vma, address)) | 359 | if (expand_stack(vma, address)) |
