diff options
Diffstat (limited to 'fs/binfmt_elf_fdpic.c')
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 18d77297ccc8..32d9b44c3cb9 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1226,11 +1226,22 @@ static int dump_write(struct file *file, const void *addr, int nr) | |||
1226 | 1226 | ||
1227 | static int dump_seek(struct file *file, loff_t off) | 1227 | static int dump_seek(struct file *file, loff_t off) |
1228 | { | 1228 | { |
1229 | if (file->f_op->llseek) { | 1229 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { |
1230 | if (file->f_op->llseek(file, off, SEEK_SET) != off) | 1230 | if (file->f_op->llseek(file, off, SEEK_CUR) < 0) |
1231 | return 0; | 1231 | return 0; |
1232 | } else { | 1232 | } else { |
1233 | file->f_pos = off; | 1233 | char *buf = (char *)get_zeroed_page(GFP_KERNEL); |
1234 | if (!buf) | ||
1235 | return 0; | ||
1236 | while (off > 0) { | ||
1237 | unsigned long n = off; | ||
1238 | if (n > PAGE_SIZE) | ||
1239 | n = PAGE_SIZE; | ||
1240 | if (!dump_write(file, buf, n)) | ||
1241 | return 0; | ||
1242 | off -= n; | ||
1243 | } | ||
1244 | free_page((unsigned long)buf); | ||
1234 | } | 1245 | } |
1235 | return 1; | 1246 | return 1; |
1236 | } | 1247 | } |
@@ -1313,30 +1324,35 @@ static int notesize(struct memelfnote *en) | |||
1313 | 1324 | ||
1314 | /* #define DEBUG */ | 1325 | /* #define DEBUG */ |
1315 | 1326 | ||
1316 | #define DUMP_WRITE(addr, nr) \ | 1327 | #define DUMP_WRITE(addr, nr, foffset) \ |
1317 | do { if (!dump_write(file, (addr), (nr))) return 0; } while(0) | 1328 | do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0) |
1318 | #define DUMP_SEEK(off) \ | ||
1319 | do { if (!dump_seek(file, (off))) return 0; } while(0) | ||
1320 | 1329 | ||
1321 | static int writenote(struct memelfnote *men, struct file *file) | 1330 | static int alignfile(struct file *file, loff_t *foffset) |
1322 | { | 1331 | { |
1323 | struct elf_note en; | 1332 | static const char buf[4] = { 0, }; |
1333 | DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset); | ||
1334 | return 1; | ||
1335 | } | ||
1324 | 1336 | ||
1337 | static int writenote(struct memelfnote *men, struct file *file, | ||
1338 | loff_t *foffset) | ||
1339 | { | ||
1340 | struct elf_note en; | ||
1325 | en.n_namesz = strlen(men->name) + 1; | 1341 | en.n_namesz = strlen(men->name) + 1; |
1326 | en.n_descsz = men->datasz; | 1342 | en.n_descsz = men->datasz; |
1327 | en.n_type = men->type; | 1343 | en.n_type = men->type; |
1328 | 1344 | ||
1329 | DUMP_WRITE(&en, sizeof(en)); | 1345 | DUMP_WRITE(&en, sizeof(en), foffset); |
1330 | DUMP_WRITE(men->name, en.n_namesz); | 1346 | DUMP_WRITE(men->name, en.n_namesz, foffset); |
1331 | /* XXX - cast from long long to long to avoid need for libgcc.a */ | 1347 | if (!alignfile(file, foffset)) |
1332 | DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ | 1348 | return 0; |
1333 | DUMP_WRITE(men->data, men->datasz); | 1349 | DUMP_WRITE(men->data, men->datasz, foffset); |
1334 | DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ | 1350 | if (!alignfile(file, foffset)) |
1351 | return 0; | ||
1335 | 1352 | ||
1336 | return 1; | 1353 | return 1; |
1337 | } | 1354 | } |
1338 | #undef DUMP_WRITE | 1355 | #undef DUMP_WRITE |
1339 | #undef DUMP_SEEK | ||
1340 | 1356 | ||
1341 | #define DUMP_WRITE(addr, nr) \ | 1357 | #define DUMP_WRITE(addr, nr) \ |
1342 | if ((size += (nr)) > cprm->limit || \ | 1358 | if ((size += (nr)) > cprm->limit || \ |
@@ -1552,7 +1568,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size, | |||
1552 | err = -EIO; | 1568 | err = -EIO; |
1553 | kunmap(page); | 1569 | kunmap(page); |
1554 | page_cache_release(page); | 1570 | page_cache_release(page); |
1555 | } else if (!dump_seek(file, file->f_pos + PAGE_SIZE)) | 1571 | } else if (!dump_seek(file, PAGE_SIZE)) |
1556 | err = -EFBIG; | 1572 | err = -EFBIG; |
1557 | if (err) | 1573 | if (err) |
1558 | goto out; | 1574 | goto out; |
@@ -1605,7 +1621,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1605 | int i; | 1621 | int i; |
1606 | struct vm_area_struct *vma; | 1622 | struct vm_area_struct *vma; |
1607 | struct elfhdr *elf = NULL; | 1623 | struct elfhdr *elf = NULL; |
1608 | loff_t offset = 0, dataoff; | 1624 | loff_t offset = 0, dataoff, foffset; |
1609 | int numnote; | 1625 | int numnote; |
1610 | struct memelfnote *notes = NULL; | 1626 | struct memelfnote *notes = NULL; |
1611 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ | 1627 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ |
@@ -1730,6 +1746,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1730 | DUMP_WRITE(elf, sizeof(*elf)); | 1746 | DUMP_WRITE(elf, sizeof(*elf)); |
1731 | offset += sizeof(*elf); /* Elf header */ | 1747 | offset += sizeof(*elf); /* Elf header */ |
1732 | offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ | 1748 | offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ |
1749 | foffset = offset; | ||
1733 | 1750 | ||
1734 | /* Write notes phdr entry */ | 1751 | /* Write notes phdr entry */ |
1735 | { | 1752 | { |
@@ -1786,7 +1803,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1786 | 1803 | ||
1787 | /* write out the notes section */ | 1804 | /* write out the notes section */ |
1788 | for (i = 0; i < numnote; i++) | 1805 | for (i = 0; i < numnote; i++) |
1789 | if (!writenote(notes + i, cprm->file)) | 1806 | if (!writenote(notes + i, cprm->file, &foffset)) |
1790 | goto end_coredump; | 1807 | goto end_coredump; |
1791 | 1808 | ||
1792 | /* write out the thread status notes section */ | 1809 | /* write out the thread status notes section */ |
@@ -1795,11 +1812,11 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1795 | list_entry(t, struct elf_thread_status, list); | 1812 | list_entry(t, struct elf_thread_status, list); |
1796 | 1813 | ||
1797 | for (i = 0; i < tmp->num_notes; i++) | 1814 | for (i = 0; i < tmp->num_notes; i++) |
1798 | if (!writenote(&tmp->notes[i], cprm->file)) | 1815 | if (!writenote(&tmp->notes[i], cprm->file, &foffset)) |
1799 | goto end_coredump; | 1816 | goto end_coredump; |
1800 | } | 1817 | } |
1801 | 1818 | ||
1802 | if (!dump_seek(cprm->file, dataoff)) | 1819 | if (!dump_seek(cprm->file, dataoff - foffset)) |
1803 | goto end_coredump; | 1820 | goto end_coredump; |
1804 | 1821 | ||
1805 | if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, | 1822 | if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, |