]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Apr 2022 06:40:09 +0000 (08:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Apr 2022 06:40:09 +0000 (08:40 +0200)
added patches:
coredump-elf-pass-coredump_params-into-fill_note_info.patch
coredump-use-the-vma-snapshot-in-fill_files_note.patch

queue-5.10/coredump-elf-pass-coredump_params-into-fill_note_info.patch [new file with mode: 0644]
queue-5.10/coredump-use-the-vma-snapshot-in-fill_files_note.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/coredump-elf-pass-coredump_params-into-fill_note_info.patch b/queue-5.10/coredump-elf-pass-coredump_params-into-fill_note_info.patch
new file mode 100644 (file)
index 0000000..bdc2013
--- /dev/null
@@ -0,0 +1,90 @@
+From 9ec7d3230717b4fe9b6c7afeb4811909c23fa1d7 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Mon, 31 Jan 2022 12:17:38 -0600
+Subject: coredump/elf: Pass coredump_params into fill_note_info
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <jannh@google.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_elf.c |   16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -1797,7 +1797,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);
+@@ -1869,7 +1869,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;
+       /*
+@@ -1878,7 +1878,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);
+@@ -2026,7 +2026,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;
+@@ -2069,7 +2069,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;
+@@ -2079,8 +2079,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);
+@@ -2193,7 +2193,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.10/coredump-use-the-vma-snapshot-in-fill_files_note.patch b/queue-5.10/coredump-use-the-vma-snapshot-in-fill_files_note.patch
new file mode 100644 (file)
index 0000000..2fead55
--- /dev/null
@@ -0,0 +1,176 @@
+From 390031c942116d4733310f0684beb8db19885fe6 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 8 Mar 2022 13:04:19 -0600
+Subject: coredump: Use the vma snapshot in fill_files_note
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <willy@infradead.org>
+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 <keescook@chromium.org>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -1613,17 +1613,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;
+@@ -1645,11 +1644,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);
+@@ -1669,9 +1669,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++;
+       }
+@@ -1682,7 +1682,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,
+@@ -1884,7 +1884,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;
+@@ -2073,7 +2073,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 <trace/events/sched.h>
+ 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;
+@@ -816,7 +817,7 @@ void do_coredump(const kernel_siginfo_t
+               file_start_write(cprm.file);
+               core_dumped = binfmt->core_dump(&cprm);
+               file_end_write(cprm.file);
+-              kvfree(cprm.vma_meta);
++              free_vma_snapshot(&cprm);
+       }
+       if (ispipe && core_pipe_limit)
+               wait_for_dump_helpers(cprm.file);
+@@ -1088,6 +1089,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.
+@@ -1124,6 +1139,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
+@@ -11,6 +11,8 @@ struct core_vma_metadata {
+       unsigned long start, end;
+       unsigned long flags;
+       unsigned long dump_size;
++      unsigned long pgoff;
++      struct file   *file;
+ };
+ /*
index 869dd1f3db41f3a3a2fc2d7d97064dbc1c602940..22a1271f0917f0e476b8aee315481b16d1349708 100644 (file)
@@ -594,3 +594,5 @@ can-m_can-m_can_tx_handler-fix-use-after-free-of-skb.patch
 can-usb_8dev-usb_8dev_start_xmit-fix-double-dev_kfree_skb-in-error-path.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