Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86a2bb5a authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Linus Torvalds
Browse files

coredump: fix spam with zero VMA process

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: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Reviewed-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c2574aaa
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -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 @@ static int elf_core_dump(struct coredump_params *cprm)
cleanup:
	free_note_info(&info);
	kfree(shdr4extnum);
	vfree(vma_filesz);
	kvfree(vma_filesz);
	kfree(phdr4note);
	kfree(elf);
out: