diff options
Diffstat (limited to 'fs/binfmt_elf_fdpic.c')
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 236 |
1 files changed, 143 insertions, 93 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 38502c67987c..2c5f9a0e5d72 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/elf.h> | 34 | #include <linux/elf.h> |
35 | #include <linux/elf-fdpic.h> | 35 | #include <linux/elf-fdpic.h> |
36 | #include <linux/elfcore.h> | 36 | #include <linux/elfcore.h> |
37 | #include <linux/coredump.h> | ||
37 | 38 | ||
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
39 | #include <asm/param.h> | 40 | #include <asm/param.h> |
@@ -75,14 +76,14 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *, | |||
75 | static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *, | 76 | static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *, |
76 | struct file *, struct mm_struct *); | 77 | struct file *, struct mm_struct *); |
77 | 78 | ||
78 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 79 | #ifdef CONFIG_ELF_CORE |
79 | static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit); | 80 | static int elf_fdpic_core_dump(struct coredump_params *cprm); |
80 | #endif | 81 | #endif |
81 | 82 | ||
82 | static struct linux_binfmt elf_fdpic_format = { | 83 | static struct linux_binfmt elf_fdpic_format = { |
83 | .module = THIS_MODULE, | 84 | .module = THIS_MODULE, |
84 | .load_binary = load_elf_fdpic_binary, | 85 | .load_binary = load_elf_fdpic_binary, |
85 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 86 | #ifdef CONFIG_ELF_CORE |
86 | .core_dump = elf_fdpic_core_dump, | 87 | .core_dump = elf_fdpic_core_dump, |
87 | #endif | 88 | #endif |
88 | .min_coredump = ELF_EXEC_PAGESIZE, | 89 | .min_coredump = ELF_EXEC_PAGESIZE, |
@@ -171,6 +172,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
171 | #ifdef ELF_FDPIC_PLAT_INIT | 172 | #ifdef ELF_FDPIC_PLAT_INIT |
172 | unsigned long dynaddr; | 173 | unsigned long dynaddr; |
173 | #endif | 174 | #endif |
175 | #ifndef CONFIG_MMU | ||
176 | unsigned long stack_prot; | ||
177 | #endif | ||
174 | struct file *interpreter = NULL; /* to shut gcc up */ | 178 | struct file *interpreter = NULL; /* to shut gcc up */ |
175 | char *interpreter_name = NULL; | 179 | char *interpreter_name = NULL; |
176 | int executable_stack; | 180 | int executable_stack; |
@@ -316,6 +320,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
316 | * defunct, deceased, etc. after this point we have to exit via | 320 | * defunct, deceased, etc. after this point we have to exit via |
317 | * error_kill */ | 321 | * error_kill */ |
318 | set_personality(PER_LINUX_FDPIC); | 322 | set_personality(PER_LINUX_FDPIC); |
323 | if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) | ||
324 | current->personality |= READ_IMPLIES_EXEC; | ||
325 | |||
326 | setup_new_exec(bprm); | ||
327 | |||
319 | set_binfmt(&elf_fdpic_format); | 328 | set_binfmt(&elf_fdpic_format); |
320 | 329 | ||
321 | current->mm->start_code = 0; | 330 | current->mm->start_code = 0; |
@@ -377,10 +386,15 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
377 | if (stack_size < PAGE_SIZE * 2) | 386 | if (stack_size < PAGE_SIZE * 2) |
378 | stack_size = PAGE_SIZE * 2; | 387 | stack_size = PAGE_SIZE * 2; |
379 | 388 | ||
389 | stack_prot = PROT_READ | PROT_WRITE; | ||
390 | if (executable_stack == EXSTACK_ENABLE_X || | ||
391 | (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) | ||
392 | stack_prot |= PROT_EXEC; | ||
393 | |||
380 | down_write(¤t->mm->mmap_sem); | 394 | down_write(¤t->mm->mmap_sem); |
381 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, | 395 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot, |
382 | PROT_READ | PROT_WRITE | PROT_EXEC, | 396 | MAP_PRIVATE | MAP_ANONYMOUS | |
383 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, | 397 | MAP_UNINITIALIZED | MAP_GROWSDOWN, |
384 | 0); | 398 | 0); |
385 | 399 | ||
386 | if (IS_ERR_VALUE(current->mm->start_brk)) { | 400 | if (IS_ERR_VALUE(current->mm->start_brk)) { |
@@ -991,15 +1005,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( | |||
991 | } | 1005 | } |
992 | } else if (!mm->start_data) { | 1006 | } else if (!mm->start_data) { |
993 | mm->start_data = seg->addr; | 1007 | mm->start_data = seg->addr; |
994 | #ifndef CONFIG_MMU | ||
995 | mm->end_data = seg->addr + phdr->p_memsz; | 1008 | mm->end_data = seg->addr + phdr->p_memsz; |
996 | #endif | ||
997 | } | 1009 | } |
998 | |||
999 | #ifdef CONFIG_MMU | ||
1000 | if (seg->addr + phdr->p_memsz > mm->end_data) | ||
1001 | mm->end_data = seg->addr + phdr->p_memsz; | ||
1002 | #endif | ||
1003 | } | 1010 | } |
1004 | 1011 | ||
1005 | seg++; | 1012 | seg++; |
@@ -1200,27 +1207,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, | |||
1200 | * | 1207 | * |
1201 | * Modelled on fs/binfmt_elf.c core dumper | 1208 | * Modelled on fs/binfmt_elf.c core dumper |
1202 | */ | 1209 | */ |
1203 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 1210 | #ifdef CONFIG_ELF_CORE |
1204 | |||
1205 | /* | ||
1206 | * These are the only things you should do on a core-file: use only these | ||
1207 | * functions to write out all the necessary info. | ||
1208 | */ | ||
1209 | static int dump_write(struct file *file, const void *addr, int nr) | ||
1210 | { | ||
1211 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | ||
1212 | } | ||
1213 | |||
1214 | static int dump_seek(struct file *file, loff_t off) | ||
1215 | { | ||
1216 | if (file->f_op->llseek) { | ||
1217 | if (file->f_op->llseek(file, off, SEEK_SET) != off) | ||
1218 | return 0; | ||
1219 | } else { | ||
1220 | file->f_pos = off; | ||
1221 | } | ||
1222 | return 1; | ||
1223 | } | ||
1224 | 1211 | ||
1225 | /* | 1212 | /* |
1226 | * Decide whether a segment is worth dumping; default is yes to be | 1213 | * Decide whether a segment is worth dumping; default is yes to be |
@@ -1300,34 +1287,35 @@ static int notesize(struct memelfnote *en) | |||
1300 | 1287 | ||
1301 | /* #define DEBUG */ | 1288 | /* #define DEBUG */ |
1302 | 1289 | ||
1303 | #define DUMP_WRITE(addr, nr) \ | 1290 | #define DUMP_WRITE(addr, nr, foffset) \ |
1304 | do { if (!dump_write(file, (addr), (nr))) return 0; } while(0) | 1291 | do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0) |
1305 | #define DUMP_SEEK(off) \ | ||
1306 | do { if (!dump_seek(file, (off))) return 0; } while(0) | ||
1307 | 1292 | ||
1308 | static int writenote(struct memelfnote *men, struct file *file) | 1293 | static int alignfile(struct file *file, loff_t *foffset) |
1309 | { | 1294 | { |
1310 | struct elf_note en; | 1295 | static const char buf[4] = { 0, }; |
1296 | DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset); | ||
1297 | return 1; | ||
1298 | } | ||
1311 | 1299 | ||
1300 | static int writenote(struct memelfnote *men, struct file *file, | ||
1301 | loff_t *foffset) | ||
1302 | { | ||
1303 | struct elf_note en; | ||
1312 | en.n_namesz = strlen(men->name) + 1; | 1304 | en.n_namesz = strlen(men->name) + 1; |
1313 | en.n_descsz = men->datasz; | 1305 | en.n_descsz = men->datasz; |
1314 | en.n_type = men->type; | 1306 | en.n_type = men->type; |
1315 | 1307 | ||
1316 | DUMP_WRITE(&en, sizeof(en)); | 1308 | DUMP_WRITE(&en, sizeof(en), foffset); |
1317 | DUMP_WRITE(men->name, en.n_namesz); | 1309 | DUMP_WRITE(men->name, en.n_namesz, foffset); |
1318 | /* XXX - cast from long long to long to avoid need for libgcc.a */ | 1310 | if (!alignfile(file, foffset)) |
1319 | DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ | 1311 | return 0; |
1320 | DUMP_WRITE(men->data, men->datasz); | 1312 | DUMP_WRITE(men->data, men->datasz, foffset); |
1321 | DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ | 1313 | if (!alignfile(file, foffset)) |
1314 | return 0; | ||
1322 | 1315 | ||
1323 | return 1; | 1316 | return 1; |
1324 | } | 1317 | } |
1325 | #undef DUMP_WRITE | 1318 | #undef DUMP_WRITE |
1326 | #undef DUMP_SEEK | ||
1327 | |||
1328 | #define DUMP_WRITE(addr, nr) \ | ||
1329 | if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ | ||
1330 | goto end_coredump; | ||
1331 | 1319 | ||
1332 | static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) | 1320 | static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) |
1333 | { | 1321 | { |
@@ -1379,7 +1367,7 @@ static inline void fill_note(struct memelfnote *note, const char *name, int type | |||
1379 | 1367 | ||
1380 | /* | 1368 | /* |
1381 | * fill up all the fields in prstatus from the given task struct, except | 1369 | * fill up all the fields in prstatus from the given task struct, except |
1382 | * registers which need to be filled up seperately. | 1370 | * registers which need to be filled up separately. |
1383 | */ | 1371 | */ |
1384 | static void fill_prstatus(struct elf_prstatus *prstatus, | 1372 | static void fill_prstatus(struct elf_prstatus *prstatus, |
1385 | struct task_struct *p, long signr) | 1373 | struct task_struct *p, long signr) |
@@ -1510,6 +1498,22 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1510 | return sz; | 1498 | return sz; |
1511 | } | 1499 | } |
1512 | 1500 | ||
1501 | static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, | ||
1502 | elf_addr_t e_shoff, int segs) | ||
1503 | { | ||
1504 | elf->e_shoff = e_shoff; | ||
1505 | elf->e_shentsize = sizeof(*shdr4extnum); | ||
1506 | elf->e_shnum = 1; | ||
1507 | elf->e_shstrndx = SHN_UNDEF; | ||
1508 | |||
1509 | memset(shdr4extnum, 0, sizeof(*shdr4extnum)); | ||
1510 | |||
1511 | shdr4extnum->sh_type = SHT_NULL; | ||
1512 | shdr4extnum->sh_size = elf->e_shnum; | ||
1513 | shdr4extnum->sh_link = elf->e_shstrndx; | ||
1514 | shdr4extnum->sh_info = segs; | ||
1515 | } | ||
1516 | |||
1513 | /* | 1517 | /* |
1514 | * dump the segments for an MMU process | 1518 | * dump the segments for an MMU process |
1515 | */ | 1519 | */ |
@@ -1538,7 +1542,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size, | |||
1538 | err = -EIO; | 1542 | err = -EIO; |
1539 | kunmap(page); | 1543 | kunmap(page); |
1540 | page_cache_release(page); | 1544 | page_cache_release(page); |
1541 | } else if (!dump_seek(file, file->f_pos + PAGE_SIZE)) | 1545 | } else if (!dump_seek(file, PAGE_SIZE)) |
1542 | err = -EFBIG; | 1546 | err = -EFBIG; |
1543 | if (err) | 1547 | if (err) |
1544 | goto out; | 1548 | goto out; |
@@ -1574,6 +1578,17 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size, | |||
1574 | } | 1578 | } |
1575 | #endif | 1579 | #endif |
1576 | 1580 | ||
1581 | static size_t elf_core_vma_data_size(unsigned long mm_flags) | ||
1582 | { | ||
1583 | struct vm_area_struct *vma; | ||
1584 | size_t size = 0; | ||
1585 | |||
1586 | for (vma = current->mm->mmap; vma; vma = vma->vm_next) | ||
1587 | if (maydump(vma, mm_flags)) | ||
1588 | size += vma->vm_end - vma->vm_start; | ||
1589 | return size; | ||
1590 | } | ||
1591 | |||
1577 | /* | 1592 | /* |
1578 | * Actual dumper | 1593 | * Actual dumper |
1579 | * | 1594 | * |
@@ -1581,8 +1596,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size, | |||
1581 | * and then they are actually written out. If we run out of core limit | 1596 | * and then they are actually written out. If we run out of core limit |
1582 | * we just truncate. | 1597 | * we just truncate. |
1583 | */ | 1598 | */ |
1584 | static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | 1599 | static int elf_fdpic_core_dump(struct coredump_params *cprm) |
1585 | struct file *file, unsigned long limit) | ||
1586 | { | 1600 | { |
1587 | #define NUM_NOTES 6 | 1601 | #define NUM_NOTES 6 |
1588 | int has_dumped = 0; | 1602 | int has_dumped = 0; |
@@ -1592,7 +1606,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1592 | int i; | 1606 | int i; |
1593 | struct vm_area_struct *vma; | 1607 | struct vm_area_struct *vma; |
1594 | struct elfhdr *elf = NULL; | 1608 | struct elfhdr *elf = NULL; |
1595 | loff_t offset = 0, dataoff; | 1609 | loff_t offset = 0, dataoff, foffset; |
1596 | int numnote; | 1610 | int numnote; |
1597 | struct memelfnote *notes = NULL; | 1611 | struct memelfnote *notes = NULL; |
1598 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ | 1612 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ |
@@ -1605,7 +1619,10 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1605 | #endif | 1619 | #endif |
1606 | int thread_status_size = 0; | 1620 | int thread_status_size = 0; |
1607 | elf_addr_t *auxv; | 1621 | elf_addr_t *auxv; |
1608 | unsigned long mm_flags; | 1622 | struct elf_phdr *phdr4note = NULL; |
1623 | struct elf_shdr *shdr4extnum = NULL; | ||
1624 | Elf_Half e_phnum; | ||
1625 | elf_addr_t e_shoff; | ||
1609 | 1626 | ||
1610 | /* | 1627 | /* |
1611 | * We no longer stop all VM operations. | 1628 | * We no longer stop all VM operations. |
@@ -1641,7 +1658,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1641 | goto cleanup; | 1658 | goto cleanup; |
1642 | #endif | 1659 | #endif |
1643 | 1660 | ||
1644 | if (signr) { | 1661 | if (cprm->signr) { |
1645 | struct core_thread *ct; | 1662 | struct core_thread *ct; |
1646 | struct elf_thread_status *tmp; | 1663 | struct elf_thread_status *tmp; |
1647 | 1664 | ||
@@ -1660,22 +1677,28 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1660 | int sz; | 1677 | int sz; |
1661 | 1678 | ||
1662 | tmp = list_entry(t, struct elf_thread_status, list); | 1679 | tmp = list_entry(t, struct elf_thread_status, list); |
1663 | sz = elf_dump_thread_status(signr, tmp); | 1680 | sz = elf_dump_thread_status(cprm->signr, tmp); |
1664 | thread_status_size += sz; | 1681 | thread_status_size += sz; |
1665 | } | 1682 | } |
1666 | } | 1683 | } |
1667 | 1684 | ||
1668 | /* now collect the dump for the current */ | 1685 | /* now collect the dump for the current */ |
1669 | fill_prstatus(prstatus, current, signr); | 1686 | fill_prstatus(prstatus, current, cprm->signr); |
1670 | elf_core_copy_regs(&prstatus->pr_reg, regs); | 1687 | elf_core_copy_regs(&prstatus->pr_reg, cprm->regs); |
1671 | 1688 | ||
1672 | segs = current->mm->map_count; | 1689 | segs = current->mm->map_count; |
1673 | #ifdef ELF_CORE_EXTRA_PHDRS | 1690 | segs += elf_core_extra_phdrs(); |
1674 | segs += ELF_CORE_EXTRA_PHDRS; | 1691 | |
1675 | #endif | 1692 | /* for notes section */ |
1693 | segs++; | ||
1694 | |||
1695 | /* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid | ||
1696 | * this, kernel supports extended numbering. Have a look at | ||
1697 | * include/linux/elf.h for further information. */ | ||
1698 | e_phnum = segs > PN_XNUM ? PN_XNUM : segs; | ||
1676 | 1699 | ||
1677 | /* Set up header */ | 1700 | /* Set up header */ |
1678 | fill_elf_fdpic_header(elf, segs + 1); /* including notes section */ | 1701 | fill_elf_fdpic_header(elf, e_phnum); |
1679 | 1702 | ||
1680 | has_dumped = 1; | 1703 | has_dumped = 1; |
1681 | current->flags |= PF_DUMPCORE; | 1704 | current->flags |= PF_DUMPCORE; |
@@ -1702,7 +1725,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1702 | 1725 | ||
1703 | /* Try to dump the FPU. */ | 1726 | /* Try to dump the FPU. */ |
1704 | if ((prstatus->pr_fpvalid = | 1727 | if ((prstatus->pr_fpvalid = |
1705 | elf_core_copy_task_fpregs(current, regs, fpu))) | 1728 | elf_core_copy_task_fpregs(current, cprm->regs, fpu))) |
1706 | fill_note(notes + numnote++, | 1729 | fill_note(notes + numnote++, |
1707 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); | 1730 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); |
1708 | #ifdef ELF_CORE_COPY_XFPREGS | 1731 | #ifdef ELF_CORE_COPY_XFPREGS |
@@ -1714,13 +1737,12 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1714 | fs = get_fs(); | 1737 | fs = get_fs(); |
1715 | set_fs(KERNEL_DS); | 1738 | set_fs(KERNEL_DS); |
1716 | 1739 | ||
1717 | DUMP_WRITE(elf, sizeof(*elf)); | ||
1718 | offset += sizeof(*elf); /* Elf header */ | 1740 | offset += sizeof(*elf); /* Elf header */ |
1719 | offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ | 1741 | offset += segs * sizeof(struct elf_phdr); /* Program headers */ |
1742 | foffset = offset; | ||
1720 | 1743 | ||
1721 | /* Write notes phdr entry */ | 1744 | /* Write notes phdr entry */ |
1722 | { | 1745 | { |
1723 | struct elf_phdr phdr; | ||
1724 | int sz = 0; | 1746 | int sz = 0; |
1725 | 1747 | ||
1726 | for (i = 0; i < numnote; i++) | 1748 | for (i = 0; i < numnote; i++) |
@@ -1728,20 +1750,38 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1728 | 1750 | ||
1729 | sz += thread_status_size; | 1751 | sz += thread_status_size; |
1730 | 1752 | ||
1731 | fill_elf_note_phdr(&phdr, sz, offset); | 1753 | phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); |
1754 | if (!phdr4note) | ||
1755 | goto end_coredump; | ||
1756 | |||
1757 | fill_elf_note_phdr(phdr4note, sz, offset); | ||
1732 | offset += sz; | 1758 | offset += sz; |
1733 | DUMP_WRITE(&phdr, sizeof(phdr)); | ||
1734 | } | 1759 | } |
1735 | 1760 | ||
1736 | /* Page-align dumped data */ | 1761 | /* Page-align dumped data */ |
1737 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 1762 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
1738 | 1763 | ||
1739 | /* | 1764 | offset += elf_core_vma_data_size(cprm->mm_flags); |
1740 | * We must use the same mm->flags while dumping core to avoid | 1765 | offset += elf_core_extra_data_size(); |
1741 | * inconsistency between the program headers and bodies, otherwise an | 1766 | e_shoff = offset; |
1742 | * unusable core file can be generated. | 1767 | |
1743 | */ | 1768 | if (e_phnum == PN_XNUM) { |
1744 | mm_flags = current->mm->flags; | 1769 | shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); |
1770 | if (!shdr4extnum) | ||
1771 | goto end_coredump; | ||
1772 | fill_extnum_info(elf, shdr4extnum, e_shoff, segs); | ||
1773 | } | ||
1774 | |||
1775 | offset = dataoff; | ||
1776 | |||
1777 | size += sizeof(*elf); | ||
1778 | if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf))) | ||
1779 | goto end_coredump; | ||
1780 | |||
1781 | size += sizeof(*phdr4note); | ||
1782 | if (size > cprm->limit | ||
1783 | || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note))) | ||
1784 | goto end_coredump; | ||
1745 | 1785 | ||
1746 | /* write program headers for segments dump */ | 1786 | /* write program headers for segments dump */ |
1747 | for (vma = current->mm->mmap; vma; vma = vma->vm_next) { | 1787 | for (vma = current->mm->mmap; vma; vma = vma->vm_next) { |
@@ -1754,7 +1794,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1754 | phdr.p_offset = offset; | 1794 | phdr.p_offset = offset; |
1755 | phdr.p_vaddr = vma->vm_start; | 1795 | phdr.p_vaddr = vma->vm_start; |
1756 | phdr.p_paddr = 0; | 1796 | phdr.p_paddr = 0; |
1757 | phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0; | 1797 | phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0; |
1758 | phdr.p_memsz = sz; | 1798 | phdr.p_memsz = sz; |
1759 | offset += phdr.p_filesz; | 1799 | offset += phdr.p_filesz; |
1760 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1800 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
@@ -1764,16 +1804,18 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1764 | phdr.p_flags |= PF_X; | 1804 | phdr.p_flags |= PF_X; |
1765 | phdr.p_align = ELF_EXEC_PAGESIZE; | 1805 | phdr.p_align = ELF_EXEC_PAGESIZE; |
1766 | 1806 | ||
1767 | DUMP_WRITE(&phdr, sizeof(phdr)); | 1807 | size += sizeof(phdr); |
1808 | if (size > cprm->limit | ||
1809 | || !dump_write(cprm->file, &phdr, sizeof(phdr))) | ||
1810 | goto end_coredump; | ||
1768 | } | 1811 | } |
1769 | 1812 | ||
1770 | #ifdef ELF_CORE_WRITE_EXTRA_PHDRS | 1813 | if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit)) |
1771 | ELF_CORE_WRITE_EXTRA_PHDRS; | 1814 | goto end_coredump; |
1772 | #endif | ||
1773 | 1815 | ||
1774 | /* write out the notes section */ | 1816 | /* write out the notes section */ |
1775 | for (i = 0; i < numnote; i++) | 1817 | for (i = 0; i < numnote; i++) |
1776 | if (!writenote(notes + i, file)) | 1818 | if (!writenote(notes + i, cprm->file, &foffset)) |
1777 | goto end_coredump; | 1819 | goto end_coredump; |
1778 | 1820 | ||
1779 | /* write out the thread status notes section */ | 1821 | /* write out the thread status notes section */ |
@@ -1782,25 +1824,33 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1782 | list_entry(t, struct elf_thread_status, list); | 1824 | list_entry(t, struct elf_thread_status, list); |
1783 | 1825 | ||
1784 | for (i = 0; i < tmp->num_notes; i++) | 1826 | for (i = 0; i < tmp->num_notes; i++) |
1785 | if (!writenote(&tmp->notes[i], file)) | 1827 | if (!writenote(&tmp->notes[i], cprm->file, &foffset)) |
1786 | goto end_coredump; | 1828 | goto end_coredump; |
1787 | } | 1829 | } |
1788 | 1830 | ||
1789 | if (!dump_seek(file, dataoff)) | 1831 | if (!dump_seek(cprm->file, dataoff - foffset)) |
1790 | goto end_coredump; | 1832 | goto end_coredump; |
1791 | 1833 | ||
1792 | if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0) | 1834 | if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, |
1835 | cprm->mm_flags) < 0) | ||
1793 | goto end_coredump; | 1836 | goto end_coredump; |
1794 | 1837 | ||
1795 | #ifdef ELF_CORE_WRITE_EXTRA_DATA | 1838 | if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) |
1796 | ELF_CORE_WRITE_EXTRA_DATA; | 1839 | goto end_coredump; |
1797 | #endif | ||
1798 | 1840 | ||
1799 | if (file->f_pos != offset) { | 1841 | if (e_phnum == PN_XNUM) { |
1842 | size += sizeof(*shdr4extnum); | ||
1843 | if (size > cprm->limit | ||
1844 | || !dump_write(cprm->file, shdr4extnum, | ||
1845 | sizeof(*shdr4extnum))) | ||
1846 | goto end_coredump; | ||
1847 | } | ||
1848 | |||
1849 | if (cprm->file->f_pos != offset) { | ||
1800 | /* Sanity check */ | 1850 | /* Sanity check */ |
1801 | printk(KERN_WARNING | 1851 | printk(KERN_WARNING |
1802 | "elf_core_dump: file->f_pos (%lld) != offset (%lld)\n", | 1852 | "elf_core_dump: file->f_pos (%lld) != offset (%lld)\n", |
1803 | file->f_pos, offset); | 1853 | cprm->file->f_pos, offset); |
1804 | } | 1854 | } |
1805 | 1855 | ||
1806 | end_coredump: | 1856 | end_coredump: |
@@ -1812,7 +1862,7 @@ cleanup: | |||
1812 | list_del(tmp); | 1862 | list_del(tmp); |
1813 | kfree(list_entry(tmp, struct elf_thread_status, list)); | 1863 | kfree(list_entry(tmp, struct elf_thread_status, list)); |
1814 | } | 1864 | } |
1815 | 1865 | kfree(phdr4note); | |
1816 | kfree(elf); | 1866 | kfree(elf); |
1817 | kfree(prstatus); | 1867 | kfree(prstatus); |
1818 | kfree(psinfo); | 1868 | kfree(psinfo); |
@@ -1825,4 +1875,4 @@ cleanup: | |||
1825 | #undef NUM_NOTES | 1875 | #undef NUM_NOTES |
1826 | } | 1876 | } |
1827 | 1877 | ||
1828 | #endif /* USE_ELF_CORE_DUMP */ | 1878 | #endif /* CONFIG_ELF_CORE */ |