Blob Blame History Raw
Subject: [PATCH] binfmt_elf: Take the mmap lock when walking the VMA list
Date: Mon, 31 Jan 2022 15:37:40 +0000
Message-id: <20220131153740.2396974-1-willy@infradead.org>
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Patch-mainline: never (different fix)
References: bsc#1209039 CVE-2023-1249

mhocko@suse.com:
The upstream fix 390031c94211 ("coredump: Use the vma snapshot in fill_files_note")
has turned out much more complex and much more disruptive to backport to older
code streams. The reference to the upstream discussion is 
https://lore.kernel.org/all/20220131153740.2396974-1-willy@infradead.org/T/#u

I'm not sure if the VMA list can change under us, but dump_vma_snapshot()
is very careful to take the mmap_lock in write mode.  We only need to
take it in read mode here as we do not care if the size of the stack
VMA changes underneath us.

If it can be changed underneath us, this is a potential use-after-free
for a multithreaded process which is dumping core.

Fixes: 2aa362c49c31 ("coredump: extend core dump note section to contain file names of mapped files")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
Signed-off-by: Michal Hocko <mhocko@suse.com>

---
 fs/binfmt_elf.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1602,6 +1602,7 @@ static int fill_files_note(struct memelf
 	name_base = name_curpos = ((char *)data) + names_ofs;
 	remaining = size - names_ofs;
 	count = 0;
+	down_read(&current->mm->mmap_sem);
 	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		struct file *file;
 		const char *filename;
@@ -1612,6 +1613,7 @@ static int fill_files_note(struct memelf
 		filename = file_path(file, name_curpos, remaining);
 		if (IS_ERR(filename)) {
 			if (PTR_ERR(filename) == -ENAMETOOLONG) {
+				up_read(&current->mm->mmap_sem);
 				vfree(data);
 				size = size * 5 / 4;
 				goto alloc;
@@ -1631,6 +1633,7 @@ static int fill_files_note(struct memelf
 		*start_end_ofs++ = vma->vm_pgoff;
 		count++;
 	}
+	up_read(&current->mm->mmap_sem);
 
 	/* Now we know exact count of files, can store it */
 	data[0] = count;