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.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index bcb884e2d613..48ffb3dc610a 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 *);
@@ -712,7 +713,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
712 goto out_free_dentry; 713 goto out_free_dentry;
713 714
714 /* OK, This is the point of no return */ 715 /* OK, This is the point of no return */
715 current->flags &= ~PF_FORKNOEXEC;
716 current->mm->def_flags = def_flags; 716 current->mm->def_flags = def_flags;
717 717
718 /* Do this immediately, since STACK_TOP as used in setup_arg_pages 718 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
@@ -934,7 +934,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
934#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ 934#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
935 935
936 install_exec_creds(bprm); 936 install_exec_creds(bprm);
937 current->flags &= ~PF_FORKNOEXEC;
938 retval = create_elf_tables(bprm, &loc->elf_ex, 937 retval = create_elf_tables(bprm, &loc->elf_ex,
939 load_addr, interp_load_addr); 938 load_addr, interp_load_addr);
940 if (retval < 0) { 939 if (retval < 0) {
@@ -1095,6 +1094,29 @@ out:
1095 */ 1094 */
1096 1095
1097/* 1096/*
1097 * The purpose of always_dump_vma() is to make sure that special kernel mappings
1098 * that are useful for post-mortem analysis are included in every core dump.
1099 * In that way we ensure that the core dump is fully interpretable later
1100 * without matching up the same kernel and hardware config to see what PC values
1101 * meant. These special mappings include - vDSO, vsyscall, and other
1102 * architecture specific mappings
1103 */
1104static bool always_dump_vma(struct vm_area_struct *vma)
1105{
1106 /* Any vsyscall mappings? */
1107 if (vma == get_gate_vma(vma->vm_mm))
1108 return true;
1109 /*
1110 * arch_vma_name() returns non-NULL for special architecture mappings,
1111 * such as vDSO sections.
1112 */
1113 if (arch_vma_name(vma))
1114 return true;
1115
1116 return false;
1117}
1118
1119/*
1098 * Decide what to dump of a segment, part, all or none. 1120 * Decide what to dump of a segment, part, all or none.
1099 */ 1121 */
1100static unsigned long vma_dump_size(struct vm_area_struct *vma, 1122static unsigned long vma_dump_size(struct vm_area_struct *vma,
@@ -1102,10 +1124,13 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
1102{ 1124{
1103#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type)) 1125#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
1104 1126
1105 /* The vma can be set up to tell us the answer directly. */ 1127 /* always dump the vdso and vsyscall sections */
1106 if (vma->vm_flags & VM_ALWAYSDUMP) 1128 if (always_dump_vma(vma))
1107 goto whole; 1129 goto whole;
1108 1130
1131 if (vma->vm_flags & VM_NODUMP)
1132 return 0;
1133
1109 /* Hugetlb memory check */ 1134 /* Hugetlb memory check */
1110 if (vma->vm_flags & VM_HUGETLB) { 1135 if (vma->vm_flags & VM_HUGETLB) {
1111 if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED)) 1136 if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED))
@@ -1390,6 +1415,22 @@ static void do_thread_regset_writeback(struct task_struct *task,
1390 regset->writeback(task, regset, 1); 1415 regset->writeback(task, regset, 1);
1391} 1416}
1392 1417
1418#ifndef PR_REG_SIZE
1419#define PR_REG_SIZE(S) sizeof(S)
1420#endif
1421
1422#ifndef PRSTATUS_SIZE
1423#define PRSTATUS_SIZE(S) sizeof(S)
1424#endif
1425
1426#ifndef PR_REG_PTR
1427#define PR_REG_PTR(S) (&((S)->pr_reg))
1428#endif
1429
1430#ifndef SET_PR_FPVALID
1431#define SET_PR_FPVALID(S, V) ((S)->pr_fpvalid = (V))
1432#endif
1433
1393static int fill_thread_core_info(struct elf_thread_core_info *t, 1434static int fill_thread_core_info(struct elf_thread_core_info *t,
1394 const struct user_regset_view *view, 1435 const struct user_regset_view *view,
1395 long signr, size_t *total) 1436 long signr, size_t *total)
@@ -1404,11 +1445,11 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
1404 */ 1445 */
1405 fill_prstatus(&t->prstatus, t->task, signr); 1446 fill_prstatus(&t->prstatus, t->task, signr);
1406 (void) view->regsets[0].get(t->task, &view->regsets[0], 1447 (void) view->regsets[0].get(t->task, &view->regsets[0],
1407 0, sizeof(t->prstatus.pr_reg), 1448 0, PR_REG_SIZE(t->prstatus.pr_reg),
1408 &t->prstatus.pr_reg, NULL); 1449 PR_REG_PTR(&t->prstatus), NULL);
1409 1450
1410 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, 1451 fill_note(&t->notes[0], "CORE", NT_PRSTATUS,
1411 sizeof(t->prstatus), &t->prstatus); 1452 PRSTATUS_SIZE(t->prstatus), &t->prstatus);
1412 *total += notesize(&t->notes[0]); 1453 *total += notesize(&t->notes[0]);
1413 1454
1414 do_thread_regset_writeback(t->task, &view->regsets[0]); 1455 do_thread_regset_writeback(t->task, &view->regsets[0]);
@@ -1421,7 +1462,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
1421 for (i = 1; i < view->n; ++i) { 1462 for (i = 1; i < view->n; ++i) {
1422 const struct user_regset *regset = &view->regsets[i]; 1463 const struct user_regset *regset = &view->regsets[i];
1423 do_thread_regset_writeback(t->task, regset); 1464 do_thread_regset_writeback(t->task, regset);
1424 if (regset->core_note_type && 1465 if (regset->core_note_type && regset->get &&
1425 (!regset->active || regset->active(t->task, regset))) { 1466 (!regset->active || regset->active(t->task, regset))) {
1426 int ret; 1467 int ret;
1427 size_t size = regset->n * regset->size; 1468 size_t size = regset->n * regset->size;
@@ -1438,7 +1479,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
1438 regset->core_note_type, 1479 regset->core_note_type,
1439 size, data); 1480 size, data);
1440 else { 1481 else {
1441 t->prstatus.pr_fpvalid = 1; 1482 SET_PR_FPVALID(&t->prstatus, 1);
1442 fill_note(&t->notes[i], "CORE", 1483 fill_note(&t->notes[i], "CORE",
1443 NT_PRFPREG, size, data); 1484 NT_PRFPREG, size, data);
1444 } 1485 }
@@ -2077,7 +2118,8 @@ out:
2077 2118
2078static int __init init_elf_binfmt(void) 2119static int __init init_elf_binfmt(void)
2079{ 2120{
2080 return register_binfmt(&elf_format); 2121 register_binfmt(&elf_format);
2122 return 0;
2081} 2123}
2082 2124
2083static void __exit exit_elf_binfmt(void) 2125static void __exit exit_elf_binfmt(void)