diff options
author | Matthew Leach <matthew.leach@arm.com> | 2013-10-11 14:52:14 +0100 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2013-10-25 15:59:37 +0100 |
commit | a1d5ebaf8ccdd100f45042ce32c591867de04ac3 (patch) | |
tree | 8f47a40eabb63ca19ec96936fd808537824c0b25 /arch/arm64/kernel/vdso.c | |
parent | 55b89540b0d8d031f90e3d711ec0df3f797ecc61 (diff) | |
download | linux-a1d5ebaf8ccdd100f45042ce32c591867de04ac3.tar.gz linux-a1d5ebaf8ccdd100f45042ce32c591867de04ac3.tar.bz2 linux-a1d5ebaf8ccdd100f45042ce32c591867de04ac3.zip |
arm64: big-endian: don't treat code as data when copying sigret code
Currently the sigreturn compat code is copied to an offset in the
vectors table. When using a BE kernel this data will be stored in the
wrong endianess so when returning from a signal on a 32-bit BE system,
arbitrary code will be executed.
Instead of declaring the code inside a struct and copying that, use
the assembler's .byte directives to store the code in the correct
endianess regardless of platform endianess.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/kernel/vdso.c')
-rw-r--r-- | arch/arm64/kernel/vdso.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 6a389dc1bd49..65d40cf6945a 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -58,7 +58,10 @@ static struct page *vectors_page[1]; static int alloc_vectors_page(void) { extern char __kuser_helper_start[], __kuser_helper_end[]; + extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[]; + int kuser_sz = __kuser_helper_end - __kuser_helper_start; + int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start; unsigned long vpage; vpage = get_zeroed_page(GFP_ATOMIC); @@ -72,7 +75,7 @@ static int alloc_vectors_page(void) /* sigreturn code */ memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET, - aarch32_sigret_code, sizeof(aarch32_sigret_code)); + __aarch32_sigret_code_start, sigret_sz); flush_icache_range(vpage, vpage + PAGE_SIZE); vectors_page[0] = virt_to_page(vpage); |