aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf_fdpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/binfmt_elf_fdpic.c')
-rw-r--r--fs/binfmt_elf_fdpic.c152
1 files changed, 47 insertions, 105 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index c166f325a183..fe2a643ee005 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -111,7 +111,7 @@ static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
111 return 0; 111 return 0;
112 if (!elf_check_arch(hdr) || !elf_check_fdpic(hdr)) 112 if (!elf_check_arch(hdr) || !elf_check_fdpic(hdr))
113 return 0; 113 return 0;
114 if (!file->f_op || !file->f_op->mmap) 114 if (!file->f_op->mmap)
115 return 0; 115 return 0;
116 return 1; 116 return 1;
117} 117}
@@ -1267,35 +1267,17 @@ static int notesize(struct memelfnote *en)
1267 1267
1268/* #define DEBUG */ 1268/* #define DEBUG */
1269 1269
1270#define DUMP_WRITE(addr, nr, foffset) \ 1270static int writenote(struct memelfnote *men, struct coredump_params *cprm)
1271 do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
1272
1273static int alignfile(struct file *file, loff_t *foffset)
1274{
1275 static const char buf[4] = { 0, };
1276 DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
1277 return 1;
1278}
1279
1280static int writenote(struct memelfnote *men, struct file *file,
1281 loff_t *foffset)
1282{ 1271{
1283 struct elf_note en; 1272 struct elf_note en;
1284 en.n_namesz = strlen(men->name) + 1; 1273 en.n_namesz = strlen(men->name) + 1;
1285 en.n_descsz = men->datasz; 1274 en.n_descsz = men->datasz;
1286 en.n_type = men->type; 1275 en.n_type = men->type;
1287 1276
1288 DUMP_WRITE(&en, sizeof(en), foffset); 1277 return dump_emit(cprm, &en, sizeof(en)) &&
1289 DUMP_WRITE(men->name, en.n_namesz, foffset); 1278 dump_emit(cprm, men->name, en.n_namesz) && dump_align(cprm, 4) &&
1290 if (!alignfile(file, foffset)) 1279 dump_emit(cprm, men->data, men->datasz) && dump_align(cprm, 4);
1291 return 0;
1292 DUMP_WRITE(men->data, men->datasz, foffset);
1293 if (!alignfile(file, foffset))
1294 return 0;
1295
1296 return 1;
1297} 1280}
1298#undef DUMP_WRITE
1299 1281
1300static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) 1282static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
1301{ 1283{
@@ -1500,66 +1482,40 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
1500/* 1482/*
1501 * dump the segments for an MMU process 1483 * dump the segments for an MMU process
1502 */ 1484 */
1503#ifdef CONFIG_MMU 1485static bool elf_fdpic_dump_segments(struct coredump_params *cprm)
1504static int elf_fdpic_dump_segments(struct file *file, size_t *size,
1505 unsigned long *limit, unsigned long mm_flags)
1506{ 1486{
1507 struct vm_area_struct *vma; 1487 struct vm_area_struct *vma;
1508 int err = 0;
1509 1488
1510 for (vma = current->mm->mmap; vma; vma = vma->vm_next) { 1489 for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1511 unsigned long addr; 1490 unsigned long addr;
1512 1491
1513 if (!maydump(vma, mm_flags)) 1492 if (!maydump(vma, cprm->mm_flags))
1514 continue; 1493 continue;
1515 1494
1495#ifdef CONFIG_MMU
1516 for (addr = vma->vm_start; addr < vma->vm_end; 1496 for (addr = vma->vm_start; addr < vma->vm_end;
1517 addr += PAGE_SIZE) { 1497 addr += PAGE_SIZE) {
1498 bool res;
1518 struct page *page = get_dump_page(addr); 1499 struct page *page = get_dump_page(addr);
1519 if (page) { 1500 if (page) {
1520 void *kaddr = kmap(page); 1501 void *kaddr = kmap(page);
1521 *size += PAGE_SIZE; 1502 res = dump_emit(cprm, kaddr, PAGE_SIZE);
1522 if (*size > *limit)
1523 err = -EFBIG;
1524 else if (!dump_write(file, kaddr, PAGE_SIZE))
1525 err = -EIO;
1526 kunmap(page); 1503 kunmap(page);
1527 page_cache_release(page); 1504 page_cache_release(page);
1528 } else if (!dump_seek(file, PAGE_SIZE)) 1505 } else {
1529 err = -EFBIG; 1506 res = dump_skip(cprm, PAGE_SIZE);
1530 if (err) 1507 }
1531 goto out; 1508 if (!res)
1509 return false;
1532 } 1510 }
1533 } 1511#else
1534out: 1512 if (!dump_emit(cprm, (void *) vma->vm_start,
1535 return err;
1536}
1537#endif
1538
1539/*
1540 * dump the segments for a NOMMU process
1541 */
1542#ifndef CONFIG_MMU
1543static int elf_fdpic_dump_segments(struct file *file, size_t *size,
1544 unsigned long *limit, unsigned long mm_flags)
1545{
1546 struct vm_area_struct *vma;
1547
1548 for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1549 if (!maydump(vma, mm_flags))
1550 continue;
1551
1552 if ((*size += PAGE_SIZE) > *limit)
1553 return -EFBIG;
1554
1555 if (!dump_write(file, (void *) vma->vm_start,
1556 vma->vm_end - vma->vm_start)) 1513 vma->vm_end - vma->vm_start))
1557 return -EIO; 1514 return false;
1515#endif
1558 } 1516 }
1559 1517 return true;
1560 return 0;
1561} 1518}
1562#endif
1563 1519
1564static size_t elf_core_vma_data_size(unsigned long mm_flags) 1520static size_t elf_core_vma_data_size(unsigned long mm_flags)
1565{ 1521{
@@ -1585,11 +1541,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1585 int has_dumped = 0; 1541 int has_dumped = 0;
1586 mm_segment_t fs; 1542 mm_segment_t fs;
1587 int segs; 1543 int segs;
1588 size_t size = 0;
1589 int i; 1544 int i;
1590 struct vm_area_struct *vma; 1545 struct vm_area_struct *vma;
1591 struct elfhdr *elf = NULL; 1546 struct elfhdr *elf = NULL;
1592 loff_t offset = 0, dataoff, foffset; 1547 loff_t offset = 0, dataoff;
1593 int numnote; 1548 int numnote;
1594 struct memelfnote *notes = NULL; 1549 struct memelfnote *notes = NULL;
1595 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ 1550 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
@@ -1606,6 +1561,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1606 struct elf_shdr *shdr4extnum = NULL; 1561 struct elf_shdr *shdr4extnum = NULL;
1607 Elf_Half e_phnum; 1562 Elf_Half e_phnum;
1608 elf_addr_t e_shoff; 1563 elf_addr_t e_shoff;
1564 struct core_thread *ct;
1565 struct elf_thread_status *tmp;
1609 1566
1610 /* 1567 /*
1611 * We no longer stop all VM operations. 1568 * We no longer stop all VM operations.
@@ -1641,28 +1598,23 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1641 goto cleanup; 1598 goto cleanup;
1642#endif 1599#endif
1643 1600
1644 if (cprm->siginfo->si_signo) { 1601 for (ct = current->mm->core_state->dumper.next;
1645 struct core_thread *ct; 1602 ct; ct = ct->next) {
1646 struct elf_thread_status *tmp; 1603 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
1647 1604 if (!tmp)
1648 for (ct = current->mm->core_state->dumper.next; 1605 goto cleanup;
1649 ct; ct = ct->next) {
1650 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
1651 if (!tmp)
1652 goto cleanup;
1653 1606
1654 tmp->thread = ct->task; 1607 tmp->thread = ct->task;
1655 list_add(&tmp->list, &thread_list); 1608 list_add(&tmp->list, &thread_list);
1656 } 1609 }
1657 1610
1658 list_for_each(t, &thread_list) { 1611 list_for_each(t, &thread_list) {
1659 struct elf_thread_status *tmp; 1612 struct elf_thread_status *tmp;
1660 int sz; 1613 int sz;
1661 1614
1662 tmp = list_entry(t, struct elf_thread_status, list); 1615 tmp = list_entry(t, struct elf_thread_status, list);
1663 sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp); 1616 sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp);
1664 thread_status_size += sz; 1617 thread_status_size += sz;
1665 }
1666 } 1618 }
1667 1619
1668 /* now collect the dump for the current */ 1620 /* now collect the dump for the current */
@@ -1720,7 +1672,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1720 1672
1721 offset += sizeof(*elf); /* Elf header */ 1673 offset += sizeof(*elf); /* Elf header */
1722 offset += segs * sizeof(struct elf_phdr); /* Program headers */ 1674 offset += segs * sizeof(struct elf_phdr); /* Program headers */
1723 foffset = offset;
1724 1675
1725 /* Write notes phdr entry */ 1676 /* Write notes phdr entry */
1726 { 1677 {
@@ -1755,13 +1706,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1755 1706
1756 offset = dataoff; 1707 offset = dataoff;
1757 1708
1758 size += sizeof(*elf); 1709 if (!dump_emit(cprm, elf, sizeof(*elf)))
1759 if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
1760 goto end_coredump; 1710 goto end_coredump;
1761 1711
1762 size += sizeof(*phdr4note); 1712 if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
1763 if (size > cprm->limit
1764 || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
1765 goto end_coredump; 1713 goto end_coredump;
1766 1714
1767 /* write program headers for segments dump */ 1715 /* write program headers for segments dump */
@@ -1785,18 +1733,16 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1785 phdr.p_flags |= PF_X; 1733 phdr.p_flags |= PF_X;
1786 phdr.p_align = ELF_EXEC_PAGESIZE; 1734 phdr.p_align = ELF_EXEC_PAGESIZE;
1787 1735
1788 size += sizeof(phdr); 1736 if (!dump_emit(cprm, &phdr, sizeof(phdr)))
1789 if (size > cprm->limit
1790 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1791 goto end_coredump; 1737 goto end_coredump;
1792 } 1738 }
1793 1739
1794 if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit)) 1740 if (!elf_core_write_extra_phdrs(cprm, offset))
1795 goto end_coredump; 1741 goto end_coredump;
1796 1742
1797 /* write out the notes section */ 1743 /* write out the notes section */
1798 for (i = 0; i < numnote; i++) 1744 for (i = 0; i < numnote; i++)
1799 if (!writenote(notes + i, cprm->file, &foffset)) 1745 if (!writenote(notes + i, cprm))
1800 goto end_coredump; 1746 goto end_coredump;
1801 1747
1802 /* write out the thread status notes section */ 1748 /* write out the thread status notes section */
@@ -1805,25 +1751,21 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1805 list_entry(t, struct elf_thread_status, list); 1751 list_entry(t, struct elf_thread_status, list);
1806 1752
1807 for (i = 0; i < tmp->num_notes; i++) 1753 for (i = 0; i < tmp->num_notes; i++)
1808 if (!writenote(&tmp->notes[i], cprm->file, &foffset)) 1754 if (!writenote(&tmp->notes[i], cprm))
1809 goto end_coredump; 1755 goto end_coredump;
1810 } 1756 }
1811 1757
1812 if (!dump_seek(cprm->file, dataoff - foffset)) 1758 if (!dump_skip(cprm, dataoff - cprm->written))
1813 goto end_coredump; 1759 goto end_coredump;
1814 1760
1815 if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, 1761 if (!elf_fdpic_dump_segments(cprm))
1816 cprm->mm_flags) < 0)
1817 goto end_coredump; 1762 goto end_coredump;
1818 1763
1819 if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) 1764 if (!elf_core_write_extra_data(cprm))
1820 goto end_coredump; 1765 goto end_coredump;
1821 1766
1822 if (e_phnum == PN_XNUM) { 1767 if (e_phnum == PN_XNUM) {
1823 size += sizeof(*shdr4extnum); 1768 if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
1824 if (size > cprm->limit
1825 || !dump_write(cprm->file, shdr4extnum,
1826 sizeof(*shdr4extnum)))
1827 goto end_coredump; 1769 goto end_coredump;
1828 } 1770 }
1829 1771