diff options
| -rw-r--r-- | arch/x86/include/asm/elf.h | 13 | ||||
| -rw-r--r-- | fs/binfmt_elf.c | 59 |
2 files changed, 58 insertions, 14 deletions
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index e8ab9a46bc68..1c18d83d3f09 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h | |||
| @@ -245,12 +245,13 @@ extern int force_personality32; | |||
| 245 | #define CORE_DUMP_USE_REGSET | 245 | #define CORE_DUMP_USE_REGSET |
| 246 | #define ELF_EXEC_PAGESIZE 4096 | 246 | #define ELF_EXEC_PAGESIZE 4096 |
| 247 | 247 | ||
| 248 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | 248 | /* |
| 249 | use of this is to invoke "./ld.so someprog" to test out a new version of | 249 | * This is the base location for PIE (ET_DYN with INTERP) loads. On |
| 250 | the loader. We need to make sure that it is out of the way of the program | 250 | * 64-bit, this is raised to 4GB to leave the entire 32-bit address |
| 251 | that it will "exec", and that there is sufficient room for the brk. */ | 251 | * space open for things that want to use the area for 32-bit pointers. |
| 252 | 252 | */ | |
| 253 | #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) | 253 | #define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \ |
| 254 | 0x100000000UL) | ||
| 254 | 255 | ||
| 255 | /* This yields a mask that user programs can use to figure out what | 256 | /* This yields a mask that user programs can use to figure out what |
| 256 | instruction set this CPU supports. This could be done in user space, | 257 | instruction set this CPU supports. This could be done in user space, |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 5075fd5c62c8..7465c3ea5dd5 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -927,17 +927,60 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
| 927 | elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; | 927 | elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; |
| 928 | 928 | ||
| 929 | vaddr = elf_ppnt->p_vaddr; | 929 | vaddr = elf_ppnt->p_vaddr; |
| 930 | /* | ||
| 931 | * If we are loading ET_EXEC or we have already performed | ||
| 932 | * the ET_DYN load_addr calculations, proceed normally. | ||
| 933 | */ | ||
| 930 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { | 934 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { |
| 931 | elf_flags |= MAP_FIXED; | 935 | elf_flags |= MAP_FIXED; |
| 932 | } else if (loc->elf_ex.e_type == ET_DYN) { | 936 | } else if (loc->elf_ex.e_type == ET_DYN) { |
| 933 | /* Try and get dynamic programs out of the way of the | 937 | /* |
| 934 | * default mmap base, as well as whatever program they | 938 | * This logic is run once for the first LOAD Program |
| 935 | * might try to exec. This is because the brk will | 939 | * Header for ET_DYN binaries to calculate the |
| 936 | * follow the loader, and is not movable. */ | 940 | * randomization (load_bias) for all the LOAD |
| 937 | load_bias = ELF_ET_DYN_BASE - vaddr; | 941 | * Program Headers, and to calculate the entire |
| 938 | if (current->flags & PF_RANDOMIZE) | 942 | * size of the ELF mapping (total_size). (Note that |
| 939 | load_bias += arch_mmap_rnd(); | 943 | * load_addr_set is set to true later once the |
| 940 | load_bias = ELF_PAGESTART(load_bias); | 944 | * initial mapping is performed.) |
| 945 | * | ||
| 946 | * There are effectively two types of ET_DYN | ||
| 947 | * binaries: programs (i.e. PIE: ET_DYN with INTERP) | ||
| 948 | * and loaders (ET_DYN without INTERP, since they | ||
| 949 | * _are_ the ELF interpreter). The loaders must | ||
| 950 | * be loaded away from programs since the program | ||
| 951 | * may otherwise collide with the loader (especially | ||
| 952 | * for ET_EXEC which does not have a randomized | ||
| 953 | * position). For example to handle invocations of | ||
| 954 | * "./ld.so someprog" to test out a new version of | ||
| 955 | * the loader, the subsequent program that the | ||
| 956 | * loader loads must avoid the loader itself, so | ||
| 957 | * they cannot share the same load range. Sufficient | ||
| 958 | * room for the brk must be allocated with the | ||
| 959 | * loader as well, since brk must be available with | ||
| 960 | * the loader. | ||
| 961 | * | ||
| 962 | * Therefore, programs are loaded offset from | ||
| 963 | * ELF_ET_DYN_BASE and loaders are loaded into the | ||
| 964 | * independently randomized mmap region (0 load_bias | ||
| 965 | * without MAP_FIXED). | ||
| 966 | */ | ||
| 967 | if (elf_interpreter) { | ||
| 968 | load_bias = ELF_ET_DYN_BASE; | ||
| 969 | if (current->flags & PF_RANDOMIZE) | ||
| 970 | load_bias += arch_mmap_rnd(); | ||
| 971 | elf_flags |= MAP_FIXED; | ||
| 972 | } else | ||
| 973 | load_bias = 0; | ||
| 974 | |||
| 975 | /* | ||
| 976 | * Since load_bias is used for all subsequent loading | ||
| 977 | * calculations, we must lower it by the first vaddr | ||
| 978 | * so that the remaining calculations based on the | ||
| 979 | * ELF vaddrs will be correctly offset. The result | ||
| 980 | * is then page aligned. | ||
| 981 | */ | ||
| 982 | load_bias = ELF_PAGESTART(load_bias - vaddr); | ||
| 983 | |||
| 941 | total_size = total_mapping_size(elf_phdata, | 984 | total_size = total_mapping_size(elf_phdata, |
| 942 | loc->elf_ex.e_phnum); | 985 | loc->elf_ex.e_phnum); |
| 943 | if (!total_size) { | 986 | if (!total_size) { |
