aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_elf.c78
-rw-r--r--include/linux/sched.h3
2 files changed, 55 insertions, 26 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 66cd711a6b1a..4263326ede04 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1201,35 +1201,68 @@ static int dump_seek(struct file *file, loff_t off)
1201} 1201}
1202 1202
1203/* 1203/*
1204 * Decide whether a segment is worth dumping; default is yes to be 1204 * Decide what to dump of a segment, part, all or none.
1205 * sure (missing info is worse than too much; etc).
1206 * Personally I'd include everything, and use the coredump limit...
1207 *
1208 * I think we should skip something. But I am not sure how. H.J.
1209 */ 1205 */
1210static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) 1206static unsigned long vma_dump_size(struct vm_area_struct *vma,
1207 unsigned long mm_flags)
1211{ 1208{
1212 /* The vma can be set up to tell us the answer directly. */ 1209 /* The vma can be set up to tell us the answer directly. */
1213 if (vma->vm_flags & VM_ALWAYSDUMP) 1210 if (vma->vm_flags & VM_ALWAYSDUMP)
1214 return 1; 1211 goto whole;
1215 1212
1216 /* Do not dump I/O mapped devices or special mappings */ 1213 /* Do not dump I/O mapped devices or special mappings */
1217 if (vma->vm_flags & (VM_IO | VM_RESERVED)) 1214 if (vma->vm_flags & (VM_IO | VM_RESERVED))
1218 return 0; 1215 return 0;
1219 1216
1217#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
1218
1220 /* By default, dump shared memory if mapped from an anonymous file. */ 1219 /* By default, dump shared memory if mapped from an anonymous file. */
1221 if (vma->vm_flags & VM_SHARED) { 1220 if (vma->vm_flags & VM_SHARED) {
1222 if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) 1221 if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0 ?
1223 return test_bit(MMF_DUMP_ANON_SHARED, &mm_flags); 1222 FILTER(ANON_SHARED) : FILTER(MAPPED_SHARED))
1224 else 1223 goto whole;
1225 return test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags); 1224 return 0;
1226 } 1225 }
1227 1226
1228 /* By default, if it hasn't been written to, don't write it out. */ 1227 /* Dump segments that have been written to. */
1229 if (!vma->anon_vma) 1228 if (vma->anon_vma && FILTER(ANON_PRIVATE))
1230 return test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags); 1229 goto whole;
1230 if (vma->vm_file == NULL)
1231 return 0;
1231 1232
1232 return test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags); 1233 if (FILTER(MAPPED_PRIVATE))
1234 goto whole;
1235
1236 /*
1237 * If this looks like the beginning of a DSO or executable mapping,
1238 * check for an ELF header. If we find one, dump the first page to
1239 * aid in determining what was mapped here.
1240 */
1241 if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) {
1242 u32 __user *header = (u32 __user *) vma->vm_start;
1243 u32 word;
1244 /*
1245 * Doing it this way gets the constant folded by GCC.
1246 */
1247 union {
1248 u32 cmp;
1249 char elfmag[SELFMAG];
1250 } magic;
1251 BUILD_BUG_ON(SELFMAG != sizeof word);
1252 magic.elfmag[EI_MAG0] = ELFMAG0;
1253 magic.elfmag[EI_MAG1] = ELFMAG1;
1254 magic.elfmag[EI_MAG2] = ELFMAG2;
1255 magic.elfmag[EI_MAG3] = ELFMAG3;
1256 if (get_user(word, header) == 0 && word == magic.cmp)
1257 return PAGE_SIZE;
1258 }
1259
1260#undef FILTER
1261
1262 return 0;
1263
1264whole:
1265 return vma->vm_end - vma->vm_start;
1233} 1266}
1234 1267
1235/* An ELF note in memory */ 1268/* An ELF note in memory */
@@ -1669,16 +1702,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
1669 for (vma = first_vma(current, gate_vma); vma != NULL; 1702 for (vma = first_vma(current, gate_vma); vma != NULL;
1670 vma = next_vma(vma, gate_vma)) { 1703 vma = next_vma(vma, gate_vma)) {
1671 struct elf_phdr phdr; 1704 struct elf_phdr phdr;
1672 size_t sz;
1673
1674 sz = vma->vm_end - vma->vm_start;
1675 1705
1676 phdr.p_type = PT_LOAD; 1706 phdr.p_type = PT_LOAD;
1677 phdr.p_offset = offset; 1707 phdr.p_offset = offset;
1678 phdr.p_vaddr = vma->vm_start; 1708 phdr.p_vaddr = vma->vm_start;
1679 phdr.p_paddr = 0; 1709 phdr.p_paddr = 0;
1680 phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0; 1710 phdr.p_filesz = vma_dump_size(vma, mm_flags);
1681 phdr.p_memsz = sz; 1711 phdr.p_memsz = vma->vm_end - vma->vm_start;
1682 offset += phdr.p_filesz; 1712 offset += phdr.p_filesz;
1683 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1713 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1684 if (vma->vm_flags & VM_WRITE) 1714 if (vma->vm_flags & VM_WRITE)
@@ -1718,13 +1748,11 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
1718 for (vma = first_vma(current, gate_vma); vma != NULL; 1748 for (vma = first_vma(current, gate_vma); vma != NULL;
1719 vma = next_vma(vma, gate_vma)) { 1749 vma = next_vma(vma, gate_vma)) {
1720 unsigned long addr; 1750 unsigned long addr;
1751 unsigned long end;
1721 1752
1722 if (!maydump(vma, mm_flags)) 1753 end = vma->vm_start + vma_dump_size(vma, mm_flags);
1723 continue;
1724 1754
1725 for (addr = vma->vm_start; 1755 for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
1726 addr < vma->vm_end;
1727 addr += PAGE_SIZE) {
1728 struct page *page; 1756 struct page *page;
1729 struct vm_area_struct *vma; 1757 struct vm_area_struct *vma;
1730 1758
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e643357eda05..cb952bc225e4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -359,8 +359,9 @@ extern int get_dumpable(struct mm_struct *mm);
359#define MMF_DUMP_ANON_SHARED 3 359#define MMF_DUMP_ANON_SHARED 3
360#define MMF_DUMP_MAPPED_PRIVATE 4 360#define MMF_DUMP_MAPPED_PRIVATE 4
361#define MMF_DUMP_MAPPED_SHARED 5 361#define MMF_DUMP_MAPPED_SHARED 5
362#define MMF_DUMP_ELF_HEADERS 6
362#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS 363#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
363#define MMF_DUMP_FILTER_BITS 4 364#define MMF_DUMP_FILTER_BITS 5
364#define MMF_DUMP_FILTER_MASK \ 365#define MMF_DUMP_FILTER_MASK \
365 (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT) 366 (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
366#define MMF_DUMP_FILTER_DEFAULT \ 367#define MMF_DUMP_FILTER_DEFAULT \