aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_elf.c77
-rw-r--r--fs/exec.c23
2 files changed, 63 insertions, 37 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index bad52433de69..06435f3665f4 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1151,11 +1151,23 @@ static int dump_write(struct file *file, const void *addr, int nr)
1151 1151
1152static int dump_seek(struct file *file, loff_t off) 1152static int dump_seek(struct file *file, loff_t off)
1153{ 1153{
1154 if (file->f_op->llseek) { 1154 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
1155 if (file->f_op->llseek(file, off, 0) != off) 1155 if (file->f_op->llseek(file, off, 1) != off)
1156 return 0; 1156 return 0;
1157 } else 1157 } else {
1158 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 }
1159 return 1; 1171 return 1;
1160} 1172}
1161 1173
@@ -1203,30 +1215,35 @@ static int notesize(struct memelfnote *en)
1203 return sz; 1215 return sz;
1204} 1216}
1205 1217
1206#define DUMP_WRITE(addr, nr) \ 1218#define DUMP_WRITE(addr, nr, foffset) \
1207 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)
1208#define DUMP_SEEK(off) \
1209 do { if (!dump_seek(file, (off))) return 0; } while(0)
1210 1220
1211static int writenote(struct memelfnote *men, struct file *file) 1221static int alignfile(struct file *file, loff_t *foffset)
1212{ 1222{
1213 struct elf_note en; 1223 char buf[4] = { 0, };
1224 DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
1225 return 1;
1226}
1214 1227
1228static int writenote(struct memelfnote *men, struct file *file,
1229 loff_t *foffset)
1230{
1231 struct elf_note en;
1215 en.n_namesz = strlen(men->name) + 1; 1232 en.n_namesz = strlen(men->name) + 1;
1216 en.n_descsz = men->datasz; 1233 en.n_descsz = men->datasz;
1217 en.n_type = men->type; 1234 en.n_type = men->type;
1218 1235
1219 DUMP_WRITE(&en, sizeof(en)); 1236 DUMP_WRITE(&en, sizeof(en), foffset);
1220 DUMP_WRITE(men->name, en.n_namesz); 1237 DUMP_WRITE(men->name, en.n_namesz, foffset);
1221 /* XXX - cast from long long to long to avoid need for libgcc.a */ 1238 if (!alignfile(file, foffset))
1222 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ 1239 return 0;
1223 DUMP_WRITE(men->data, men->datasz); 1240 DUMP_WRITE(men->data, men->datasz, foffset);
1224 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ 1241 if (!alignfile(file, foffset))
1242 return 0;
1225 1243
1226 return 1; 1244 return 1;
1227} 1245}
1228#undef DUMP_WRITE 1246#undef DUMP_WRITE
1229#undef DUMP_SEEK
1230 1247
1231#define DUMP_WRITE(addr, nr) \ 1248#define DUMP_WRITE(addr, nr) \
1232 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ 1249 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
@@ -1426,7 +1443,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1426 int i; 1443 int i;
1427 struct vm_area_struct *vma; 1444 struct vm_area_struct *vma;
1428 struct elfhdr *elf = NULL; 1445 struct elfhdr *elf = NULL;
1429 loff_t offset = 0, dataoff; 1446 loff_t offset = 0, dataoff, foffset;
1430 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; 1447 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1431 int numnote; 1448 int numnote;
1432 struct memelfnote *notes = NULL; 1449 struct memelfnote *notes = NULL;
@@ -1569,7 +1586,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1569 DUMP_WRITE(&phdr, sizeof(phdr)); 1586 DUMP_WRITE(&phdr, sizeof(phdr));
1570 } 1587 }
1571 1588
1572 /* Page-align dumped data */ 1589 foffset = offset;
1590
1573 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1591 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
1574 1592
1575 /* Write program headers for segments dump */ 1593 /* Write program headers for segments dump */
@@ -1594,6 +1612,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1594 phdr.p_align = ELF_EXEC_PAGESIZE; 1612 phdr.p_align = ELF_EXEC_PAGESIZE;
1595 1613
1596 DUMP_WRITE(&phdr, sizeof(phdr)); 1614 DUMP_WRITE(&phdr, sizeof(phdr));
1615 foffset += sizeof(phdr);
1597 } 1616 }
1598 1617
1599#ifdef ELF_CORE_WRITE_EXTRA_PHDRS 1618#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
@@ -1602,7 +1621,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1602 1621
1603 /* write out the notes section */ 1622 /* write out the notes section */
1604 for (i = 0; i < numnote; i++) 1623 for (i = 0; i < numnote; i++)
1605 if (!writenote(notes + i, file)) 1624 if (!writenote(notes + i, file, &foffset))
1606 goto end_coredump; 1625 goto end_coredump;
1607 1626
1608 /* write out the thread status notes section */ 1627 /* write out the thread status notes section */
@@ -1611,11 +1630,12 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1611 list_entry(t, struct elf_thread_status, list); 1630 list_entry(t, struct elf_thread_status, list);
1612 1631
1613 for (i = 0; i < tmp->num_notes; i++) 1632 for (i = 0; i < tmp->num_notes; i++)
1614 if (!writenote(&tmp->notes[i], file)) 1633 if (!writenote(&tmp->notes[i], file, &foffset))
1615 goto end_coredump; 1634 goto end_coredump;
1616 } 1635 }
1617 1636
1618 DUMP_SEEK(dataoff); 1637 /* Align to page */
1638 DUMP_SEEK(dataoff - foffset);
1619 1639
1620 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { 1640 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
1621 unsigned long addr; 1641 unsigned long addr;
@@ -1631,10 +1651,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1631 1651
1632 if (get_user_pages(current, current->mm, addr, 1, 0, 1, 1652 if (get_user_pages(current, current->mm, addr, 1, 0, 1,
1633 &page, &vma) <= 0) { 1653 &page, &vma) <= 0) {
1634 DUMP_SEEK(file->f_pos + PAGE_SIZE); 1654 DUMP_SEEK(PAGE_SIZE);
1635 } else { 1655 } else {
1636 if (page == ZERO_PAGE(addr)) { 1656 if (page == ZERO_PAGE(addr)) {
1637 DUMP_SEEK(file->f_pos + PAGE_SIZE); 1657 DUMP_SEEK(PAGE_SIZE);
1638 } else { 1658 } else {
1639 void *kaddr; 1659 void *kaddr;
1640 flush_cache_page(vma, addr, 1660 flush_cache_page(vma, addr,
@@ -1658,13 +1678,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1658 ELF_CORE_WRITE_EXTRA_DATA; 1678 ELF_CORE_WRITE_EXTRA_DATA;
1659#endif 1679#endif
1660 1680
1661 if (file->f_pos != offset) {
1662 /* Sanity check */
1663 printk(KERN_WARNING
1664 "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
1665 file->f_pos, offset);
1666 }
1667
1668end_coredump: 1681end_coredump:
1669 set_fs(fs); 1682 set_fs(fs);
1670 1683
diff --git a/fs/exec.c b/fs/exec.c
index 0db3fc3c5f0f..6270f8f20a63 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -58,7 +58,7 @@
58#endif 58#endif
59 59
60int core_uses_pid; 60int core_uses_pid;
61char core_pattern[65] = "core"; 61char core_pattern[128] = "core";
62int suid_dumpable = 0; 62int suid_dumpable = 0;
63 63
64EXPORT_SYMBOL(suid_dumpable); 64EXPORT_SYMBOL(suid_dumpable);
@@ -1463,6 +1463,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1463 int retval = 0; 1463 int retval = 0;
1464 int fsuid = current->fsuid; 1464 int fsuid = current->fsuid;
1465 int flag = 0; 1465 int flag = 0;
1466 int ispipe = 0;
1466 1467
1467 binfmt = current->binfmt; 1468 binfmt = current->binfmt;
1468 if (!binfmt || !binfmt->core_dump) 1469 if (!binfmt || !binfmt->core_dump)
@@ -1504,22 +1505,34 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1504 lock_kernel(); 1505 lock_kernel();
1505 format_corename(corename, core_pattern, signr); 1506 format_corename(corename, core_pattern, signr);
1506 unlock_kernel(); 1507 unlock_kernel();
1507 file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); 1508 if (corename[0] == '|') {
1509 /* SIGPIPE can happen, but it's just never processed */
1510 if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
1511 printk(KERN_INFO "Core dump to %s pipe failed\n",
1512 corename);
1513 goto fail_unlock;
1514 }
1515 ispipe = 1;
1516 } else
1517 file = filp_open(corename,
1518 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
1508 if (IS_ERR(file)) 1519 if (IS_ERR(file))
1509 goto fail_unlock; 1520 goto fail_unlock;
1510 inode = file->f_dentry->d_inode; 1521 inode = file->f_dentry->d_inode;
1511 if (inode->i_nlink > 1) 1522 if (inode->i_nlink > 1)
1512 goto close_fail; /* multiple links - don't dump */ 1523 goto close_fail; /* multiple links - don't dump */
1513 if (d_unhashed(file->f_dentry)) 1524 if (!ispipe && d_unhashed(file->f_dentry))
1514 goto close_fail; 1525 goto close_fail;
1515 1526
1516 if (!S_ISREG(inode->i_mode)) 1527 /* AK: actually i see no reason to not allow this for named pipes etc.,
1528 but keep the previous behaviour for now. */
1529 if (!ispipe && !S_ISREG(inode->i_mode))
1517 goto close_fail; 1530 goto close_fail;
1518 if (!file->f_op) 1531 if (!file->f_op)
1519 goto close_fail; 1532 goto close_fail;
1520 if (!file->f_op->write) 1533 if (!file->f_op->write)
1521 goto close_fail; 1534 goto close_fail;
1522 if (do_truncate(file->f_dentry, 0, 0, file) != 0) 1535 if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
1523 goto close_fail; 1536 goto close_fail;
1524 1537
1525 retval = binfmt->core_dump(signr, regs, file); 1538 retval = binfmt->core_dump(signr, regs, file);