coredump: remove VM_ALWAYSDUMP flag
authorJason Baron <jbaron@redhat.com>
Fri, 23 Mar 2012 22:02:51 +0000 (15:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Mar 2012 23:58:42 +0000 (16:58 -0700)
The motivation for this patchset was that I was looking at a way for a
qemu-kvm process, to exclude the guest memory from its core dump, which
can be quite large.  There are already a number of filter flags in
/proc/<pid>/coredump_filter, however, these allow one to specify 'types'
of kernel memory, not specific address ranges (which is needed in this
case).

Since there are no more vma flags available, the first patch eliminates
the need for the 'VM_ALWAYSDUMP' flag.  The flag is used internally by
the kernel to mark vdso and vsyscall pages.  However, it is simple
enough to check if a vma covers a vdso or vsyscall page without the need
for this flag.

The second patch then replaces the 'VM_ALWAYSDUMP' flag with a new
'VM_NODUMP' flag, which can be set by userspace using new madvise flags:
'MADV_DONTDUMP', and unset via 'MADV_DODUMP'.  The core dump filters
continue to work the same as before unless 'MADV_DONTDUMP' is set on the
region.

The qemu code which implements this features is at:

  http://people.redhat.com/~jbaron/qemu-dump/qemu-dump.patch

In my testing the qemu core dump shrunk from 383MB -> 13MB with this
patch.

I also believe that the 'MADV_DONTDUMP' flag might be useful for
security sensitive apps, which might want to select which areas are
dumped.

This patch:

The VM_ALWAYSDUMP flag is currently used by the coredump code to
indicate that a vma is part of a vsyscall or vdso section.  However, we
can determine if a vma is in one these sections by checking it against
the gate_vma and checking for a non-NULL return value from
arch_vma_name().  Thus, freeing a valuable vma bit.

Signed-off-by: Jason Baron <jbaron@redhat.com>
Acked-by: Roland McGrath <roland@hack.frob.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Avi Kivity <avi@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
15 files changed:
arch/arm/kernel/process.c
arch/hexagon/kernel/vdso.c
arch/mips/kernel/vdso.c
arch/powerpc/kernel/vdso.c
arch/s390/kernel/vdso.c
arch/sh/kernel/vsyscall/vsyscall.c
arch/tile/mm/elf.c
arch/unicore32/kernel/process.c
arch/x86/um/mem_32.c
arch/x86/um/vdso/vma.c
arch/x86/vdso/vdso32-setup.c
arch/x86/vdso/vma.c
fs/binfmt_elf.c
include/linux/mm.h
mm/memory.c

index c2ae3cd331feea2e9ea37439cdde6dd458711db1..219e4efee1a6b64d17855ada4ce30db9c35175cd 100644 (file)
@@ -533,8 +533,7 @@ int vectors_user_mapping(void)
        struct mm_struct *mm = current->mm;
        return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
                                       VM_READ | VM_EXEC |
-                                      VM_MAYREAD | VM_MAYEXEC |
-                                      VM_ALWAYSDUMP | VM_RESERVED,
+                                      VM_MAYREAD | VM_MAYEXEC | VM_RESERVED,
                                       NULL);
 }
 
index 16277c33308af1cd6a735735bd24932bd76dff9e..f212a453b527d09accbd09c16dbfa5ae506745e1 100644 (file)
@@ -78,8 +78,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
        /* MAYWRITE to allow gdb to COW and set breakpoints. */
        ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
                                      VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                     VM_ALWAYSDUMP,
+                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                      &vdso_page);
 
        if (ret)
index e5cdfd603f8fb6dabbdf22051b043604c8ad6496..0f1af58b036a155dab46b898c2d7df04fc2ef245 100644 (file)
@@ -88,8 +88,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        ret = install_special_mapping(mm, addr, PAGE_SIZE,
                                      VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                     VM_ALWAYSDUMP,
+                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                      &vdso_page);
 
        if (ret)
index 7d14bb697d407fc93fa6fd8d2411f61c08adbcf2..d36ee1055f88cf3b06e4c4ee2d683f8bd2f9c918 100644 (file)
@@ -263,17 +263,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
         * the "data" page of the vDSO or you'll stop getting kernel updates
         * and your nice userland gettimeofday will be totally dead.
         * It's fine to use that for setting breakpoints in the vDSO code
-        * pages though
-        *
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
+        * pages though.
         */
        rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
                                     VM_READ|VM_EXEC|
-                                    VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                    VM_ALWAYSDUMP,
+                                    VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                     vdso_pagelist);
        if (rc) {
                current->mm->context.vdso_base = 0;
index e704a9965f902ce808648da176a99d60505ce927..9c80138206b079dc79e61b88d489c56148f47bad 100644 (file)
@@ -241,17 +241,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
         * on the "data" page of the vDSO or you'll stop getting kernel
         * updates and your nice userland gettimeofday will be totally dead.
         * It's fine to use that for setting breakpoints in the vDSO code
-        * pages though
-        *
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
+        * pages though.
         */
        rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
                                     VM_READ|VM_EXEC|
-                                    VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                    VM_ALWAYSDUMP,
+                                    VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                     vdso_pagelist);
        if (rc)
                current->mm->context.vdso_base = 0;
index 1d6d51a1ce7955bb055cc2169b3e22d7c997d3b2..5ca579720a0992322099732c16faa79a1d1b9b75 100644 (file)
@@ -73,8 +73,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        ret = install_special_mapping(mm, addr, PAGE_SIZE,
                                      VM_READ | VM_EXEC |
-                                     VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |
-                                     VM_ALWAYSDUMP,
+                                     VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
                                      syscall_pages);
        if (unlikely(ret))
                goto up_fail;
index 55e58e93bfc58025d4de4815794c2affd9638f9a..1a00fb64fc88316df271121ae6ced4bc96817e2e 100644 (file)
@@ -117,17 +117,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 
        /*
         * MAYWRITE to allow gdb to COW and set breakpoints
-        *
-        * Make sure the vDSO gets into every core dump.  Dumping its
-        * contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to
-        * see what PC values meant.
         */
        vdso_base = VDSO_BASE;
        retval = install_special_mapping(mm, vdso_base, PAGE_SIZE,
                                         VM_READ|VM_EXEC|
-                                        VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                        VM_ALWAYSDUMP,
+                                        VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                         vdso_pages);
 
 #ifndef __tilegx__
index 52edc2b628732552c1e8cc6578acb5fe2a8a0427..432b4291f37b63a8ccab05b81c52a409ecdef9e7 100644 (file)
@@ -381,7 +381,7 @@ int vectors_user_mapping(void)
        return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
                                       VM_READ | VM_EXEC |
                                       VM_MAYREAD | VM_MAYEXEC |
-                                      VM_ALWAYSDUMP | VM_RESERVED,
+                                      VM_RESERVED,
                                       NULL);
 }
 
index 639900a6fde9942a534739c2de8f5451e3082bff..f40281e5d6a27430e5aa018dba8861bcf4a208b6 100644 (file)
@@ -23,14 +23,6 @@ static int __init gate_vma_init(void)
        gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
        gate_vma.vm_page_prot = __P101;
 
-       /*
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
-        */
-       gate_vma.vm_flags |= VM_ALWAYSDUMP;
-
        return 0;
 }
 __initcall(gate_vma_init);
index 91f4ec9a0a56eb2997e51ee339877656be7d6174..af91901babb8455f9ed4a8e10b8f6f8f856d8bec 100644 (file)
@@ -64,8 +64,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
                VM_READ|VM_EXEC|
-               VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-               VM_ALWAYSDUMP,
+               VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                vdsop);
 
        up_write(&mm->mmap_sem);
index 468d591dde3159eaeeab46d09c04805354b95882..a944020fa8593f634b3c81ad28d26c6c1de1241b 100644 (file)
@@ -250,13 +250,7 @@ static int __init gate_vma_init(void)
        gate_vma.vm_end = FIXADDR_USER_END;
        gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
        gate_vma.vm_page_prot = __P101;
-       /*
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
-        */
-       gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
        return 0;
 }
 
@@ -343,17 +337,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
        if (compat_uses_vma || !compat) {
                /*
                 * MAYWRITE to allow gdb to COW and set breakpoints
-                *
-                * Make sure the vDSO gets into every core dump.
-                * Dumping its contents makes post-mortem fully
-                * interpretable later without matching up the same
-                * kernel and hardware config to see what PC values
-                * meant.
                 */
                ret = install_special_mapping(mm, addr, PAGE_SIZE,
                                              VM_READ|VM_EXEC|
-                                             VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                             VM_ALWAYSDUMP,
+                                             VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                              vdso32_pages);
 
                if (ret)
index 153407c35b75bda37e2b5d2675d3abb6280cc9cd..17e18279649f7029d7c2b10881ad155e6a022e00 100644 (file)
@@ -124,8 +124,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        ret = install_special_mapping(mm, addr, vdso_size,
                                      VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                     VM_ALWAYSDUMP,
+                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
                                      vdso_pages);
        if (ret) {
                current->mm->context.vdso = NULL;
index 81878b78c9d4666c2bc7a8d14da15cfbab3037a6..b64be5b5ac218f03714f9c3813698975333a480a 100644 (file)
@@ -1092,6 +1092,29 @@ out:
  * Jeremy Fitzhardinge <jeremy@sw.oz.au>
  */
 
+/*
+ * The purpose of always_dump_vma() is to make sure that special kernel mappings
+ * that are useful for post-mortem analysis are included in every core dump.
+ * In that way we ensure that the core dump is fully interpretable later
+ * without matching up the same kernel and hardware config to see what PC values
+ * meant. These special mappings include - vDSO, vsyscall, and other
+ * architecture specific mappings
+ */
+static bool always_dump_vma(struct vm_area_struct *vma)
+{
+       /* Any vsyscall mappings? */
+       if (vma == get_gate_vma(vma->vm_mm))
+               return true;
+       /*
+        * arch_vma_name() returns non-NULL for special architecture mappings,
+        * such as vDSO sections.
+        */
+       if (arch_vma_name(vma))
+               return true;
+
+       return false;
+}
+
 /*
  * Decide what to dump of a segment, part, all or none.
  */
@@ -1100,8 +1123,8 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
 {
 #define FILTER(type)   (mm_flags & (1UL << MMF_DUMP_##type))
 
-       /* The vma can be set up to tell us the answer directly.  */
-       if (vma->vm_flags & VM_ALWAYSDUMP)
+       /* always dump the vdso and vsyscall sections */
+       if (always_dump_vma(vma))
                goto whole;
 
        /* Hugetlb memory check */
index 7330742e797325e6c55c3c3027518e6ed7e53aeb..2de2ddba51d4c318738031f41254aeb4ac755af0 100644 (file)
@@ -111,7 +111,6 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_HUGEPAGE    0x01000000      /* MADV_HUGEPAGE marked this vma */
 #endif
 #define VM_INSERTPAGE  0x02000000      /* The vma has had "vm_insert_page()" done on it */
-#define VM_ALWAYSDUMP  0x04000000      /* Always include in core dumps */
 
 #define VM_CAN_NONLINEAR 0x08000000    /* Has ->fault & does nonlinear pages */
 #define VM_MIXEDMAP    0x10000000      /* Can contain "struct page" and pure PFN pages */
index 3416b6e018d6a7667fce3168924da3dccdec8e22..6105f475fa8633edf5180792b2cf0c5288734f08 100644 (file)
@@ -3623,13 +3623,7 @@ static int __init gate_vma_init(void)
        gate_vma.vm_end = FIXADDR_USER_END;
        gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
        gate_vma.vm_page_prot = __P101;
-       /*
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
-        */
-       gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
        return 0;
 }
 __initcall(gate_vma_init);