Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
Pull arm fixes fixes from Russell King: "This fixes a couple of problems with commit48be69a026
("ARM: move signal handlers into a vdso-like page"), one of which was originally discovered via my testing originally, but the fix for it was never actually committed. The other shows up on noMMU builds, and such platforms are extremely rare and as such are not part of my nightly testing" * 'fixes' of git://git.linaro.org/people/rmk/linux-arm: ARM: fix nommu builds with48be69a02
(ARM: move signal handlers into a vdso-like page) ARM: fix a cockup in48be69a02
(ARM: move signal handlers into a vdso-like page)
This commit is contained in:
commit
9250d9047d
|
@ -130,8 +130,10 @@ struct mm_struct;
|
||||||
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
||||||
#define arch_randomize_brk arch_randomize_brk
|
#define arch_randomize_brk arch_randomize_brk
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
||||||
struct linux_binprm;
|
struct linux_binprm;
|
||||||
int arch_setup_additional_pages(struct linux_binprm *, int);
|
int arch_setup_additional_pages(struct linux_binprm *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -474,17 +474,18 @@ const char *arch_vma_name(struct vm_area_struct *vma)
|
||||||
"[sigpage]" : NULL;
|
"[sigpage]" : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct page *signal_page;
|
||||||
extern struct page *get_signal_page(void);
|
extern struct page *get_signal_page(void);
|
||||||
|
|
||||||
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
struct page *page;
|
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
page = get_signal_page();
|
if (!signal_page)
|
||||||
if (!page)
|
signal_page = get_signal_page();
|
||||||
|
if (!signal_page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
down_write(&mm->mmap_sem);
|
down_write(&mm->mmap_sem);
|
||||||
|
@ -496,7 +497,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||||
|
|
||||||
ret = install_special_mapping(mm, addr, PAGE_SIZE,
|
ret = install_special_mapping(mm, addr, PAGE_SIZE,
|
||||||
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
|
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
|
||||||
&page);
|
&signal_page);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
mm->context.sigpage = addr;
|
mm->context.sigpage = addr;
|
||||||
|
|
|
@ -402,7 +402,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||||
__put_user(sigreturn_codes[idx+1], rc+1))
|
__put_user(sigreturn_codes[idx+1], rc+1))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) {
|
#ifdef CONFIG_MMU
|
||||||
|
if (cpsr & MODE32_BIT) {
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -412,7 +413,9 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||||
*/
|
*/
|
||||||
retcode = mm->context.sigpage + signal_return_offset +
|
retcode = mm->context.sigpage + signal_return_offset +
|
||||||
(idx << 2) + thumb;
|
(idx << 2) + thumb;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Ensure that the instruction cache sees
|
* Ensure that the instruction cache sees
|
||||||
* the return code written onto the stack.
|
* the return code written onto the stack.
|
||||||
|
@ -614,35 +617,32 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct page *signal_page;
|
|
||||||
|
|
||||||
struct page *get_signal_page(void)
|
struct page *get_signal_page(void)
|
||||||
{
|
{
|
||||||
if (!signal_page) {
|
unsigned long ptr;
|
||||||
unsigned long ptr;
|
unsigned offset;
|
||||||
unsigned offset;
|
struct page *page;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
|
||||||
signal_page = alloc_pages(GFP_KERNEL, 0);
|
page = alloc_pages(GFP_KERNEL, 0);
|
||||||
|
|
||||||
if (!signal_page)
|
if (!page)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
addr = page_address(signal_page);
|
addr = page_address(page);
|
||||||
|
|
||||||
/* Give the signal return code some randomness */
|
/* Give the signal return code some randomness */
|
||||||
offset = 0x200 + (get_random_int() & 0x7fc);
|
offset = 0x200 + (get_random_int() & 0x7fc);
|
||||||
signal_return_offset = offset;
|
signal_return_offset = offset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy signal return handlers into the vector page, and
|
* Copy signal return handlers into the vector page, and
|
||||||
* set sigreturn to be a pointer to these.
|
* set sigreturn to be a pointer to these.
|
||||||
*/
|
*/
|
||||||
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
|
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
|
||||||
|
|
||||||
ptr = (unsigned long)addr + offset;
|
ptr = (unsigned long)addr + offset;
|
||||||
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
|
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
|
||||||
}
|
|
||||||
|
|
||||||
return signal_page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue