Skip to content

Commit

Permalink
Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
Browse files Browse the repository at this point in the history
Pull arm fixes fixes from Russell King:
 "This fixes a couple of problems with commit 48be69a ("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 with 48be69a (ARM: move signal handlers into a vdso-like page)
  ARM: fix a cockup in 48be69a (ARM: move signal handlers into a vdso-like page)
  • Loading branch information
torvalds committed Aug 3, 2013
2 parents abe0308 + e35ac62 commit 9250d90
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 28 deletions.
2 changes: 2 additions & 0 deletions arch/arm/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ struct mm_struct;
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk

#ifdef CONFIG_MMU
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
int arch_setup_additional_pages(struct linux_binprm *, int);
#endif

#endif
9 changes: 5 additions & 4 deletions arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,17 +474,18 @@ const char *arch_vma_name(struct vm_area_struct *vma)
"[sigpage]" : NULL;
}

static struct page *signal_page;
extern struct page *get_signal_page(void);

int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
struct mm_struct *mm = current->mm;
struct page *page;
unsigned long addr;
int ret;

page = get_signal_page();
if (!page)
if (!signal_page)
signal_page = get_signal_page();
if (!signal_page)
return -ENOMEM;

down_write(&mm->mmap_sem);
Expand All @@ -496,7 +497,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)

ret = install_special_mapping(mm, addr, PAGE_SIZE,
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
&page);
&signal_page);

if (ret == 0)
mm->context.sigpage = addr;
Expand Down
48 changes: 24 additions & 24 deletions arch/arm/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
__put_user(sigreturn_codes[idx+1], rc+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;

/*
Expand All @@ -412,7 +413,9 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
*/
retcode = mm->context.sigpage + signal_return_offset +
(idx << 2) + thumb;
} else {
} else
#endif
{
/*
* Ensure that the instruction cache sees
* the return code written onto the stack.
Expand Down Expand Up @@ -614,35 +617,32 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
return 0;
}

static struct page *signal_page;

struct page *get_signal_page(void)
{
if (!signal_page) {
unsigned long ptr;
unsigned offset;
void *addr;
unsigned long ptr;
unsigned offset;
struct page *page;
void *addr;

signal_page = alloc_pages(GFP_KERNEL, 0);
page = alloc_pages(GFP_KERNEL, 0);

if (!signal_page)
return NULL;
if (!page)
return NULL;

addr = page_address(signal_page);
addr = page_address(page);

/* Give the signal return code some randomness */
offset = 0x200 + (get_random_int() & 0x7fc);
signal_return_offset = offset;
/* Give the signal return code some randomness */
offset = 0x200 + (get_random_int() & 0x7fc);
signal_return_offset = offset;

/*
* Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these.
*/
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
/*
* Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these.
*/
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));

ptr = (unsigned long)addr + offset;
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
}
ptr = (unsigned long)addr + offset;
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));

return signal_page;
return page;
}

0 comments on commit 9250d90

Please sign in to comment.