elf.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/export.h>
  3. #include <linux/sched.h>
  4. #include <linux/personality.h>
  5. #include <linux/binfmts.h>
  6. #include <linux/elf.h>
  7. #include <linux/elf-fdpic.h>
  8. #include <asm/system_info.h>
  9. int elf_check_arch(const struct elf32_hdr *x)
  10. {
  11. unsigned int eflags;
  12. /* Make sure it's an ARM executable */
  13. if (x->e_machine != EM_ARM)
  14. return 0;
  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. eflags = x->e_flags;
  22. if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
  23. unsigned int flt_fmt;
  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. flt_fmt = eflags & (EF_ARM_VFP_FLOAT | EF_ARM_SOFT_FLOAT);
  28. /* VFP requires the supporting code */
  29. if (flt_fmt == EF_ARM_VFP_FLOAT && !(elf_hwcap & HWCAP_VFP))
  30. return 0;
  31. }
  32. return 1;
  33. }
  34. EXPORT_SYMBOL(elf_check_arch);
  35. void elf_set_personality(const struct elf32_hdr *x)
  36. {
  37. unsigned int eflags = x->e_flags;
  38. unsigned int personality = current->personality & ~PER_MASK;
  39. /*
  40. * We only support Linux ELF executables, so always set the
  41. * personality to LINUX.
  42. */
  43. personality |= PER_LINUX;
  44. /*
  45. * APCS-26 is only valid for OABI executables
  46. */
  47. if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN &&
  48. (eflags & EF_ARM_APCS_26))
  49. personality &= ~ADDR_LIMIT_32BIT;
  50. else
  51. personality |= ADDR_LIMIT_32BIT;
  52. set_personality(personality);
  53. /*
  54. * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0
  55. * and CP1, we only enable access to the iWMMXt coprocessor if the
  56. * binary is EABI or softfloat (and thus, guaranteed not to use
  57. * FPA instructions.)
  58. */
  59. if (elf_hwcap & HWCAP_IWMMXT &&
  60. eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) {
  61. set_thread_flag(TIF_USING_IWMMXT);
  62. } else {
  63. clear_thread_flag(TIF_USING_IWMMXT);
  64. }
  65. }
  66. EXPORT_SYMBOL(elf_set_personality);
  67. /*
  68. * An executable for which elf_read_implies_exec() returns TRUE will
  69. * have the READ_IMPLIES_EXEC personality flag set automatically.
  70. *
  71. * The decision process for determining the results are:
  72. *
  73. *              CPU: | lacks NX*  | has NX |
  74. * ELF:              |            |           |
  75. * ---------------------|------------|------------|
  76. * missing PT_GNU_STACK | exec-all   | exec-all  |
  77. * PT_GNU_STACK == RWX  | exec-all   | exec-stack |
  78. * PT_GNU_STACK == RW   | exec-all  | exec-none |
  79. *
  80. * exec-all : all PROT_READ user mappings are executable, except when
  81. * backed by files on a noexec-filesystem.
  82. * exec-none : only PROT_EXEC user mappings are executable.
  83. * exec-stack: only the stack and PROT_EXEC user mappings are executable.
  84. *
  85. * *this column has no architectural effect: NX markings are ignored by
  86. * hardware, but may have behavioral effects when "wants X" collides with
  87. * "cannot be X" constraints in memory permission flags, as in
  88. * https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com
  89. *
  90. */
  91. int arm_elf_read_implies_exec(int executable_stack)
  92. {
  93. if (executable_stack == EXSTACK_DEFAULT)
  94. return 1;
  95. if (cpu_architecture() < CPU_ARCH_ARMv6)
  96. return 1;
  97. return 0;
  98. }
  99. EXPORT_SYMBOL(arm_elf_read_implies_exec);
  100. #if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
  101. void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
  102. struct elf_fdpic_params *interp_params,
  103. unsigned long *start_stack,
  104. unsigned long *start_brk)
  105. {
  106. elf_set_personality(&exec_params->hdr);
  107. exec_params->load_addr = 0x8000;
  108. interp_params->load_addr = ELF_ET_DYN_BASE;
  109. *start_stack = TASK_SIZE - SZ_16M;
  110. if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
  111. exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
  112. exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
  113. }
  114. }
  115. #endif