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.c91
1 files changed, 50 insertions, 41 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index dfd8cfb7fb5d..06435f3665f4 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -46,7 +46,6 @@
46static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); 46static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
47static int load_elf_library(struct file *); 47static int load_elf_library(struct file *);
48static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); 48static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
49extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
50 49
51#ifndef elf_addr_t 50#ifndef elf_addr_t
52#define elf_addr_t unsigned long 51#define elf_addr_t unsigned long
@@ -1038,10 +1037,8 @@ out_free_interp:
1038out_free_file: 1037out_free_file:
1039 sys_close(elf_exec_fileno); 1038 sys_close(elf_exec_fileno);
1040out_free_fh: 1039out_free_fh:
1041 if (files) { 1040 if (files)
1042 put_files_struct(current->files); 1041 reset_files_struct(current, files);
1043 current->files = files;
1044 }
1045out_free_ph: 1042out_free_ph:
1046 kfree(elf_phdata); 1043 kfree(elf_phdata);
1047 goto out; 1044 goto out;
@@ -1154,11 +1151,23 @@ static int dump_write(struct file *file, const void *addr, int nr)
1154 1151
1155static int dump_seek(struct file *file, loff_t off) 1152static int dump_seek(struct file *file, loff_t off)
1156{ 1153{
1157 if (file->f_op->llseek) { 1154 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
1158 if (file->f_op->llseek(file, off, 0) != off) 1155 if (file->f_op->llseek(file, off, 1) != off)
1159 return 0; 1156 return 0;
1160 } else 1157 } else {
1161 file->f_pos = off; 1158 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
1159 if (!buf)
1160 return 0;
1161 while (off > 0) {
1162 unsigned long n = off;
1163 if (n > PAGE_SIZE)
1164 n = PAGE_SIZE;
1165 if (!dump_write(file, buf, n))
1166 return 0;
1167 off -= n;
1168 }
1169 free_page((unsigned long)buf);
1170 }
1162 return 1; 1171 return 1;
1163} 1172}
1164 1173
@@ -1206,30 +1215,35 @@ static int notesize(struct memelfnote *en)
1206 return sz; 1215 return sz;
1207} 1216}
1208 1217
1209#define DUMP_WRITE(addr, nr) \ 1218#define DUMP_WRITE(addr, nr, foffset) \
1210 do { if (!dump_write(file, (addr), (nr))) return 0; } while(0) 1219 do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
1211#define DUMP_SEEK(off) \
1212 do { if (!dump_seek(file, (off))) return 0; } while(0)
1213 1220
1214static int writenote(struct memelfnote *men, struct file *file) 1221static int alignfile(struct file *file, loff_t *foffset)
1215{ 1222{
1216 struct elf_note en; 1223 char buf[4] = { 0, };
1224 DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
1225 return 1;
1226}
1217 1227
1228static int writenote(struct memelfnote *men, struct file *file,
1229 loff_t *foffset)
1230{
1231 struct elf_note en;
1218 en.n_namesz = strlen(men->name) + 1; 1232 en.n_namesz = strlen(men->name) + 1;
1219 en.n_descsz = men->datasz; 1233 en.n_descsz = men->datasz;
1220 en.n_type = men->type; 1234 en.n_type = men->type;
1221 1235
1222 DUMP_WRITE(&en, sizeof(en)); 1236 DUMP_WRITE(&en, sizeof(en), foffset);
1223 DUMP_WRITE(men->name, en.n_namesz); 1237 DUMP_WRITE(men->name, en.n_namesz, foffset);
1224 /* XXX - cast from long long to long to avoid need for libgcc.a */ 1238 if (!alignfile(file, foffset))
1225 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ 1239 return 0;
1226 DUMP_WRITE(men->data, men->datasz); 1240 DUMP_WRITE(men->data, men->datasz, foffset);
1227 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ 1241 if (!alignfile(file, foffset))
1242 return 0;
1228 1243
1229 return 1; 1244 return 1;
1230} 1245}
1231#undef DUMP_WRITE 1246#undef DUMP_WRITE
1232#undef DUMP_SEEK
1233 1247
1234#define DUMP_WRITE(addr, nr) \ 1248#define DUMP_WRITE(addr, nr) \
1235 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ 1249 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
@@ -1429,7 +1443,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1429 int i; 1443 int i;
1430 struct vm_area_struct *vma; 1444 struct vm_area_struct *vma;
1431 struct elfhdr *elf = NULL; 1445 struct elfhdr *elf = NULL;
1432 loff_t offset = 0, dataoff; 1446 loff_t offset = 0, dataoff, foffset;
1433 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; 1447 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1434 int numnote; 1448 int numnote;
1435 struct memelfnote *notes = NULL; 1449 struct memelfnote *notes = NULL;
@@ -1481,20 +1495,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1481 1495
1482 if (signr) { 1496 if (signr) {
1483 struct elf_thread_status *tmp; 1497 struct elf_thread_status *tmp;
1484 read_lock(&tasklist_lock); 1498 rcu_read_lock();
1485 do_each_thread(g,p) 1499 do_each_thread(g,p)
1486 if (current->mm == p->mm && current != p) { 1500 if (current->mm == p->mm && current != p) {
1487 tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); 1501 tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
1488 if (!tmp) { 1502 if (!tmp) {
1489 read_unlock(&tasklist_lock); 1503 rcu_read_unlock();
1490 goto cleanup; 1504 goto cleanup;
1491 } 1505 }
1492 INIT_LIST_HEAD(&tmp->list);
1493 tmp->thread = p; 1506 tmp->thread = p;
1494 list_add(&tmp->list, &thread_list); 1507 list_add(&tmp->list, &thread_list);
1495 } 1508 }
1496 while_each_thread(g,p); 1509 while_each_thread(g,p);
1497 read_unlock(&tasklist_lock); 1510 rcu_read_unlock();
1498 list_for_each(t, &thread_list) { 1511 list_for_each(t, &thread_list) {
1499 struct elf_thread_status *tmp; 1512 struct elf_thread_status *tmp;
1500 int sz; 1513 int sz;
@@ -1573,7 +1586,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1573 DUMP_WRITE(&phdr, sizeof(phdr)); 1586 DUMP_WRITE(&phdr, sizeof(phdr));
1574 } 1587 }
1575 1588
1576 /* Page-align dumped data */ 1589 foffset = offset;
1590
1577 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1591 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
1578 1592
1579 /* Write program headers for segments dump */ 1593 /* Write program headers for segments dump */
@@ -1598,6 +1612,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1598 phdr.p_align = ELF_EXEC_PAGESIZE; 1612 phdr.p_align = ELF_EXEC_PAGESIZE;
1599 1613
1600 DUMP_WRITE(&phdr, sizeof(phdr)); 1614 DUMP_WRITE(&phdr, sizeof(phdr));
1615 foffset += sizeof(phdr);
1601 } 1616 }
1602 1617
1603#ifdef ELF_CORE_WRITE_EXTRA_PHDRS 1618#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
@@ -1606,7 +1621,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1606 1621
1607 /* write out the notes section */ 1622 /* write out the notes section */
1608 for (i = 0; i < numnote; i++) 1623 for (i = 0; i < numnote; i++)
1609 if (!writenote(notes + i, file)) 1624 if (!writenote(notes + i, file, &foffset))
1610 goto end_coredump; 1625 goto end_coredump;
1611 1626
1612 /* write out the thread status notes section */ 1627 /* write out the thread status notes section */
@@ -1615,11 +1630,12 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1615 list_entry(t, struct elf_thread_status, list); 1630 list_entry(t, struct elf_thread_status, list);
1616 1631
1617 for (i = 0; i < tmp->num_notes; i++) 1632 for (i = 0; i < tmp->num_notes; i++)
1618 if (!writenote(&tmp->notes[i], file)) 1633 if (!writenote(&tmp->notes[i], file, &foffset))
1619 goto end_coredump; 1634 goto end_coredump;
1620 } 1635 }
1621 1636
1622 DUMP_SEEK(dataoff); 1637 /* Align to page */
1638 DUMP_SEEK(dataoff - foffset);
1623 1639
1624 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { 1640 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
1625 unsigned long addr; 1641 unsigned long addr;
@@ -1635,10 +1651,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1635 1651
1636 if (get_user_pages(current, current->mm, addr, 1, 0, 1, 1652 if (get_user_pages(current, current->mm, addr, 1, 0, 1,
1637 &page, &vma) <= 0) { 1653 &page, &vma) <= 0) {
1638 DUMP_SEEK(file->f_pos + PAGE_SIZE); 1654 DUMP_SEEK(PAGE_SIZE);
1639 } else { 1655 } else {
1640 if (page == ZERO_PAGE(addr)) { 1656 if (page == ZERO_PAGE(addr)) {
1641 DUMP_SEEK(file->f_pos + PAGE_SIZE); 1657 DUMP_SEEK(PAGE_SIZE);
1642 } else { 1658 } else {
1643 void *kaddr; 1659 void *kaddr;
1644 flush_cache_page(vma, addr, 1660 flush_cache_page(vma, addr,
@@ -1662,13 +1678,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1662 ELF_CORE_WRITE_EXTRA_DATA; 1678 ELF_CORE_WRITE_EXTRA_DATA;
1663#endif 1679#endif
1664 1680
1665 if (file->f_pos != offset) {
1666 /* Sanity check */
1667 printk(KERN_WARNING
1668 "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
1669 file->f_pos, offset);
1670 }
1671
1672end_coredump: 1681end_coredump:
1673 set_fs(fs); 1682 set_fs(fs);
1674 1683