]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
coredump: fix spam with zero VMA process
authorAlexey Dobriyan <adobriyan@gmail.com>
Thu, 14 Jun 2018 22:27:24 +0000 (15:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Jun 2018 22:55:24 +0000 (07:55 +0900)
Nobody ever tried to self destruct by unmapping whole address space at
once:

munmap((void *)0, (1ULL << 47) - 4096);

Doing this produces 2 warnings for zero-length vmalloc allocations:

  a.out[1353]: segfault at 7f80bcc4b757 ip 00007f80bcc4b757 sp 00007fff683939b8 error 14
  a.out: vmalloc: allocation failure: 0 bytes, mode:0xcc0(GFP_KERNEL), nodemask=(null)
...
  a.out: vmalloc: allocation failure: 0 bytes, mode:0xcc0(GFP_KERNEL), nodemask=(null)
...

Fix is to switch to kvmalloc().

Steps to reproduce:

// vsyscall=none
#include <sys/mman.h>
#include <sys/resource.h>
int main(void)
{
setrlimit(RLIMIT_CORE, &(struct rlimit){RLIM_INFINITY, RLIM_INFINITY});
munmap((void *)0, (1ULL << 47) - 4096);
return 0;
}

Link: http://lkml.kernel.org/r/20180410180353.GA2515@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/binfmt_elf.c

index 070b6184642d140bbc25868ced5a3d443d6f6acd..0ac456b52bddb62e9c817d61bccc886c7c8cde85 100644 (file)
@@ -1621,8 +1621,8 @@ static int fill_files_note(struct memelfnote *note)
        if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
                return -EINVAL;
        size = round_up(size, PAGE_SIZE);
-       data = vmalloc(size);
-       if (!data)
+       data = kvmalloc(size, GFP_KERNEL);
+       if (ZERO_OR_NULL_PTR(data))
                return -ENOMEM;
 
        start_end_ofs = data + 2;
@@ -1639,7 +1639,7 @@ static int fill_files_note(struct memelfnote *note)
                filename = file_path(file, name_curpos, remaining);
                if (IS_ERR(filename)) {
                        if (PTR_ERR(filename) == -ENAMETOOLONG) {
-                               vfree(data);
+                               kvfree(data);
                                size = size * 5 / 4;
                                goto alloc;
                        }
@@ -1932,7 +1932,7 @@ static void free_note_info(struct elf_note_info *info)
                kfree(t);
        }
        kfree(info->psinfo.data);
-       vfree(info->files.data);
+       kvfree(info->files.data);
 }
 
 #else
@@ -2148,7 +2148,7 @@ static void free_note_info(struct elf_note_info *info)
 
        /* Free data possibly allocated by fill_files_note(): */
        if (info->notes_files)
-               vfree(info->notes_files->data);
+               kvfree(info->notes_files->data);
 
        kfree(info->prstatus);
        kfree(info->psinfo);
@@ -2294,8 +2294,9 @@ static int elf_core_dump(struct coredump_params *cprm)
 
        if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz))
                goto end_coredump;
-       vma_filesz = vmalloc(array_size(sizeof(*vma_filesz), (segs - 1)));
-       if (!vma_filesz)
+       vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)),
+                             GFP_KERNEL);
+       if (ZERO_OR_NULL_PTR(vma_filesz))
                goto end_coredump;
 
        for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
@@ -2402,7 +2403,7 @@ end_coredump:
 cleanup:
        free_note_info(&info);
        kfree(shdr4extnum);
-       vfree(vma_filesz);
+       kvfree(vma_filesz);
        kfree(phdr4note);
        kfree(elf);
 out: