diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 81ef686a91ca..a0a691d1cbee 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -306,7 +306,6 @@ void __show_regs(struct pt_regs *regs) | |||
306 | 306 | ||
307 | void show_regs(struct pt_regs * regs) | 307 | void show_regs(struct pt_regs * regs) |
308 | { | 308 | { |
309 | printk("\n"); | ||
310 | __show_regs(regs); | 309 | __show_regs(regs); |
311 | dump_stack(); | 310 | dump_stack(); |
312 | } | 311 | } |
@@ -334,6 +333,8 @@ void flush_thread(void) | |||
334 | memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); | 333 | memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); |
335 | memset(&thread->fpstate, 0, sizeof(union fp_state)); | 334 | memset(&thread->fpstate, 0, sizeof(union fp_state)); |
336 | 335 | ||
336 | flush_tls(); | ||
337 | |||
337 | thread_notify(THREAD_NOTIFY_FLUSH, thread); | 338 | thread_notify(THREAD_NOTIFY_FLUSH, thread); |
338 | } | 339 | } |
339 | 340 | ||
@@ -472,19 +473,57 @@ int in_gate_area_no_mm(unsigned long addr) | |||
472 | 473 | ||
473 | const char *arch_vma_name(struct vm_area_struct *vma) | 474 | const char *arch_vma_name(struct vm_area_struct *vma) |
474 | { | 475 | { |
475 | return is_gate_vma(vma) ? "[vectors]" : | 476 | return is_gate_vma(vma) ? "[vectors]" : NULL; |
476 | (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? | 477 | } |
477 | "[sigpage]" : NULL; | 478 | |
479 | /* If possible, provide a placement hint at a random offset from the | ||
480 | * stack for the signal page. | ||
481 | */ | ||
482 | static unsigned long sigpage_addr(const struct mm_struct *mm, | ||
483 | unsigned int npages) | ||
484 | { | ||
485 | unsigned long offset; | ||
486 | unsigned long first; | ||
487 | unsigned long last; | ||
488 | unsigned long addr; | ||
489 | unsigned int slots; | ||
490 | |||
491 | first = PAGE_ALIGN(mm->start_stack); | ||
492 | |||
493 | last = TASK_SIZE - (npages << PAGE_SHIFT); | ||
494 | |||
495 | /* No room after stack? */ | ||
496 | if (first > last) | ||
497 | return 0; | ||
498 | |||
499 | /* Just enough room? */ | ||
500 | if (first == last) | ||
501 | return first; | ||
502 | |||
503 | slots = ((last - first) >> PAGE_SHIFT) + 1; | ||
504 | |||
505 | offset = get_random_int() % slots; | ||
506 | |||
507 | addr = first + (offset << PAGE_SHIFT); | ||
508 | |||
509 | return addr; | ||
478 | } | 510 | } |
479 | 511 | ||
480 | static struct page *signal_page; | 512 | static struct page *signal_page; |
481 | extern struct page *get_signal_page(void); | 513 | extern struct page *get_signal_page(void); |
482 | 514 | ||
515 | static const struct vm_special_mapping sigpage_mapping = { | ||
516 | .name = "[sigpage]", | ||
517 | .pages = &signal_page, | ||
518 | }; | ||
519 | |||
483 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | 520 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) |
484 | { | 521 | { |
485 | struct mm_struct *mm = current->mm; | 522 | struct mm_struct *mm = current->mm; |
523 | struct vm_area_struct *vma; | ||
486 | unsigned long addr; | 524 | unsigned long addr; |
487 | int ret; | 525 | unsigned long hint; |
526 | int ret = 0; | ||
488 | 527 | ||
489 | if (!signal_page) | 528 | if (!signal_page) |
490 | signal_page = get_signal_page(); | 529 | signal_page = get_signal_page(); |
@@ -492,18 +531,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
492 | return -ENOMEM; | 531 | return -ENOMEM; |
493 | 532 | ||
494 | down_write(&mm->mmap_sem); | 533 | down_write(&mm->mmap_sem); |
495 | addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); | 534 | hint = sigpage_addr(mm, 1); |
535 | addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0); | ||
496 | if (IS_ERR_VALUE(addr)) { | 536 | if (IS_ERR_VALUE(addr)) { |
497 | ret = addr; | 537 | ret = addr; |
498 | goto up_fail; | 538 | goto up_fail; |
499 | } | 539 | } |
500 | 540 | ||
501 | ret = install_special_mapping(mm, addr, PAGE_SIZE, | 541 | vma = _install_special_mapping(mm, addr, PAGE_SIZE, |
502 | VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, | 542 | VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, |
503 | &signal_page); | 543 | &sigpage_mapping); |
544 | |||
545 | if (IS_ERR(vma)) { | ||
546 | ret = PTR_ERR(vma); | ||
547 | goto up_fail; | ||
548 | } | ||
504 | 549 | ||
505 | if (ret == 0) | 550 | mm->context.sigpage = addr; |
506 | mm->context.sigpage = addr; | ||
507 | 551 | ||
508 | up_fail: | 552 | up_fail: |
509 | up_write(&mm->mmap_sem); | 553 | up_write(&mm->mmap_sem); |