diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
| -rw-r--r-- | arch/arm/kernel/process.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index d3ca4f6915af..536c85fe72a8 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -197,6 +197,7 @@ void machine_shutdown(void) | |||
| 197 | */ | 197 | */ |
| 198 | void machine_halt(void) | 198 | void machine_halt(void) |
| 199 | { | 199 | { |
| 200 | local_irq_disable(); | ||
| 200 | smp_send_stop(); | 201 | smp_send_stop(); |
| 201 | 202 | ||
| 202 | local_irq_disable(); | 203 | local_irq_disable(); |
| @@ -211,6 +212,7 @@ void machine_halt(void) | |||
| 211 | */ | 212 | */ |
| 212 | void machine_power_off(void) | 213 | void machine_power_off(void) |
| 213 | { | 214 | { |
| 215 | local_irq_disable(); | ||
| 214 | smp_send_stop(); | 216 | smp_send_stop(); |
| 215 | 217 | ||
| 216 | if (pm_power_off) | 218 | if (pm_power_off) |
| @@ -230,6 +232,7 @@ void machine_power_off(void) | |||
| 230 | */ | 232 | */ |
| 231 | void machine_restart(char *cmd) | 233 | void machine_restart(char *cmd) |
| 232 | { | 234 | { |
| 235 | local_irq_disable(); | ||
| 233 | smp_send_stop(); | 236 | smp_send_stop(); |
| 234 | 237 | ||
| 235 | arm_pm_restart(reboot_mode, cmd); | 238 | arm_pm_restart(reboot_mode, cmd); |
| @@ -426,10 +429,11 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
| 426 | } | 429 | } |
| 427 | 430 | ||
| 428 | #ifdef CONFIG_MMU | 431 | #ifdef CONFIG_MMU |
| 432 | #ifdef CONFIG_KUSER_HELPERS | ||
| 429 | /* | 433 | /* |
| 430 | * The vectors page is always readable from user space for the | 434 | * The vectors page is always readable from user space for the |
| 431 | * atomic helpers and the signal restart code. Insert it into the | 435 | * atomic helpers. Insert it into the gate_vma so that it is visible |
| 432 | * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. | 436 | * through ptrace and /proc/<pid>/mem. |
| 433 | */ | 437 | */ |
| 434 | static struct vm_area_struct gate_vma = { | 438 | static struct vm_area_struct gate_vma = { |
| 435 | .vm_start = 0xffff0000, | 439 | .vm_start = 0xffff0000, |
| @@ -458,9 +462,48 @@ int in_gate_area_no_mm(unsigned long addr) | |||
| 458 | { | 462 | { |
| 459 | return in_gate_area(NULL, addr); | 463 | return in_gate_area(NULL, addr); |
| 460 | } | 464 | } |
| 465 | #define is_gate_vma(vma) ((vma) = &gate_vma) | ||
| 466 | #else | ||
| 467 | #define is_gate_vma(vma) 0 | ||
| 468 | #endif | ||
| 461 | 469 | ||
| 462 | const char *arch_vma_name(struct vm_area_struct *vma) | 470 | const char *arch_vma_name(struct vm_area_struct *vma) |
| 463 | { | 471 | { |
| 464 | return (vma == &gate_vma) ? "[vectors]" : NULL; | 472 | return is_gate_vma(vma) ? "[vectors]" : |
| 473 | (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? | ||
| 474 | "[sigpage]" : NULL; | ||
| 475 | } | ||
| 476 | |||
| 477 | static struct page *signal_page; | ||
| 478 | extern struct page *get_signal_page(void); | ||
| 479 | |||
| 480 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | ||
| 481 | { | ||
| 482 | struct mm_struct *mm = current->mm; | ||
| 483 | unsigned long addr; | ||
| 484 | int ret; | ||
| 485 | |||
| 486 | if (!signal_page) | ||
| 487 | signal_page = get_signal_page(); | ||
| 488 | if (!signal_page) | ||
| 489 | return -ENOMEM; | ||
| 490 | |||
| 491 | down_write(&mm->mmap_sem); | ||
| 492 | addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); | ||
| 493 | if (IS_ERR_VALUE(addr)) { | ||
| 494 | ret = addr; | ||
| 495 | goto up_fail; | ||
| 496 | } | ||
| 497 | |||
| 498 | ret = install_special_mapping(mm, addr, PAGE_SIZE, | ||
| 499 | VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, | ||
| 500 | &signal_page); | ||
| 501 | |||
| 502 | if (ret == 0) | ||
| 503 | mm->context.sigpage = addr; | ||
| 504 | |||
| 505 | up_fail: | ||
| 506 | up_write(&mm->mmap_sem); | ||
| 507 | return ret; | ||
| 465 | } | 508 | } |
| 466 | #endif | 509 | #endif |
