aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c83
1 files changed, 57 insertions, 26 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 07d096c4992..16f73541707 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -35,6 +35,7 @@
35#include <asm/uaccess.h> 35#include <asm/uaccess.h>
36#include <asm/param.h> 36#include <asm/param.h>
37#include <asm/page.h> 37#include <asm/page.h>
38#include <asm/exec.h>
38 39
39static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); 40static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
40static int load_elf_library(struct file *); 41static int load_elf_library(struct file *);
@@ -81,9 +82,7 @@ static int set_brk(unsigned long start, unsigned long end)
81 end = ELF_PAGEALIGN(end); 82 end = ELF_PAGEALIGN(end);
82 if (end > start) { 83 if (end > start) {
83 unsigned long addr; 84 unsigned long addr;
84 down_write(&current->mm->mmap_sem); 85 addr = vm_brk(start, end - start);
85 addr = do_brk(start, end - start);
86 up_write(&current->mm->mmap_sem);
87 if (BAD_ADDR(addr)) 86 if (BAD_ADDR(addr))
88 return addr; 87 return addr;
89 } 88 }
@@ -513,9 +512,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
513 elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); 512 elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
514 513
515 /* Map the last of the bss segment */ 514 /* Map the last of the bss segment */
516 down_write(&current->mm->mmap_sem); 515 error = vm_brk(elf_bss, last_bss - elf_bss);
517 error = do_brk(elf_bss, last_bss - elf_bss);
518 up_write(&current->mm->mmap_sem);
519 if (BAD_ADDR(error)) 516 if (BAD_ADDR(error))
520 goto out_close; 517 goto out_close;
521 } 518 }
@@ -712,7 +709,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
712 goto out_free_dentry; 709 goto out_free_dentry;
713 710
714 /* OK, This is the point of no return */ 711 /* OK, This is the point of no return */
715 current->flags &= ~PF_FORKNOEXEC;
716 current->mm->def_flags = def_flags; 712 current->mm->def_flags = def_flags;
717 713
718 /* Do this immediately, since STACK_TOP as used in setup_arg_pages 714 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
@@ -934,7 +930,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
934#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ 930#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
935 931
936 install_exec_creds(bprm); 932 install_exec_creds(bprm);
937 current->flags &= ~PF_FORKNOEXEC;
938 retval = create_elf_tables(bprm, &loc->elf_ex, 933 retval = create_elf_tables(bprm, &loc->elf_ex,
939 load_addr, interp_load_addr); 934 load_addr, interp_load_addr);
940 if (retval < 0) { 935 if (retval < 0) {
@@ -963,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
963 and some applications "depend" upon this behavior. 958 and some applications "depend" upon this behavior.
964 Since we do not have the power to recompile these, we 959 Since we do not have the power to recompile these, we
965 emulate the SVr4 behavior. Sigh. */ 960 emulate the SVr4 behavior. Sigh. */
966 down_write(&current->mm->mmap_sem); 961 error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
967 error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
968 MAP_FIXED | MAP_PRIVATE, 0); 962 MAP_FIXED | MAP_PRIVATE, 0);
969 up_write(&current->mm->mmap_sem);
970 } 963 }
971 964
972#ifdef ELF_PLAT_INIT 965#ifdef ELF_PLAT_INIT
@@ -1051,8 +1044,7 @@ static int load_elf_library(struct file *file)
1051 eppnt++; 1044 eppnt++;
1052 1045
1053 /* Now use mmap to map the library into memory. */ 1046 /* Now use mmap to map the library into memory. */
1054 down_write(&current->mm->mmap_sem); 1047 error = vm_mmap(file,
1055 error = do_mmap(file,
1056 ELF_PAGESTART(eppnt->p_vaddr), 1048 ELF_PAGESTART(eppnt->p_vaddr),
1057 (eppnt->p_filesz + 1049 (eppnt->p_filesz +
1058 ELF_PAGEOFFSET(eppnt->p_vaddr)), 1050 ELF_PAGEOFFSET(eppnt->p_vaddr)),
@@ -1060,7 +1052,6 @@ static int load_elf_library(struct file *file)
1060 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, 1052 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
1061 (eppnt->p_offset - 1053 (eppnt->p_offset -
1062 ELF_PAGEOFFSET(eppnt->p_vaddr))); 1054 ELF_PAGEOFFSET(eppnt->p_vaddr)));
1063 up_write(&current->mm->mmap_sem);
1064 if (error != ELF_PAGESTART(eppnt->p_vaddr)) 1055 if (error != ELF_PAGESTART(eppnt->p_vaddr))
1065 goto out_free_ph; 1056 goto out_free_ph;
1066 1057
@@ -1073,11 +1064,8 @@ static int load_elf_library(struct file *file)
1073 len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + 1064 len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
1074 ELF_MIN_ALIGN - 1); 1065 ELF_MIN_ALIGN - 1);
1075 bss = eppnt->p_memsz + eppnt->p_vaddr; 1066 bss = eppnt->p_memsz + eppnt->p_vaddr;
1076 if (bss > len) { 1067 if (bss > len)
1077 down_write(&current->mm->mmap_sem); 1068 vm_brk(len, bss - len);
1078 do_brk(len, bss - len);
1079 up_write(&current->mm->mmap_sem);
1080 }
1081 error = 0; 1069 error = 0;
1082 1070
1083out_free_ph: 1071out_free_ph:
@@ -1095,6 +1083,29 @@ out:
1095 */ 1083 */
1096 1084
1097/* 1085/*
1086 * The purpose of always_dump_vma() is to make sure that special kernel mappings
1087 * that are useful for post-mortem analysis are included in every core dump.
1088 * In that way we ensure that the core dump is fully interpretable later
1089 * without matching up the same kernel and hardware config to see what PC values
1090 * meant. These special mappings include - vDSO, vsyscall, and other
1091 * architecture specific mappings
1092 */
1093static bool always_dump_vma(struct vm_area_struct *vma)
1094{
1095 /* Any vsyscall mappings? */
1096 if (vma == get_gate_vma(vma->vm_mm))
1097 return true;
1098 /*
1099 * arch_vma_name() returns non-NULL for special architecture mappings,
1100 * such as vDSO sections.
1101 */
1102 if (arch_vma_name(vma))
1103 return true;
1104
1105 return false;
1106}
1107
1108/*
1098 * Decide what to dump of a segment, part, all or none. 1109 * Decide what to dump of a segment, part, all or none.
1099 */ 1110 */
1100static unsigned long vma_dump_size(struct vm_area_struct *vma, 1111static unsigned long vma_dump_size(struct vm_area_struct *vma,
@@ -1102,10 +1113,13 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
1102{ 1113{
1103#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type)) 1114#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
1104 1115
1105 /* The vma can be set up to tell us the answer directly. */ 1116 /* always dump the vdso and vsyscall sections */
1106 if (vma->vm_flags & VM_ALWAYSDUMP) 1117 if (always_dump_vma(vma))
1107 goto whole; 1118 goto whole;
1108 1119
1120 if (vma->vm_flags & VM_NODUMP)
1121 return 0;
1122
1109 /* Hugetlb memory check */ 1123 /* Hugetlb memory check */
1110 if (vma->vm_flags & VM_HUGETLB) { 1124 if (vma->vm_flags & VM_HUGETLB) {
1111 if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED)) 1125 if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED))
@@ -1390,6 +1404,22 @@ static void do_thread_regset_writeback(struct task_struct *task,
1390 regset->writeback(task, regset, 1); 1404 regset->writeback(task, regset, 1);
1391} 1405}
1392 1406
1407#ifndef PR_REG_SIZE
1408#define PR_REG_SIZE(S) sizeof(S)
1409#endif
1410
1411#ifndef PRSTATUS_SIZE
1412#define PRSTATUS_SIZE(S) sizeof(S)
1413#endif
1414
1415#ifndef PR_REG_PTR
1416#define PR_REG_PTR(S) (&((S)->pr_reg))
1417#endif
1418
1419#ifndef SET_PR_FPVALID
1420#define SET_PR_FPVALID(S, V) ((S)->pr_fpvalid = (V))
1421#endif
1422
1393static int fill_thread_core_info(struct elf_thread_core_info *t, 1423static int fill_thread_core_info(struct elf_thread_core_info *t,
1394 const struct user_regset_view *view, 1424 const struct user_regset_view *view,
1395 long signr, size_t *total) 1425 long signr, size_t *total)
@@ -1404,11 +1434,11 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
1404 */ 1434 */
1405 fill_prstatus(&t->prstatus, t->task, signr); 1435 fill_prstatus(&t->prstatus, t->task, signr);
1406 (void) view->regsets[0].get(t->task, &view->regsets[0], 1436 (void) view->regsets[0].get(t->task, &view->regsets[0],
1407 0, sizeof(t->prstatus.pr_reg), 1437 0, PR_REG_SIZE(t->prstatus.pr_reg),
1408 &t->prstatus.pr_reg, NULL); 1438 PR_REG_PTR(&t->prstatus), NULL);
1409 1439
1410 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, 1440 fill_note(&t->notes[0], "CORE", NT_PRSTATUS,
1411 sizeof(t->prstatus), &t->prstatus); 1441 PRSTATUS_SIZE(t->prstatus), &t->prstatus);
1412 *total += notesize(&t->notes[0]); 1442 *total += notesize(&t->notes[0]);
1413 1443
1414 do_thread_regset_writeback(t->task, &view->regsets[0]); 1444 do_thread_regset_writeback(t->task, &view->regsets[0]);
@@ -1438,7 +1468,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
1438 regset->core_note_type, 1468 regset->core_note_type,
1439 size, data); 1469 size, data);
1440 else { 1470 else {
1441 t->prstatus.pr_fpvalid = 1; 1471 SET_PR_FPVALID(&t->prstatus, 1);
1442 fill_note(&t->notes[i], "CORE", 1472 fill_note(&t->notes[i], "CORE",
1443 NT_PRFPREG, size, data); 1473 NT_PRFPREG, size, data);
1444 } 1474 }
@@ -2077,7 +2107,8 @@ out:
2077 2107
2078static int __init init_elf_binfmt(void) 2108static int __init init_elf_binfmt(void)
2079{ 2109{
2080 return register_binfmt(&elf_format); 2110 register_binfmt(&elf_format);
2111 return 0;
2081} 2112}
2082 2113
2083static void __exit exit_elf_binfmt(void) 2114static void __exit exit_elf_binfmt(void)