Skip to content

Commit 17ef329

Browse files
Russell Kinggregkh
Russell King
authored andcommitted
ARM: fix a cockup in 48be69a (ARM: move signal handlers into a vdso-like page)
commit e0d4075 upstream. Unfortunately, I never committed the fix to a nasty oops which can occur as a result of that commit: ------------[ cut here ]------------ kernel BUG at /home/olof/work/batch/include/linux/mm.h:414! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 PID: 490 Comm: killall5 Not tainted 3.11.0-rc3-00288-gabe0308 #53 task: e90acac0 ti: e9be8000 task.ti: e9be8000 PC is at special_mapping_fault+0xa4/0xc4 LR is at __do_fault+0x68/0x48c This doesn't show up unless you do quite a bit of testing; a simple boot test does not do this, so all my nightly tests were passing fine. The reason for this is that install_special_mapping() expects the page array to stick around, and as this was only inserting one page which was stored on the kernel stack, that's why this was blowing up. Reported-by: Olof Johansson <[email protected]> Tested-by: Olof Johansson <[email protected]> Signed-off-by: Russell King <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 75bc444 commit 17ef329

File tree

2 files changed

+24
-26
lines changed

2 files changed

+24
-26
lines changed

arch/arm/kernel/process.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,17 +478,18 @@ const char *arch_vma_name(struct vm_area_struct *vma)
478478
"[sigpage]" : NULL;
479479
}
480480

481+
static struct page *signal_page;
481482
extern struct page *get_signal_page(void);
482483

483484
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
484485
{
485486
struct mm_struct *mm = current->mm;
486-
struct page *page;
487487
unsigned long addr;
488488
int ret;
489489

490-
page = get_signal_page();
491-
if (!page)
490+
if (!signal_page)
491+
signal_page = get_signal_page();
492+
if (!signal_page)
492493
return -ENOMEM;
493494

494495
down_write(&mm->mmap_sem);
@@ -500,7 +501,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
500501

501502
ret = install_special_mapping(mm, addr, PAGE_SIZE,
502503
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
503-
&page);
504+
&signal_page);
504505

505506
if (ret == 0)
506507
mm->context.sigpage = addr;

arch/arm/kernel/signal.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -609,35 +609,32 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
609609
return 0;
610610
}
611611

612-
static struct page *signal_page;
613-
614612
struct page *get_signal_page(void)
615613
{
616-
if (!signal_page) {
617-
unsigned long ptr;
618-
unsigned offset;
619-
void *addr;
614+
unsigned long ptr;
615+
unsigned offset;
616+
struct page *page;
617+
void *addr;
620618

621-
signal_page = alloc_pages(GFP_KERNEL, 0);
619+
page = alloc_pages(GFP_KERNEL, 0);
622620

623-
if (!signal_page)
624-
return NULL;
621+
if (!page)
622+
return NULL;
625623

626-
addr = page_address(signal_page);
624+
addr = page_address(page);
627625

628-
/* Give the signal return code some randomness */
629-
offset = 0x200 + (get_random_int() & 0x7fc);
630-
signal_return_offset = offset;
626+
/* Give the signal return code some randomness */
627+
offset = 0x200 + (get_random_int() & 0x7fc);
628+
signal_return_offset = offset;
631629

632-
/*
633-
* Copy signal return handlers into the vector page, and
634-
* set sigreturn to be a pointer to these.
635-
*/
636-
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
630+
/*
631+
* Copy signal return handlers into the vector page, and
632+
* set sigreturn to be a pointer to these.
633+
*/
634+
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
637635

638-
ptr = (unsigned long)addr + offset;
639-
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
640-
}
636+
ptr = (unsigned long)addr + offset;
637+
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
641638

642-
return signal_page;
639+
return page;
643640
}

0 commit comments

Comments
 (0)