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.c59
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
1227static int dump_seek(struct file *file, loff_t off) 1227static 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
1321static int writenote(struct memelfnote *men, struct file *file) 1330static 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
1337static 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,