Skip to content

Commit

Permalink
Merge branch 'security-fixes' into fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Russell King committed Aug 1, 2013
2 parents 2449189 + a5463cd commit 24195ca
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 99 deletions.
3 changes: 2 additions & 1 deletion arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ config VECTORS_BASE
default DRAM_BASE if REMAP_VECTORS_TO_RAM
default 0x00000000
help
The base address of exception vectors.
The base address of exception vectors. This must be two pages
in size.

config ARM_PATCH_PHYS_VIRT
bool "Patch physical to virtual translations at runtime" if EMBEDDED
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,8 @@ struct mm_struct;
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk

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

#endif
1 change: 1 addition & 0 deletions arch/arm/include/asm/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef struct {
int switch_pending;
#endif
unsigned int vmalloc_seq;
unsigned long sigpage;
} mm_context_t;

#ifdef CONFIG_CPU_HAS_ASID
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, const void *from);

#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
#endif

#ifdef CONFIG_ARM_LPAE
#include <asm/pgtable-3level-types.h>
Expand Down
103 changes: 53 additions & 50 deletions arch/arm/kernel/entry-armv.S
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,18 @@ ENDPROC(__switch_to)
#endif
.endm

.macro kuser_pad, sym, size
.if (. - \sym) & 3
.rept 4 - (. - \sym) & 3
.byte 0
.endr
.endif
.rept (\size - (. - \sym)) / 4
.word 0xe7fddef1
.endr
.endm

#ifdef CONFIG_KUSER_HELPERS
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
Expand Down Expand Up @@ -832,18 +844,13 @@ kuser_cmpxchg64_fixup:
#error "incoherent kernel configuration"
#endif

/* pad to next slot */
.rept (16 - (. - __kuser_cmpxchg64)/4)
.word 0
.endr

.align 5
kuser_pad __kuser_cmpxchg64, 64

__kuser_memory_barrier: @ 0xffff0fa0
smp_dmb arm
usr_ret lr

.align 5
kuser_pad __kuser_memory_barrier, 32

__kuser_cmpxchg: @ 0xffff0fc0

Expand Down Expand Up @@ -916,13 +923,14 @@ kuser_cmpxchg32_fixup:

#endif

.align 5
kuser_pad __kuser_cmpxchg, 32

__kuser_get_tls: @ 0xffff0fe0
ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init
usr_ret lr
mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code
.rep 4
kuser_pad __kuser_get_tls, 16
.rep 3
.word 0 @ 0xffff0ff0 software TLS value, then
.endr @ pad up to __kuser_helper_version

Expand All @@ -932,14 +940,16 @@ __kuser_helper_version: @ 0xffff0ffc
.globl __kuser_helper_end
__kuser_helper_end:

#endif

THUMB( .thumb )

/*
* Vector stubs.
*
* This code is copied to 0xffff0200 so we can use branches in the
* vectors, rather than ldr's. Note that this code must not
* exceed 0x300 bytes.
* This code is copied to 0xffff1000 so we can use branches in the
* vectors, rather than ldr's. Note that this code must not exceed
* a page size.
*
* Common stub entry macro:
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
Expand Down Expand Up @@ -986,8 +996,17 @@ ENDPROC(vector_\name)
1:
.endm

.globl __stubs_start
.section .stubs, "ax", %progbits
__stubs_start:
@ This must be the first word
.word vector_swi

vector_rst:
ARM( swi SYS_ERROR0 )
THUMB( svc #0 )
THUMB( nop )
b vector_und

/*
* Interrupt dispatcher
*/
Expand Down Expand Up @@ -1081,6 +1100,16 @@ __stubs_start:

.align 5

/*=============================================================================
* Address exception handler
*-----------------------------------------------------------------------------
* These aren't too critical.
* (they're not supposed to happen, and won't happen in 32-bit data mode).
*/

vector_addrexcptn:
b vector_addrexcptn

/*=============================================================================
* Undefined FIQs
*-----------------------------------------------------------------------------
Expand All @@ -1094,45 +1123,19 @@ __stubs_start:
vector_fiq:
subs pc, lr, #4

/*=============================================================================
* Address exception handler
*-----------------------------------------------------------------------------
* These aren't too critical.
* (they're not supposed to happen, and won't happen in 32-bit data mode).
*/

vector_addrexcptn:
b vector_addrexcptn

/*
* We group all the following data together to optimise
* for CPUs with separate I & D caches.
*/
.align 5

.LCvswi:
.word vector_swi

.globl __stubs_end
__stubs_end:

.equ stubs_offset, __vectors_start + 0x200 - __stubs_start
.globl vector_fiq_offset
.equ vector_fiq_offset, vector_fiq

.globl __vectors_start
.section .vectors, "ax", %progbits
__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc #0 )
THUMB( nop )
W(b) vector_und + stubs_offset
W(ldr) pc, .LCvswi + stubs_offset
W(b) vector_pabt + stubs_offset
W(b) vector_dabt + stubs_offset
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset

.globl __vectors_end
__vectors_end:
W(b) vector_rst
W(b) vector_und
W(ldr) pc, __vectors_start + 0x1000
W(b) vector_pabt
W(b) vector_dabt
W(b) vector_addrexcptn
W(b) vector_irq
W(b) vector_fiq

.data

Expand Down
19 changes: 14 additions & 5 deletions arch/arm/kernel/fiq.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
#include <asm/irq.h>
#include <asm/traps.h>

#define FIQ_OFFSET ({ \
extern void *vector_fiq_offset; \
(unsigned)&vector_fiq_offset; \
})

static unsigned long no_fiq_insn;

/* Default reacquire function
Expand Down Expand Up @@ -80,13 +85,16 @@ int show_fiq_list(struct seq_file *p, int prec)
void set_fiq_handler(void *start, unsigned int length)
{
#if defined(CONFIG_CPU_USE_DOMAINS)
memcpy((void *)0xffff001c, start, length);
void *base = (void *)0xffff0000;
#else
memcpy(vectors_page + 0x1c, start, length);
void *base = vectors_page;
#endif
flush_icache_range(0xffff001c, 0xffff001c + length);
unsigned offset = FIQ_OFFSET;

memcpy(base + offset, start, length);
flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
if (!vectors_high())
flush_icache_range(0x1c, 0x1c + length);
flush_icache_range(offset, offset + length);
}

int claim_fiq(struct fiq_handler *f)
Expand Down Expand Up @@ -144,6 +152,7 @@ EXPORT_SYMBOL(disable_fiq);

void __init init_FIQ(int start)
{
no_fiq_insn = *(unsigned long *)0xffff001c;
unsigned offset = FIQ_OFFSET;
no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
fiq_start = start;
}
45 changes: 42 additions & 3 deletions arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,11 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
}

#ifdef CONFIG_MMU
#ifdef CONFIG_KUSER_HELPERS
/*
* The vectors page is always readable from user space for the
* atomic helpers and the signal restart code. Insert it into the
* gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
* atomic helpers. Insert it into the gate_vma so that it is visible
* through ptrace and /proc/<pid>/mem.
*/
static struct vm_area_struct gate_vma = {
.vm_start = 0xffff0000,
Expand Down Expand Up @@ -461,9 +462,47 @@ int in_gate_area_no_mm(unsigned long addr)
{
return in_gate_area(NULL, addr);
}
#define is_gate_vma(vma) ((vma) = &gate_vma)
#else
#define is_gate_vma(vma) 0
#endif

const char *arch_vma_name(struct vm_area_struct *vma)
{
return (vma == &gate_vma) ? "[vectors]" : NULL;
return is_gate_vma(vma) ? "[vectors]" :
(vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
"[sigpage]" : NULL;
}

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)
return -ENOMEM;

down_write(&mm->mmap_sem);
addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
}

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

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

up_fail:
up_write(&mm->mmap_sem);
return ret;
}
#endif
Loading

0 comments on commit 24195ca

Please sign in to comment.