diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index bdb201230bae..41e04183e4ce 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -377,6 +377,11 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, | |||
377 | } else | 377 | } else |
378 | map_addr = vm_mmap(filep, addr, size, prot, type, off); | 378 | map_addr = vm_mmap(filep, addr, size, prot, type, off); |
379 | 379 | ||
380 | if ((type & MAP_FIXED_NOREPLACE) && BAD_ADDR(map_addr)) | ||
381 | pr_info("%d (%s): Uhuuh, elf segment at %p requested but the memory is mapped already\n", | ||
382 | task_pid_nr(current), current->comm, | ||
383 | (void *)addr); | ||
384 | |||
380 | return(map_addr); | 385 | return(map_addr); |
381 | } | 386 | } |
382 | 387 | ||
@@ -575,7 +580,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
575 | elf_prot |= PROT_EXEC; | 580 | elf_prot |= PROT_EXEC; |
576 | vaddr = eppnt->p_vaddr; | 581 | vaddr = eppnt->p_vaddr; |
577 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 582 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
578 | elf_type |= MAP_FIXED; | 583 | elf_type |= MAP_FIXED_NOREPLACE; |
579 | else if (no_base && interp_elf_ex->e_type == ET_DYN) | 584 | else if (no_base && interp_elf_ex->e_type == ET_DYN) |
580 | load_addr = -vaddr; | 585 | load_addr = -vaddr; |
581 | 586 | ||
@@ -890,7 +895,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
890 | the correct location in memory. */ | 895 | the correct location in memory. */ |
891 | for(i = 0, elf_ppnt = elf_phdata; | 896 | for(i = 0, elf_ppnt = elf_phdata; |
892 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 897 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { |
893 | int elf_prot = 0, elf_flags; | 898 | int elf_prot = 0, elf_flags, elf_fixed = MAP_FIXED_NOREPLACE; |
894 | unsigned long k, vaddr; | 899 | unsigned long k, vaddr; |
895 | unsigned long total_size = 0; | 900 | unsigned long total_size = 0; |
896 | 901 | ||
@@ -922,6 +927,13 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
922 | */ | 927 | */ |
923 | } | 928 | } |
924 | } | 929 | } |
930 | |||
931 | /* | ||
932 | * Some binaries have overlapping elf segments and then | ||
933 | * we have to forcefully map over an existing mapping | ||
934 | * e.g. over this newly established brk mapping. | ||
935 | */ | ||
936 | elf_fixed = MAP_FIXED; | ||
925 | } | 937 | } |
926 | 938 | ||
927 | if (elf_ppnt->p_flags & PF_R) | 939 | if (elf_ppnt->p_flags & PF_R) |
@@ -939,7 +951,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
939 | * the ET_DYN load_addr calculations, proceed normally. | 951 | * the ET_DYN load_addr calculations, proceed normally. |
940 | */ | 952 | */ |
941 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { | 953 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { |
942 | elf_flags |= MAP_FIXED; | 954 | elf_flags |= elf_fixed; |
943 | } else if (loc->elf_ex.e_type == ET_DYN) { | 955 | } else if (loc->elf_ex.e_type == ET_DYN) { |
944 | /* | 956 | /* |
945 | * This logic is run once for the first LOAD Program | 957 | * This logic is run once for the first LOAD Program |
@@ -975,7 +987,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
975 | load_bias = ELF_ET_DYN_BASE; | 987 | load_bias = ELF_ET_DYN_BASE; |
976 | if (current->flags & PF_RANDOMIZE) | 988 | if (current->flags & PF_RANDOMIZE) |
977 | load_bias += arch_mmap_rnd(); | 989 | load_bias += arch_mmap_rnd(); |
978 | elf_flags |= MAP_FIXED; | 990 | elf_flags |= elf_fixed; |
979 | } else | 991 | } else |
980 | load_bias = 0; | 992 | load_bias = 0; |
981 | 993 | ||
@@ -1155,6 +1167,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
1155 | ELF_PLAT_INIT(regs, reloc_func_desc); | 1167 | ELF_PLAT_INIT(regs, reloc_func_desc); |
1156 | #endif | 1168 | #endif |
1157 | 1169 | ||
1170 | finalize_exec(bprm); | ||
1158 | start_thread(regs, elf_entry, bprm->p); | 1171 | start_thread(regs, elf_entry, bprm->p); |
1159 | retval = 0; | 1172 | retval = 0; |
1160 | out: | 1173 | out: |
@@ -1234,7 +1247,7 @@ static int load_elf_library(struct file *file) | |||
1234 | (eppnt->p_filesz + | 1247 | (eppnt->p_filesz + |
1235 | ELF_PAGEOFFSET(eppnt->p_vaddr)), | 1248 | ELF_PAGEOFFSET(eppnt->p_vaddr)), |
1236 | PROT_READ | PROT_WRITE | PROT_EXEC, | 1249 | PROT_READ | PROT_WRITE | PROT_EXEC, |
1237 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, | 1250 | MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_DENYWRITE, |
1238 | (eppnt->p_offset - | 1251 | (eppnt->p_offset - |
1239 | ELF_PAGEOFFSET(eppnt->p_vaddr))); | 1252 | ELF_PAGEOFFSET(eppnt->p_vaddr))); |
1240 | if (error != ELF_PAGESTART(eppnt->p_vaddr)) | 1253 | if (error != ELF_PAGESTART(eppnt->p_vaddr)) |