hc
2023-11-06 36f0949ef9854b82a9a3154d970da4e3b8d12a61
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// SPDX-License-Identifier: GPL-2.0
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <linux/elf-fdpic.h>
#include <asm/system_info.h>
 
int elf_check_arch(const struct elf32_hdr *x)
{
   unsigned int eflags;
 
   /* Make sure it's an ARM executable */
   if (x->e_machine != EM_ARM)
       return 0;
 
   /* Make sure the entry address is reasonable */
   if (x->e_entry & 1) {
       if (!(elf_hwcap & HWCAP_THUMB))
           return 0;
   } else if (x->e_entry & 3)
       return 0;
 
   eflags = x->e_flags;
   if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
       unsigned int flt_fmt;
 
       /* APCS26 is only allowed if the CPU supports it */
       if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT))
           return 0;
 
       flt_fmt = eflags & (EF_ARM_VFP_FLOAT | EF_ARM_SOFT_FLOAT);
 
       /* VFP requires the supporting code */
       if (flt_fmt == EF_ARM_VFP_FLOAT && !(elf_hwcap & HWCAP_VFP))
           return 0;
   }
   return 1;
}
EXPORT_SYMBOL(elf_check_arch);
 
void elf_set_personality(const struct elf32_hdr *x)
{
   unsigned int eflags = x->e_flags;
   unsigned int personality = current->personality & ~PER_MASK;
 
   /*
    * We only support Linux ELF executables, so always set the
    * personality to LINUX.
    */
   personality |= PER_LINUX;
 
   /*
    * APCS-26 is only valid for OABI executables
    */
   if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN &&
       (eflags & EF_ARM_APCS_26))
       personality &= ~ADDR_LIMIT_32BIT;
   else
       personality |= ADDR_LIMIT_32BIT;
 
   set_personality(personality);
 
   /*
    * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0
    * and CP1, we only enable access to the iWMMXt coprocessor if the
    * binary is EABI or softfloat (and thus, guaranteed not to use
    * FPA instructions.)
    */
   if (elf_hwcap & HWCAP_IWMMXT &&
       eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) {
       set_thread_flag(TIF_USING_IWMMXT);
   } else {
       clear_thread_flag(TIF_USING_IWMMXT);
   }
}
EXPORT_SYMBOL(elf_set_personality);
 
/*
 * Set READ_IMPLIES_EXEC if:
 *  - the binary requires an executable stack
 *  - we're running on a CPU which doesn't support NX.
 */
int arm_elf_read_implies_exec(int executable_stack)
{
   if (executable_stack != EXSTACK_DISABLE_X)
       return 1;
   if (cpu_architecture() < CPU_ARCH_ARMv6)
       return 1;
   return 0;
}
EXPORT_SYMBOL(arm_elf_read_implies_exec);
 
#if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
 
void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
                  struct elf_fdpic_params *interp_params,
                  unsigned long *start_stack,
                  unsigned long *start_brk)
{
   elf_set_personality(&exec_params->hdr);
 
   exec_params->load_addr = 0x8000;
   interp_params->load_addr = ELF_ET_DYN_BASE;
   *start_stack = TASK_SIZE - SZ_16M;
 
   if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
       exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
       exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
   }
}
 
#endif