Commit 82df39738ba9e02c057fa99b7461a56117d36119

Authored by Roland McGrath
Committed by Linus Torvalds
1 parent e629a7ddc0

Add MMF_DUMP_ELF_HEADERS

This adds the MMF_DUMP_ELF_HEADERS option to /proc/pid/coredump_filter.
This dumps the first page (only) of a private file mapping if it appears to
be a mapping of an ELF file.  Including these pages in the core dump may
give sufficient identifying information to associate the original DSO and
executable file images and their debugging information with a core file in
a generic way just from its contents (e.g.  when those binaries were built
with ld --build-id).  I expect this to become the default behavior
eventually.  Existing versions of gdb can be confused by the core dumps it
creates, so it won't enabled by default for some time to come.  Soon many
people will have systems with a gdb that handle these dumps, so they can
arrange to set the bit at boot and have it inherited system-wide.

This also cleans up the checking of the MMF_DUMP_* flag bits, which did not
need to be using atomic macros.

Signed-off-by: Roland McGrath <roland@redhat.com>
Cc: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 55 additions and 26 deletions Side-by-side Diff

... ... @@ -1201,35 +1201,68 @@
1201 1201 }
1202 1202  
1203 1203 /*
1204   - * Decide whether a segment is worth dumping; default is yes to be
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.
  1204 + * Decide what to dump of a segment, part, all or none.
1209 1205 */
1210   -static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
  1206 +static unsigned long vma_dump_size(struct vm_area_struct *vma,
  1207 + unsigned long mm_flags)
1211 1208 {
1212 1209 /* The vma can be set up to tell us the answer directly. */
1213 1210 if (vma->vm_flags & VM_ALWAYSDUMP)
1214   - return 1;
  1211 + goto whole;
1215 1212  
1216 1213 /* Do not dump I/O mapped devices or special mappings */
1217 1214 if (vma->vm_flags & (VM_IO | VM_RESERVED))
1218 1215 return 0;
1219 1216  
  1217 +#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
  1218 +
1220 1219 /* By default, dump shared memory if mapped from an anonymous file. */
1221 1220 if (vma->vm_flags & VM_SHARED) {
1222   - if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0)
1223   - return test_bit(MMF_DUMP_ANON_SHARED, &mm_flags);
1224   - else
1225   - return test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags);
  1221 + if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0 ?
  1222 + FILTER(ANON_SHARED) : FILTER(MAPPED_SHARED))
  1223 + goto whole;
  1224 + return 0;
1226 1225 }
1227 1226  
1228   - /* By default, if it hasn't been written to, don't write it out. */
1229   - if (!vma->anon_vma)
1230   - return test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags);
  1227 + /* Dump segments that have been written to. */
  1228 + if (vma->anon_vma && FILTER(ANON_PRIVATE))
  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 +
  1264 +whole:
  1265 + return vma->vm_end - vma->vm_start;
1233 1266 }
1234 1267  
1235 1268 /* An ELF note in memory */
1236 1269  
1237 1270  
... ... @@ -1669,16 +1702,13 @@
1669 1702 for (vma = first_vma(current, gate_vma); vma != NULL;
1670 1703 vma = next_vma(vma, gate_vma)) {
1671 1704 struct elf_phdr phdr;
1672   - size_t sz;
1673 1705  
1674   - sz = vma->vm_end - vma->vm_start;
1675   -
1676 1706 phdr.p_type = PT_LOAD;
1677 1707 phdr.p_offset = offset;
1678 1708 phdr.p_vaddr = vma->vm_start;
1679 1709 phdr.p_paddr = 0;
1680   - phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
1681   - phdr.p_memsz = sz;
  1710 + phdr.p_filesz = vma_dump_size(vma, mm_flags);
  1711 + phdr.p_memsz = vma->vm_end - vma->vm_start;
1682 1712 offset += phdr.p_filesz;
1683 1713 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1684 1714 if (vma->vm_flags & VM_WRITE)
1685 1715  
1686 1716  
... ... @@ -1718,13 +1748,11 @@
1718 1748 for (vma = first_vma(current, gate_vma); vma != NULL;
1719 1749 vma = next_vma(vma, gate_vma)) {
1720 1750 unsigned long addr;
  1751 + unsigned long end;
1721 1752  
1722   - if (!maydump(vma, mm_flags))
1723   - continue;
  1753 + end = vma->vm_start + vma_dump_size(vma, mm_flags);
1724 1754  
1725   - for (addr = vma->vm_start;
1726   - addr < vma->vm_end;
1727   - addr += PAGE_SIZE) {
  1755 + for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
1728 1756 struct page *page;
1729 1757 struct vm_area_struct *vma;
1730 1758  
include/linux/sched.h
... ... @@ -359,8 +359,9 @@
359 359 #define MMF_DUMP_ANON_SHARED 3
360 360 #define MMF_DUMP_MAPPED_PRIVATE 4
361 361 #define MMF_DUMP_MAPPED_SHARED 5
  362 +#define MMF_DUMP_ELF_HEADERS 6
362 363 #define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
363   -#define MMF_DUMP_FILTER_BITS 4
  364 +#define MMF_DUMP_FILTER_BITS 5
364 365 #define MMF_DUMP_FILTER_MASK \
365 366 (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
366 367 #define MMF_DUMP_FILTER_DEFAULT \