From: Greg Kroah-Hartman Date: Tue, 5 Apr 2022 06:40:16 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v5.17.2~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2629749847c9b03a052452ffe2c63f76186e8ccf;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: coredump-elf-pass-coredump_params-into-fill_note_info.patch coredump-use-the-vma-snapshot-in-fill_files_note.patch --- diff --git a/queue-5.15/coredump-elf-pass-coredump_params-into-fill_note_info.patch b/queue-5.15/coredump-elf-pass-coredump_params-into-fill_note_info.patch new file mode 100644 index 00000000000..d99c8da00e5 --- /dev/null +++ b/queue-5.15/coredump-elf-pass-coredump_params-into-fill_note_info.patch @@ -0,0 +1,107 @@ +From 9ec7d3230717b4fe9b6c7afeb4811909c23fa1d7 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Mon, 31 Jan 2022 12:17:38 -0600 +Subject: coredump/elf: Pass coredump_params into fill_note_info + +From: Eric W. Biederman + +commit 9ec7d3230717b4fe9b6c7afeb4811909c23fa1d7 upstream. + +Instead of individually passing cprm->siginfo and cprm->regs +into fill_note_info pass all of struct coredump_params. + +This is preparation to allow fill_files_note to use the existing +vma snapshot. + +Reviewed-by: Jann Horn +Reviewed-by: Kees Cook +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + fs/binfmt_elf.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1799,7 +1799,7 @@ static int fill_thread_core_info(struct + + static int fill_note_info(struct elfhdr *elf, int phdrs, + struct elf_note_info *info, +- const kernel_siginfo_t *siginfo, struct pt_regs *regs) ++ struct coredump_params *cprm) + { + struct task_struct *dump_task = current; + const struct user_regset_view *view = task_user_regset_view(dump_task); +@@ -1871,7 +1871,7 @@ static int fill_note_info(struct elfhdr + * Now fill in each thread's information. + */ + for (t = info->thread; t != NULL; t = t->next) +- if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size)) ++ if (!fill_thread_core_info(t, view, cprm->siginfo->si_signo, &info->size)) + return 0; + + /* +@@ -1880,7 +1880,7 @@ static int fill_note_info(struct elfhdr + fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm); + info->size += notesize(&info->psinfo); + +- fill_siginfo_note(&info->signote, &info->csigdata, siginfo); ++ fill_siginfo_note(&info->signote, &info->csigdata, cprm->siginfo); + info->size += notesize(&info->signote); + + fill_auxv_note(&info->auxv, current->mm); +@@ -2028,7 +2028,7 @@ static int elf_note_info_init(struct elf + + static int fill_note_info(struct elfhdr *elf, int phdrs, + struct elf_note_info *info, +- const kernel_siginfo_t *siginfo, struct pt_regs *regs) ++ struct coredump_params *cprm) + { + struct core_thread *ct; + struct elf_thread_status *ets; +@@ -2049,13 +2049,13 @@ static int fill_note_info(struct elfhdr + list_for_each_entry(ets, &info->thread_list, list) { + int sz; + +- sz = elf_dump_thread_status(siginfo->si_signo, ets); ++ sz = elf_dump_thread_status(cprm->siginfo->si_signo, ets); + info->thread_status_size += sz; + } + /* now collect the dump for the current */ + memset(info->prstatus, 0, sizeof(*info->prstatus)); +- fill_prstatus(&info->prstatus->common, current, siginfo->si_signo); +- elf_core_copy_regs(&info->prstatus->pr_reg, regs); ++ fill_prstatus(&info->prstatus->common, current, cprm->siginfo->si_signo); ++ elf_core_copy_regs(&info->prstatus->pr_reg, cprm->regs); + + /* Set up header */ + fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS); +@@ -2071,7 +2071,7 @@ static int fill_note_info(struct elfhdr + fill_note(info->notes + 1, "CORE", NT_PRPSINFO, + sizeof(*info->psinfo), info->psinfo); + +- fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo); ++ fill_siginfo_note(info->notes + 2, &info->csigdata, cprm->siginfo); + fill_auxv_note(info->notes + 3, current->mm); + info->numnote = 4; + +@@ -2081,8 +2081,8 @@ static int fill_note_info(struct elfhdr + } + + /* Try to dump the FPU. */ +- info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, +- info->fpu); ++ info->prstatus->pr_fpvalid = ++ elf_core_copy_task_fpregs(current, cprm->regs, info->fpu); + if (info->prstatus->pr_fpvalid) + fill_note(info->notes + info->numnote++, + "CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu); +@@ -2195,7 +2195,7 @@ static int elf_core_dump(struct coredump + * Collect all the non-memory information about the process for the + * notes. This also sets up the file header. + */ +- if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs)) ++ if (!fill_note_info(&elf, e_phnum, &info, cprm)) + goto end_coredump; + + has_dumped = 1; diff --git a/queue-5.15/coredump-use-the-vma-snapshot-in-fill_files_note.patch b/queue-5.15/coredump-use-the-vma-snapshot-in-fill_files_note.patch new file mode 100644 index 00000000000..cbbbde10892 --- /dev/null +++ b/queue-5.15/coredump-use-the-vma-snapshot-in-fill_files_note.patch @@ -0,0 +1,176 @@ +From 390031c942116d4733310f0684beb8db19885fe6 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Tue, 8 Mar 2022 13:04:19 -0600 +Subject: coredump: Use the vma snapshot in fill_files_note + +From: Eric W. Biederman + +commit 390031c942116d4733310f0684beb8db19885fe6 upstream. + +Matthew Wilcox reported that there is a missing mmap_lock in +file_files_note that could possibly lead to a user after free. + +Solve this by using the existing vma snapshot for consistency +and to avoid the need to take the mmap_lock anywhere in the +coredump code except for dump_vma_snapshot. + +Update the dump_vma_snapshot to capture vm_pgoff and vm_file +that are neeeded by fill_files_note. + +Add free_vma_snapshot to free the captured values of vm_file. + +Reported-by: Matthew Wilcox +Link: https://lkml.kernel.org/r/20220131153740.2396974-1-willy@infradead.org +Cc: stable@vger.kernel.org +Fixes: a07279c9a8cd ("binfmt_elf, binfmt_elf_fdpic: use a VMA list snapshot") +Fixes: 2aa362c49c31 ("coredump: extend core dump note section to contain file names of mapped files") +Reviewed-by: Kees Cook +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + fs/binfmt_elf.c | 24 ++++++++++++------------ + fs/coredump.c | 22 +++++++++++++++++++++- + include/linux/coredump.h | 2 ++ + 3 files changed, 35 insertions(+), 13 deletions(-) + +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1618,17 +1618,16 @@ static void fill_siginfo_note(struct mem + * long file_ofs + * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... + */ +-static int fill_files_note(struct memelfnote *note) ++static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm) + { +- struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; + unsigned count, size, names_ofs, remaining, n; + user_long_t *data; + user_long_t *start_end_ofs; + char *name_base, *name_curpos; ++ int i; + + /* *Estimated* file count and total data size needed */ +- count = mm->map_count; ++ count = cprm->vma_count; + if (count > UINT_MAX / 64) + return -EINVAL; + size = count * 64; +@@ -1650,11 +1649,12 @@ static int fill_files_note(struct memelf + name_base = name_curpos = ((char *)data) + names_ofs; + remaining = size - names_ofs; + count = 0; +- for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) { ++ for (i = 0; i < cprm->vma_count; i++) { ++ struct core_vma_metadata *m = &cprm->vma_meta[i]; + struct file *file; + const char *filename; + +- file = vma->vm_file; ++ file = m->file; + if (!file) + continue; + filename = file_path(file, name_curpos, remaining); +@@ -1674,9 +1674,9 @@ static int fill_files_note(struct memelf + memmove(name_curpos, filename, n); + name_curpos += n; + +- *start_end_ofs++ = vma->vm_start; +- *start_end_ofs++ = vma->vm_end; +- *start_end_ofs++ = vma->vm_pgoff; ++ *start_end_ofs++ = m->start; ++ *start_end_ofs++ = m->end; ++ *start_end_ofs++ = m->pgoff; + count++; + } + +@@ -1687,7 +1687,7 @@ static int fill_files_note(struct memelf + * Count usually is less than mm->map_count, + * we need to move filenames down. + */ +- n = mm->map_count - count; ++ n = cprm->vma_count - count; + if (n != 0) { + unsigned shift_bytes = n * 3 * sizeof(data[0]); + memmove(name_base - shift_bytes, name_base, +@@ -1886,7 +1886,7 @@ static int fill_note_info(struct elfhdr + fill_auxv_note(&info->auxv, current->mm); + info->size += notesize(&info->auxv); + +- if (fill_files_note(&info->files) == 0) ++ if (fill_files_note(&info->files, cprm) == 0) + info->size += notesize(&info->files); + + return 1; +@@ -2075,7 +2075,7 @@ static int fill_note_info(struct elfhdr + fill_auxv_note(info->notes + 3, current->mm); + info->numnote = 4; + +- if (fill_files_note(info->notes + info->numnote) == 0) { ++ if (fill_files_note(info->notes + info->numnote, cprm) == 0) { + info->notes_files = info->notes + info->numnote; + info->numnote++; + } +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -54,6 +54,7 @@ + #include + + static bool dump_vma_snapshot(struct coredump_params *cprm); ++static void free_vma_snapshot(struct coredump_params *cprm); + + int core_uses_pid; + unsigned int core_pipe_limit; +@@ -834,7 +835,7 @@ void do_coredump(const kernel_siginfo_t + dump_emit(&cprm, "", 1); + } + file_end_write(cprm.file); +- kvfree(cprm.vma_meta); ++ free_vma_snapshot(&cprm); + } + if (ispipe && core_pipe_limit) + wait_for_dump_helpers(cprm.file); +@@ -1111,6 +1112,20 @@ static struct vm_area_struct *next_vma(s + return gate_vma; + } + ++static void free_vma_snapshot(struct coredump_params *cprm) ++{ ++ if (cprm->vma_meta) { ++ int i; ++ for (i = 0; i < cprm->vma_count; i++) { ++ struct file *file = cprm->vma_meta[i].file; ++ if (file) ++ fput(file); ++ } ++ kvfree(cprm->vma_meta); ++ cprm->vma_meta = NULL; ++ } ++} ++ + /* + * Under the mmap_lock, take a snapshot of relevant information about the task's + * VMAs. +@@ -1147,6 +1162,11 @@ static bool dump_vma_snapshot(struct cor + m->end = vma->vm_end; + m->flags = vma->vm_flags; + m->dump_size = vma_dump_size(vma, cprm->mm_flags); ++ m->pgoff = vma->vm_pgoff; ++ ++ m->file = vma->vm_file; ++ if (m->file) ++ get_file(m->file); + } + + mmap_write_unlock(mm); +--- a/include/linux/coredump.h ++++ b/include/linux/coredump.h +@@ -12,6 +12,8 @@ struct core_vma_metadata { + unsigned long start, end; + unsigned long flags; + unsigned long dump_size; ++ unsigned long pgoff; ++ struct file *file; + }; + + extern int core_uses_pid; diff --git a/queue-5.15/series b/queue-5.15/series index e6e99ffdc86..0aa8474b09b 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -909,3 +909,5 @@ swiotlb-support-aligned-swiotlb-buffers.patch iommu-dma-account-for-min_align_mask-w-swiotlb.patch coredump-snapshot-the-vmas-in-do_coredump.patch coredump-remove-the-warn_on-in-dump_vma_snapshot.patch +coredump-elf-pass-coredump_params-into-fill_note_info.patch +coredump-use-the-vma-snapshot-in-fill_files_note.patch