diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/elf.c | 79 | ||||
-rw-r--r-- | arch/arm/kernel/module.c | 2 |
3 files changed, 81 insertions, 2 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 1d296fc8494e..4305345987d3 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -10,7 +10,7 @@ endif | |||
10 | 10 | ||
11 | # Object file lists. | 11 | # Object file lists. |
12 | 12 | ||
13 | obj-y := compat.o entry-armv.o entry-common.o irq.o \ | 13 | obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \ |
14 | process.o ptrace.o setup.o signal.o \ | 14 | process.o ptrace.o setup.o signal.o \ |
15 | sys_arm.o stacktrace.o time.o traps.o | 15 | sys_arm.o stacktrace.o time.o traps.o |
16 | 16 | ||
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c new file mode 100644 index 000000000000..513f332f040d --- /dev/null +++ b/arch/arm/kernel/elf.c | |||
@@ -0,0 +1,79 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/sched.h> | ||
3 | #include <linux/personality.h> | ||
4 | #include <linux/binfmts.h> | ||
5 | #include <linux/elf.h> | ||
6 | |||
7 | int elf_check_arch(const struct elf32_hdr *x) | ||
8 | { | ||
9 | unsigned int eflags; | ||
10 | |||
11 | /* Make sure it's an ARM executable */ | ||
12 | if (x->e_machine != EM_ARM) | ||
13 | return 0; | ||
14 | |||
15 | /* Make sure the entry address is reasonable */ | ||
16 | if (x->e_entry & 1) { | ||
17 | if (!(elf_hwcap & HWCAP_THUMB)) | ||
18 | return 0; | ||
19 | } else if (x->e_entry & 3) | ||
20 | return 0; | ||
21 | |||
22 | eflags = x->e_flags; | ||
23 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { | ||
24 | /* APCS26 is only allowed if the CPU supports it */ | ||
25 | if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT)) | ||
26 | return 0; | ||
27 | |||
28 | /* VFP requires the supporting code */ | ||
29 | if ((eflags & EF_ARM_VFP_FLOAT) && !(elf_hwcap & HWCAP_VFP)) | ||
30 | return 0; | ||
31 | } | ||
32 | return 1; | ||
33 | } | ||
34 | EXPORT_SYMBOL(elf_check_arch); | ||
35 | |||
36 | void elf_set_personality(const struct elf32_hdr *x) | ||
37 | { | ||
38 | unsigned int eflags = x->e_flags; | ||
39 | unsigned int personality = PER_LINUX_32BIT; | ||
40 | |||
41 | /* | ||
42 | * APCS-26 is only valid for OABI executables | ||
43 | */ | ||
44 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { | ||
45 | if (eflags & EF_ARM_APCS_26) | ||
46 | personality = PER_LINUX; | ||
47 | } | ||
48 | |||
49 | set_personality(personality); | ||
50 | |||
51 | /* | ||
52 | * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0 | ||
53 | * and CP1, we only enable access to the iWMMXt coprocessor if the | ||
54 | * binary is EABI or softfloat (and thus, guaranteed not to use | ||
55 | * FPA instructions.) | ||
56 | */ | ||
57 | if (elf_hwcap & HWCAP_IWMMXT && | ||
58 | eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) { | ||
59 | set_thread_flag(TIF_USING_IWMMXT); | ||
60 | } else { | ||
61 | clear_thread_flag(TIF_USING_IWMMXT); | ||
62 | } | ||
63 | } | ||
64 | EXPORT_SYMBOL(elf_set_personality); | ||
65 | |||
66 | /* | ||
67 | * Set READ_IMPLIES_EXEC if: | ||
68 | * - the binary requires an executable stack | ||
69 | * - we're running on a CPU which doesn't support NX. | ||
70 | */ | ||
71 | int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack) | ||
72 | { | ||
73 | if (executable_stack != EXSTACK_ENABLE_X) | ||
74 | return 1; | ||
75 | if (cpu_architecture() <= CPU_ARCH_ARMv6) | ||
76 | return 1; | ||
77 | return 0; | ||
78 | } | ||
79 | EXPORT_SYMBOL(arm_elf_read_implies_exec); | ||
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index a68259a0cccd..9203ba7d58ee 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -47,7 +47,7 @@ void *module_alloc(unsigned long size) | |||
47 | if (!area) | 47 | if (!area) |
48 | return NULL; | 48 | return NULL; |
49 | 49 | ||
50 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); | 50 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); |
51 | } | 51 | } |
52 | #else /* CONFIG_MMU */ | 52 | #else /* CONFIG_MMU */ |
53 | void *module_alloc(unsigned long size) | 53 | void *module_alloc(unsigned long size) |