aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/elf.h16
-rw-r--r--arch/arm/include/asm/mmu.h8
-rw-r--r--arch/arm/include/asm/processor.h22
-rw-r--r--arch/arm/include/asm/ucontext.h1
-rw-r--r--arch/arm/include/uapi/asm/ptrace.h4
-rw-r--r--arch/arm/include/uapi/asm/unistd.h1
-rw-r--r--arch/arm/kernel/asm-offsets.c4
-rw-r--r--arch/arm/kernel/elf.c24
-rw-r--r--arch/arm/kernel/signal.c53
-rw-r--r--arch/arm/kernel/signal.h11
-rw-r--r--arch/arm/kernel/sigreturn_codes.S56
-rw-r--r--arch/arm/kernel/traps.c3
-rw-r--r--fs/Kconfig.binfmt4
-rw-r--r--fs/binfmt_elf.c15
-rw-r--r--fs/binfmt_elf_fdpic.c13
15 files changed, 199 insertions, 36 deletions
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index f13ae153fb24..ad0ca4f2ba13 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -100,10 +100,15 @@ struct elf32_hdr;
100extern int elf_check_arch(const struct elf32_hdr *); 100extern int elf_check_arch(const struct elf32_hdr *);
101#define elf_check_arch elf_check_arch 101#define elf_check_arch elf_check_arch
102 102
103#define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC platform */
104#define elf_check_fdpic(x) ((x)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC)
105#define elf_check_const_displacement(x) ((x)->e_flags & EF_ARM_PIC)
106#define ELF_FDPIC_CORE_EFLAGS 0
107
103#define vmcore_elf64_check_arch(x) (0) 108#define vmcore_elf64_check_arch(x) (0)
104 109
105extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int); 110extern int arm_elf_read_implies_exec(int);
106#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk) 111#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(stk)
107 112
108struct task_struct; 113struct task_struct;
109int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); 114int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
@@ -120,6 +125,13 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
120 have no such handler. */ 125 have no such handler. */
121#define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 126#define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
122 127
128#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \
129 do { \
130 (_r)->ARM_r7 = _exec_map_addr; \
131 (_r)->ARM_r8 = _interp_map_addr; \
132 (_r)->ARM_r9 = dynamic_addr; \
133 } while(0)
134
123extern void elf_set_personality(const struct elf32_hdr *); 135extern void elf_set_personality(const struct elf32_hdr *);
124#define SET_PERSONALITY(ex) elf_set_personality(&(ex)) 136#define SET_PERSONALITY(ex) elf_set_personality(&(ex))
125 137
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index a5b47421059d..bdec37c6ac35 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -14,6 +14,10 @@ typedef struct {
14#ifdef CONFIG_VDSO 14#ifdef CONFIG_VDSO
15 unsigned long vdso; 15 unsigned long vdso;
16#endif 16#endif
17#ifdef CONFIG_BINFMT_ELF_FDPIC
18 unsigned long exec_fdpic_loadmap;
19 unsigned long interp_fdpic_loadmap;
20#endif
17} mm_context_t; 21} mm_context_t;
18 22
19#ifdef CONFIG_CPU_HAS_ASID 23#ifdef CONFIG_CPU_HAS_ASID
@@ -33,6 +37,10 @@ typedef struct {
33 */ 37 */
34typedef struct { 38typedef struct {
35 unsigned long end_brk; 39 unsigned long end_brk;
40#ifdef CONFIG_BINFMT_ELF_FDPIC
41 unsigned long exec_fdpic_loadmap;
42 unsigned long interp_fdpic_loadmap;
43#endif
36} mm_context_t; 44} mm_context_t;
37 45
38#endif 46#endif
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index c3d5fc124a05..338cbe0a18ef 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -47,15 +47,24 @@ struct thread_struct {
47 47
48#define INIT_THREAD { } 48#define INIT_THREAD { }
49 49
50#ifdef CONFIG_MMU
51#define nommu_start_thread(regs) do { } while (0)
52#else
53#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
54#endif
55
56#define start_thread(regs,pc,sp) \ 50#define start_thread(regs,pc,sp) \
57({ \ 51({ \
52 unsigned long r7, r8, r9; \
53 \
54 if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC)) { \
55 r7 = regs->ARM_r7; \
56 r8 = regs->ARM_r8; \
57 r9 = regs->ARM_r9; \
58 } \
58 memset(regs->uregs, 0, sizeof(regs->uregs)); \ 59 memset(regs->uregs, 0, sizeof(regs->uregs)); \
60 if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) && \
61 current->personality & FDPIC_FUNCPTRS) { \
62 regs->ARM_r7 = r7; \
63 regs->ARM_r8 = r8; \
64 regs->ARM_r9 = r9; \
65 regs->ARM_r10 = current->mm->start_data; \
66 } else if (!IS_ENABLED(CONFIG_MMU)) \
67 regs->ARM_r10 = current->mm->start_data; \
59 if (current->personality & ADDR_LIMIT_32BIT) \ 68 if (current->personality & ADDR_LIMIT_32BIT) \
60 regs->ARM_cpsr = USR_MODE; \ 69 regs->ARM_cpsr = USR_MODE; \
61 else \ 70 else \
@@ -65,7 +74,6 @@ struct thread_struct {
65 regs->ARM_cpsr |= PSR_ENDSTATE; \ 74 regs->ARM_cpsr |= PSR_ENDSTATE; \
66 regs->ARM_pc = pc & ~1; /* pc */ \ 75 regs->ARM_pc = pc & ~1; /* pc */ \
67 regs->ARM_sp = sp; /* sp */ \ 76 regs->ARM_sp = sp; /* sp */ \
68 nommu_start_thread(regs); \
69}) 77})
70 78
71/* Forward declaration, a strange C thing */ 79/* Forward declaration, a strange C thing */
diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
index 921d8274855c..b42c75ae0d19 100644
--- a/arch/arm/include/asm/ucontext.h
+++ b/arch/arm/include/asm/ucontext.h
@@ -2,6 +2,7 @@
2#define _ASMARM_UCONTEXT_H 2#define _ASMARM_UCONTEXT_H
3 3
4#include <asm/fpstate.h> 4#include <asm/fpstate.h>
5#include <asm/user.h>
5 6
6/* 7/*
7 * struct sigcontext only has room for the basic registers, but struct 8 * struct sigcontext only has room for the basic registers, but struct
diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h
index 5af0ed1b825a..3173eb9751fd 100644
--- a/arch/arm/include/uapi/asm/ptrace.h
+++ b/arch/arm/include/uapi/asm/ptrace.h
@@ -31,6 +31,10 @@
31#define PTRACE_SETVFPREGS 28 31#define PTRACE_SETVFPREGS 28
32#define PTRACE_GETHBPREGS 29 32#define PTRACE_GETHBPREGS 29
33#define PTRACE_SETHBPREGS 30 33#define PTRACE_SETHBPREGS 30
34#define PTRACE_GETFDPIC 31
35
36#define PTRACE_GETFDPIC_EXEC 0
37#define PTRACE_GETFDPIC_INTERP 1
34 38
35/* 39/*
36 * PSR bits 40 * PSR bits
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index 28bd456494a3..575b25fc29c6 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -35,5 +35,6 @@
35#define __ARM_NR_usr26 (__ARM_NR_BASE+3) 35#define __ARM_NR_usr26 (__ARM_NR_BASE+3)
36#define __ARM_NR_usr32 (__ARM_NR_BASE+4) 36#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
37#define __ARM_NR_set_tls (__ARM_NR_BASE+5) 37#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
38#define __ARM_NR_get_tls (__ARM_NR_BASE+6)
38 39
39#endif /* _UAPI__ASM_ARM_UNISTD_H */ 40#endif /* _UAPI__ASM_ARM_UNISTD_H */
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 608008229c7d..13c155850822 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -28,6 +28,7 @@
28#include <asm/vdso_datapage.h> 28#include <asm/vdso_datapage.h>
29#include <asm/hardware/cache-l2x0.h> 29#include <asm/hardware/cache-l2x0.h>
30#include <linux/kbuild.h> 30#include <linux/kbuild.h>
31#include "signal.h"
31 32
32/* 33/*
33 * Make sure that the compiler and target are compatible. 34 * Make sure that the compiler and target are compatible.
@@ -112,6 +113,9 @@ int main(void)
112 DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit)); 113 DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit));
113 DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs)); 114 DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
114 BLANK(); 115 BLANK();
116 DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3]));
117 DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3]));
118 BLANK();
115#ifdef CONFIG_CACHE_L2X0 119#ifdef CONFIG_CACHE_L2X0
116 DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); 120 DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base));
117 DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); 121 DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl));
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
index d0d1e83150c9..569e69ece5ca 100644
--- a/arch/arm/kernel/elf.c
+++ b/arch/arm/kernel/elf.c
@@ -3,6 +3,7 @@
3#include <linux/personality.h> 3#include <linux/personality.h>
4#include <linux/binfmts.h> 4#include <linux/binfmts.h>
5#include <linux/elf.h> 5#include <linux/elf.h>
6#include <linux/elf-fdpic.h>
6#include <asm/system_info.h> 7#include <asm/system_info.h>
7 8
8int elf_check_arch(const struct elf32_hdr *x) 9int elf_check_arch(const struct elf32_hdr *x)
@@ -80,7 +81,7 @@ EXPORT_SYMBOL(elf_set_personality);
80 * - the binary requires an executable stack 81 * - the binary requires an executable stack
81 * - we're running on a CPU which doesn't support NX. 82 * - we're running on a CPU which doesn't support NX.
82 */ 83 */
83int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack) 84int arm_elf_read_implies_exec(int executable_stack)
84{ 85{
85 if (executable_stack != EXSTACK_DISABLE_X) 86 if (executable_stack != EXSTACK_DISABLE_X)
86 return 1; 87 return 1;
@@ -89,3 +90,24 @@ int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
89 return 0; 90 return 0;
90} 91}
91EXPORT_SYMBOL(arm_elf_read_implies_exec); 92EXPORT_SYMBOL(arm_elf_read_implies_exec);
93
94#if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
95
96void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
97 struct elf_fdpic_params *interp_params,
98 unsigned long *start_stack,
99 unsigned long *start_brk)
100{
101 elf_set_personality(&exec_params->hdr);
102
103 exec_params->load_addr = 0x8000;
104 interp_params->load_addr = ELF_ET_DYN_BASE;
105 *start_stack = TASK_SIZE - SZ_16M;
106
107 if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
108 exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
109 exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
110 }
111}
112
113#endif
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index e2de50bf8742..237973492479 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -19,11 +19,12 @@
19#include <asm/elf.h> 19#include <asm/elf.h>
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/traps.h> 21#include <asm/traps.h>
22#include <asm/ucontext.h>
23#include <asm/unistd.h> 22#include <asm/unistd.h>
24#include <asm/vfp.h> 23#include <asm/vfp.h>
25 24
26extern const unsigned long sigreturn_codes[7]; 25#include "signal.h"
26
27extern const unsigned long sigreturn_codes[17];
27 28
28static unsigned long signal_return_offset; 29static unsigned long signal_return_offset;
29 30
@@ -172,15 +173,6 @@ static int restore_vfp_context(char __user **auxp)
172/* 173/*
173 * Do a signal return; undo the signal stack. These are aligned to 64-bit. 174 * Do a signal return; undo the signal stack. These are aligned to 64-bit.
174 */ 175 */
175struct sigframe {
176 struct ucontext uc;
177 unsigned long retcode[2];
178};
179
180struct rt_sigframe {
181 struct siginfo info;
182 struct sigframe sig;
183};
184 176
185static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) 177static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
186{ 178{
@@ -366,9 +358,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
366 unsigned long __user *rc, void __user *frame) 358 unsigned long __user *rc, void __user *frame)
367{ 359{
368 unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; 360 unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
361 unsigned long handler_fdpic_GOT = 0;
369 unsigned long retcode; 362 unsigned long retcode;
370 int thumb = 0; 363 unsigned int idx, thumb = 0;
371 unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); 364 unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
365 bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
366 (current->personality & FDPIC_FUNCPTRS);
367
368 if (fdpic) {
369 unsigned long __user *fdpic_func_desc =
370 (unsigned long __user *)handler;
371 if (__get_user(handler, &fdpic_func_desc[0]) ||
372 __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
373 return 1;
374 }
372 375
373 cpsr |= PSR_ENDSTATE; 376 cpsr |= PSR_ENDSTATE;
374 377
@@ -408,9 +411,26 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
408 411
409 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 412 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
410 retcode = (unsigned long)ksig->ka.sa.sa_restorer; 413 retcode = (unsigned long)ksig->ka.sa.sa_restorer;
414 if (fdpic) {
415 /*
416 * We need code to load the function descriptor.
417 * That code follows the standard sigreturn code
418 * (6 words), and is made of 3 + 2 words for each
419 * variant. The 4th copied word is the actual FD
420 * address that the assembly code expects.
421 */
422 idx = 6 + thumb * 3;
423 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
424 idx += 5;
425 if (__put_user(sigreturn_codes[idx], rc ) ||
426 __put_user(sigreturn_codes[idx+1], rc+1) ||
427 __put_user(sigreturn_codes[idx+2], rc+2) ||
428 __put_user(retcode, rc+3))
429 return 1;
430 goto rc_finish;
431 }
411 } else { 432 } else {
412 unsigned int idx = thumb << 1; 433 idx = thumb << 1;
413
414 if (ksig->ka.sa.sa_flags & SA_SIGINFO) 434 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
415 idx += 3; 435 idx += 3;
416 436
@@ -422,6 +442,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
422 __put_user(sigreturn_codes[idx+1], rc+1)) 442 __put_user(sigreturn_codes[idx+1], rc+1))
423 return 1; 443 return 1;
424 444
445rc_finish:
425#ifdef CONFIG_MMU 446#ifdef CONFIG_MMU
426 if (cpsr & MODE32_BIT) { 447 if (cpsr & MODE32_BIT) {
427 struct mm_struct *mm = current->mm; 448 struct mm_struct *mm = current->mm;
@@ -441,7 +462,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
441 * the return code written onto the stack. 462 * the return code written onto the stack.
442 */ 463 */
443 flush_icache_range((unsigned long)rc, 464 flush_icache_range((unsigned long)rc,
444 (unsigned long)(rc + 2)); 465 (unsigned long)(rc + 3));
445 466
446 retcode = ((unsigned long)rc) + thumb; 467 retcode = ((unsigned long)rc) + thumb;
447 } 468 }
@@ -451,6 +472,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
451 regs->ARM_sp = (unsigned long)frame; 472 regs->ARM_sp = (unsigned long)frame;
452 regs->ARM_lr = retcode; 473 regs->ARM_lr = retcode;
453 regs->ARM_pc = handler; 474 regs->ARM_pc = handler;
475 if (fdpic)
476 regs->ARM_r9 = handler_fdpic_GOT;
454 regs->ARM_cpsr = cpsr; 477 regs->ARM_cpsr = cpsr;
455 478
456 return 0; 479 return 0;
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
new file mode 100644
index 000000000000..b7b838b05229
--- /dev/null
+++ b/arch/arm/kernel/signal.h
@@ -0,0 +1,11 @@
1#include <asm/ucontext.h>
2
3struct sigframe {
4 struct ucontext uc;
5 unsigned long retcode[4];
6};
7
8struct rt_sigframe {
9 struct siginfo info;
10 struct sigframe sig;
11};
diff --git a/arch/arm/kernel/sigreturn_codes.S b/arch/arm/kernel/sigreturn_codes.S
index b84d0cb13682..2c7b22e32152 100644
--- a/arch/arm/kernel/sigreturn_codes.S
+++ b/arch/arm/kernel/sigreturn_codes.S
@@ -14,6 +14,8 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <asm/assembler.h>
18#include <asm/asm-offsets.h>
17#include <asm/unistd.h> 19#include <asm/unistd.h>
18 20
19/* 21/*
@@ -51,6 +53,17 @@ ARM_OK( .arm )
51 .thumb 53 .thumb
52 .endm 54 .endm
53 55
56 .macro arm_fdpic_slot n
57 .org sigreturn_codes + 24 + 20 * (\n)
58ARM_OK( .arm )
59 .endm
60
61 .macro thumb_fdpic_slot n
62 .org sigreturn_codes + 24 + 20 * (\n) + 12
63 .thumb
64 .endm
65
66
54#if __LINUX_ARM_ARCH__ <= 4 67#if __LINUX_ARM_ARCH__ <= 4
55 /* 68 /*
56 * Note we manually set minimally required arch that supports 69 * Note we manually set minimally required arch that supports
@@ -90,13 +103,46 @@ ARM_OK( swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE) )
90 movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE) 103 movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
91 swi #0 104 swi #0
92 105
106 /* ARM sigreturn restorer FDPIC bounce code snippet */
107 arm_fdpic_slot 0
108ARM_OK( ldr r3, [sp, #SIGFRAME_RC3_OFFSET] )
109ARM_OK( ldmia r3, {r3, r9} )
110#ifdef CONFIG_ARM_THUMB
111ARM_OK( bx r3 )
112#else
113ARM_OK( ret r3 )
114#endif
115
116 /* Thumb sigreturn restorer FDPIC bounce code snippet */
117 thumb_fdpic_slot 0
118 ldr r3, [sp, #SIGFRAME_RC3_OFFSET]
119 ldmia r3, {r2, r3}
120 mov r9, r3
121 bx r2
122
123 /* ARM sigreturn_rt restorer FDPIC bounce code snippet */
124 arm_fdpic_slot 1
125ARM_OK( ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET] )
126ARM_OK( ldmia r3, {r3, r9} )
127#ifdef CONFIG_ARM_THUMB
128ARM_OK( bx r3 )
129#else
130ARM_OK( ret r3 )
131#endif
132
133 /* Thumb sigreturn_rt restorer FDPIC bounce code snippet */
134 thumb_fdpic_slot 1
135 ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET]
136 ldmia r3, {r2, r3}
137 mov r9, r3
138 bx r2
139
93 /* 140 /*
94 * Note on addtional space: setup_return in signal.c 141 * Note on additional space: setup_return in signal.c
95 * algorithm uses two words copy regardless whether 142 * always copies the same number of words regardless whether
96 * it is thumb case or not, so we need additional 143 * it is thumb case or not, so we need one additional padding
97 * word after real last entry. 144 * word after the last entry.
98 */ 145 */
99 arm_slot 2
100 .space 4 146 .space 4
101 147
102 .size sigreturn_codes, . - sigreturn_codes 148 .size sigreturn_codes, . - sigreturn_codes
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 948c648fea00..43c0560f7b2d 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -647,6 +647,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
647 set_tls(regs->ARM_r0); 647 set_tls(regs->ARM_r0);
648 return 0; 648 return 0;
649 649
650 case NR(get_tls):
651 return current_thread_info()->tp_value[0];
652
650 default: 653 default:
651 /* Calls 9f00xx..9f07ff are defined to return -ENOSYS 654 /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
652 if not implemented, rather than raising SIGILL. This 655 if not implemented, rather than raising SIGILL. This
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index b2f82cf6bf86..58c2bbd385ad 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -34,8 +34,8 @@ config ARCH_BINFMT_ELF_STATE
34 34
35config BINFMT_ELF_FDPIC 35config BINFMT_ELF_FDPIC
36 bool "Kernel support for FDPIC ELF binaries" 36 bool "Kernel support for FDPIC ELF binaries"
37 default y 37 default y if !BINFMT_ELF
38 depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X) 38 depends on (ARM || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
39 select ELFCORE 39 select ELFCORE
40 help 40 help
41 ELF FDPIC binaries are based on ELF, but allow the individual load 41 ELF FDPIC binaries are based on ELF, but allow the individual load
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 73b01e474fdc..e4f7ef8294ac 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -51,6 +51,11 @@
51#define user_siginfo_t siginfo_t 51#define user_siginfo_t siginfo_t
52#endif 52#endif
53 53
54/* That's for binfmt_elf_fdpic to deal with */
55#ifndef elf_check_fdpic
56#define elf_check_fdpic(ex) false
57#endif
58
54static int load_elf_binary(struct linux_binprm *bprm); 59static int load_elf_binary(struct linux_binprm *bprm);
55static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *, 60static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
56 int, int, unsigned long); 61 int, int, unsigned long);
@@ -541,7 +546,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
541 if (interp_elf_ex->e_type != ET_EXEC && 546 if (interp_elf_ex->e_type != ET_EXEC &&
542 interp_elf_ex->e_type != ET_DYN) 547 interp_elf_ex->e_type != ET_DYN)
543 goto out; 548 goto out;
544 if (!elf_check_arch(interp_elf_ex)) 549 if (!elf_check_arch(interp_elf_ex) ||
550 elf_check_fdpic(interp_elf_ex))
545 goto out; 551 goto out;
546 if (!interpreter->f_op->mmap) 552 if (!interpreter->f_op->mmap)
547 goto out; 553 goto out;
@@ -718,6 +724,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
718 goto out; 724 goto out;
719 if (!elf_check_arch(&loc->elf_ex)) 725 if (!elf_check_arch(&loc->elf_ex))
720 goto out; 726 goto out;
727 if (elf_check_fdpic(&loc->elf_ex))
728 goto out;
721 if (!bprm->file->f_op->mmap) 729 if (!bprm->file->f_op->mmap)
722 goto out; 730 goto out;
723 731
@@ -817,7 +825,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
817 if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) 825 if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
818 goto out_free_dentry; 826 goto out_free_dentry;
819 /* Verify the interpreter has a valid arch */ 827 /* Verify the interpreter has a valid arch */
820 if (!elf_check_arch(&loc->interp_elf_ex)) 828 if (!elf_check_arch(&loc->interp_elf_ex) ||
829 elf_check_fdpic(&loc->interp_elf_ex))
821 goto out_free_dentry; 830 goto out_free_dentry;
822 831
823 /* Load the interpreter program headers */ 832 /* Load the interpreter program headers */
@@ -1190,6 +1199,8 @@ static int load_elf_library(struct file *file)
1190 if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || 1199 if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
1191 !elf_check_arch(&elf_ex) || !file->f_op->mmap) 1200 !elf_check_arch(&elf_ex) || !file->f_op->mmap)
1192 goto out; 1201 goto out;
1202 if (elf_check_fdpic(&elf_ex))
1203 goto out;
1193 1204
1194 /* Now read in all of the header information */ 1205 /* Now read in all of the header information */
1195 1206
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index e70c039ac190..5429b035e249 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -378,6 +378,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
378 executable_stack); 378 executable_stack);
379 if (retval < 0) 379 if (retval < 0)
380 goto error; 380 goto error;
381#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
382 retval = arch_setup_additional_pages(bprm, !!interpreter_name);
383 if (retval < 0)
384 goto error;
385#endif
381#endif 386#endif
382 387
383 /* load the executable and interpreter into memory */ 388 /* load the executable and interpreter into memory */
@@ -831,6 +836,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
831 if (phdr->p_vaddr >= seg->p_vaddr && 836 if (phdr->p_vaddr >= seg->p_vaddr &&
832 phdr->p_vaddr + phdr->p_memsz <= 837 phdr->p_vaddr + phdr->p_memsz <=
833 seg->p_vaddr + seg->p_memsz) { 838 seg->p_vaddr + seg->p_memsz) {
839 Elf32_Dyn __user *dyn;
840 Elf32_Sword d_tag;
841
834 params->dynamic_addr = 842 params->dynamic_addr =
835 (phdr->p_vaddr - seg->p_vaddr) + 843 (phdr->p_vaddr - seg->p_vaddr) +
836 seg->addr; 844 seg->addr;
@@ -843,8 +851,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
843 goto dynamic_error; 851 goto dynamic_error;
844 852
845 tmp = phdr->p_memsz / sizeof(Elf32_Dyn); 853 tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
846 if (((Elf32_Dyn *) 854 dyn = (Elf32_Dyn __user *)params->dynamic_addr;
847 params->dynamic_addr)[tmp - 1].d_tag != 0) 855 __get_user(d_tag, &dyn[tmp - 1].d_tag);
856 if (d_tag != 0)
848 goto dynamic_error; 857 goto dynamic_error;
849 break; 858 break;
850 } 859 }