]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.17-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Apr 2022 06:25:22 +0000 (08:25 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Apr 2022 06:25:22 +0000 (08:25 +0200)
added patches:
coredump-remove-the-warn_on-in-dump_vma_snapshot.patch
coredump-snapshot-the-vmas-in-do_coredump.patch

queue-5.17/coredump-remove-the-warn_on-in-dump_vma_snapshot.patch [new file with mode: 0644]
queue-5.17/coredump-snapshot-the-vmas-in-do_coredump.patch [new file with mode: 0644]
queue-5.17/series

diff --git a/queue-5.17/coredump-remove-the-warn_on-in-dump_vma_snapshot.patch b/queue-5.17/coredump-remove-the-warn_on-in-dump_vma_snapshot.patch
new file mode 100644 (file)
index 0000000..8d548dd
--- /dev/null
@@ -0,0 +1,41 @@
+From 49c1866348f364478a0c4d3dd13fd08bb82d3a5b Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 8 Mar 2022 13:01:19 -0600
+Subject: coredump: Remove the WARN_ON in dump_vma_snapshot
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 49c1866348f364478a0c4d3dd13fd08bb82d3a5b upstream.
+
+The condition is impossible and to the best of my knowledge has never
+triggered.
+
+We are in deep trouble if that conditions happens and we walk past
+the end of our allocated array.
+
+So delete the WARN_ON and the code that makes it look like the kernel
+can handle the case of walking past the end of it's vma_meta array.
+
+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/coredump.c |    6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/fs/coredump.c
++++ b/fs/coredump.c
+@@ -1139,12 +1139,6 @@ static bool dump_vma_snapshot(struct cor
+       mmap_write_unlock(mm);
+-      if (WARN_ON(i != cprm->vma_count)) {
+-              kvfree(cprm->vma_meta);
+-              return false;
+-      }
+-
+-
+       for (i = 0; i < cprm->vma_count; i++) {
+               struct core_vma_metadata *m = cprm->vma_meta + i;
diff --git a/queue-5.17/coredump-snapshot-the-vmas-in-do_coredump.patch b/queue-5.17/coredump-snapshot-the-vmas-in-do_coredump.patch
new file mode 100644 (file)
index 0000000..ae82a2f
--- /dev/null
@@ -0,0 +1,312 @@
+From 95c5436a4883841588dae86fb0b9325f47ba5ad3 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 8 Mar 2022 12:55:29 -0600
+Subject: coredump: Snapshot the vmas in do_coredump
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 95c5436a4883841588dae86fb0b9325f47ba5ad3 upstream.
+
+Move the call of dump_vma_snapshot and kvfree(vma_meta) out of the
+individual coredump routines into do_coredump itself.  This makes
+the code less error prone and easier to maintain.
+
+Make the vma snapshot available to the coredump routines
+in struct coredump_params.  This makes it easier to
+change and update what is captures in the vma snapshot
+and will be needed for fixing fill_file_notes.
+
+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          |   20 +++++++-------------
+ fs/binfmt_elf_fdpic.c    |   18 ++++++------------
+ fs/coredump.c            |   41 +++++++++++++++++++++++------------------
+ include/linux/binfmts.h  |    3 +++
+ include/linux/coredump.h |    3 ---
+ 5 files changed, 39 insertions(+), 46 deletions(-)
+
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -2192,8 +2192,7 @@ static void fill_extnum_info(struct elfh
+ static int elf_core_dump(struct coredump_params *cprm)
+ {
+       int has_dumped = 0;
+-      int vma_count, segs, i;
+-      size_t vma_data_size;
++      int segs, i;
+       struct elfhdr elf;
+       loff_t offset = 0, dataoff;
+       struct elf_note_info info = { };
+@@ -2201,16 +2200,12 @@ static int elf_core_dump(struct coredump
+       struct elf_shdr *shdr4extnum = NULL;
+       Elf_Half e_phnum;
+       elf_addr_t e_shoff;
+-      struct core_vma_metadata *vma_meta;
+-
+-      if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
+-              return 0;
+       /*
+        * The number of segs are recored into ELF header as 16bit value.
+        * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
+        */
+-      segs = vma_count + elf_core_extra_phdrs();
++      segs = cprm->vma_count + elf_core_extra_phdrs();
+       /* for notes section */
+       segs++;
+@@ -2249,7 +2244,7 @@ static int elf_core_dump(struct coredump
+       dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+-      offset += vma_data_size;
++      offset += cprm->vma_data_size;
+       offset += elf_core_extra_data_size();
+       e_shoff = offset;
+@@ -2269,8 +2264,8 @@ static int elf_core_dump(struct coredump
+               goto end_coredump;
+       /* Write program headers for segments dump */
+-      for (i = 0; i < vma_count; i++) {
+-              struct core_vma_metadata *meta = vma_meta + i;
++      for (i = 0; i < cprm->vma_count; i++) {
++              struct core_vma_metadata *meta = cprm->vma_meta + i;
+               struct elf_phdr phdr;
+               phdr.p_type = PT_LOAD;
+@@ -2307,8 +2302,8 @@ static int elf_core_dump(struct coredump
+       /* Align to page */
+       dump_skip_to(cprm, dataoff);
+-      for (i = 0; i < vma_count; i++) {
+-              struct core_vma_metadata *meta = vma_meta + i;
++      for (i = 0; i < cprm->vma_count; i++) {
++              struct core_vma_metadata *meta = cprm->vma_meta + i;
+               if (!dump_user_range(cprm, meta->start, meta->dump_size))
+                       goto end_coredump;
+@@ -2325,7 +2320,6 @@ static int elf_core_dump(struct coredump
+ end_coredump:
+       free_note_info(&info);
+       kfree(shdr4extnum);
+-      kvfree(vma_meta);
+       kfree(phdr4note);
+       return has_dumped;
+ }
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -1465,7 +1465,7 @@ static bool elf_fdpic_dump_segments(stru
+ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ {
+       int has_dumped = 0;
+-      int vma_count, segs;
++      int segs;
+       int i;
+       struct elfhdr *elf = NULL;
+       loff_t offset = 0, dataoff;
+@@ -1480,8 +1480,6 @@ static int elf_fdpic_core_dump(struct co
+       elf_addr_t e_shoff;
+       struct core_thread *ct;
+       struct elf_thread_status *tmp;
+-      struct core_vma_metadata *vma_meta = NULL;
+-      size_t vma_data_size;
+       /* alloc memory for large data structures: too large to be on stack */
+       elf = kmalloc(sizeof(*elf), GFP_KERNEL);
+@@ -1491,9 +1489,6 @@ static int elf_fdpic_core_dump(struct co
+       if (!psinfo)
+               goto end_coredump;
+-      if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
+-              goto end_coredump;
+-
+       for (ct = current->signal->core_state->dumper.next;
+                                       ct; ct = ct->next) {
+               tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
+@@ -1513,7 +1508,7 @@ static int elf_fdpic_core_dump(struct co
+       tmp->next = thread_list;
+       thread_list = tmp;
+-      segs = vma_count + elf_core_extra_phdrs();
++      segs = cprm->vma_count + elf_core_extra_phdrs();
+       /* for notes section */
+       segs++;
+@@ -1558,7 +1553,7 @@ static int elf_fdpic_core_dump(struct co
+       /* Page-align dumped data */
+       dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+-      offset += vma_data_size;
++      offset += cprm->vma_data_size;
+       offset += elf_core_extra_data_size();
+       e_shoff = offset;
+@@ -1578,8 +1573,8 @@ static int elf_fdpic_core_dump(struct co
+               goto end_coredump;
+       /* write program headers for segments dump */
+-      for (i = 0; i < vma_count; i++) {
+-              struct core_vma_metadata *meta = vma_meta + i;
++      for (i = 0; i < cprm->vma_count; i++) {
++              struct core_vma_metadata *meta = cprm->vma_meta + i;
+               struct elf_phdr phdr;
+               size_t sz;
+@@ -1628,7 +1623,7 @@ static int elf_fdpic_core_dump(struct co
+       dump_skip_to(cprm, dataoff);
+-      if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count))
++      if (!elf_fdpic_dump_segments(cprm, cprm->vma_meta, cprm->vma_count))
+               goto end_coredump;
+       if (!elf_core_write_extra_data(cprm))
+@@ -1652,7 +1647,6 @@ end_coredump:
+               thread_list = thread_list->next;
+               kfree(tmp);
+       }
+-      kvfree(vma_meta);
+       kfree(phdr4note);
+       kfree(elf);
+       kfree(psinfo);
+--- a/fs/coredump.c
++++ b/fs/coredump.c
+@@ -54,6 +54,8 @@
+ #include <trace/events/sched.h>
++static bool dump_vma_snapshot(struct coredump_params *cprm);
++
+ static int core_uses_pid;
+ static unsigned int core_pipe_limit;
+ static char core_pattern[CORENAME_MAX_SIZE] = "core";
+@@ -532,6 +534,7 @@ void do_coredump(const kernel_siginfo_t
+                * by any locks.
+                */
+               .mm_flags = mm->flags,
++              .vma_meta = NULL,
+       };
+       audit_core_dumps(siginfo->si_signo);
+@@ -746,6 +749,9 @@ void do_coredump(const kernel_siginfo_t
+                       pr_info("Core dump to |%s disabled\n", cn.corename);
+                       goto close_fail;
+               }
++              if (!dump_vma_snapshot(&cprm))
++                      goto close_fail;
++
+               file_start_write(cprm.file);
+               core_dumped = binfmt->core_dump(&cprm);
+               /*
+@@ -759,6 +765,7 @@ void do_coredump(const kernel_siginfo_t
+                       dump_emit(&cprm, "", 1);
+               }
+               file_end_write(cprm.file);
++              kvfree(cprm.vma_meta);
+       }
+       if (ispipe && core_pipe_limit)
+               wait_for_dump_helpers(cprm.file);
+@@ -1096,14 +1103,11 @@ static struct vm_area_struct *next_vma(s
+  * Under the mmap_lock, take a snapshot of relevant information about the task's
+  * VMAs.
+  */
+-int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
+-                    struct core_vma_metadata **vma_meta,
+-                    size_t *vma_data_size_ptr)
++static bool dump_vma_snapshot(struct coredump_params *cprm)
+ {
+       struct vm_area_struct *vma, *gate_vma;
+       struct mm_struct *mm = current->mm;
+       int i;
+-      size_t vma_data_size = 0;
+       /*
+        * Once the stack expansion code is fixed to not change VMA bounds
+@@ -1111,20 +1115,21 @@ int dump_vma_snapshot(struct coredump_pa
+        * mmap_lock in read mode.
+        */
+       if (mmap_write_lock_killable(mm))
+-              return -EINTR;
++              return false;
++      cprm->vma_data_size = 0;
+       gate_vma = get_gate_vma(mm);
+-      *vma_count = mm->map_count + (gate_vma ? 1 : 0);
++      cprm->vma_count = mm->map_count + (gate_vma ? 1 : 0);
+-      *vma_meta = kvmalloc_array(*vma_count, sizeof(**vma_meta), GFP_KERNEL);
+-      if (!*vma_meta) {
++      cprm->vma_meta = kvmalloc_array(cprm->vma_count, sizeof(*cprm->vma_meta), GFP_KERNEL);
++      if (!cprm->vma_meta) {
+               mmap_write_unlock(mm);
+-              return -ENOMEM;
++              return false;
+       }
+       for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
+                       vma = next_vma(vma, gate_vma), i++) {
+-              struct core_vma_metadata *m = (*vma_meta) + i;
++              struct core_vma_metadata *m = cprm->vma_meta + i;
+               m->start = vma->vm_start;
+               m->end = vma->vm_end;
+@@ -1134,13 +1139,14 @@ int dump_vma_snapshot(struct coredump_pa
+       mmap_write_unlock(mm);
+-      if (WARN_ON(i != *vma_count)) {
+-              kvfree(*vma_meta);
+-              return -EFAULT;
++      if (WARN_ON(i != cprm->vma_count)) {
++              kvfree(cprm->vma_meta);
++              return false;
+       }
+-      for (i = 0; i < *vma_count; i++) {
+-              struct core_vma_metadata *m = (*vma_meta) + i;
++
++      for (i = 0; i < cprm->vma_count; i++) {
++              struct core_vma_metadata *m = cprm->vma_meta + i;
+               if (m->dump_size == DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER) {
+                       char elfmag[SELFMAG];
+@@ -1153,9 +1159,8 @@ int dump_vma_snapshot(struct coredump_pa
+                       }
+               }
+-              vma_data_size += m->dump_size;
++              cprm->vma_data_size += m->dump_size;
+       }
+-      *vma_data_size_ptr = vma_data_size;
+-      return 0;
++      return true;
+ }
+--- a/include/linux/binfmts.h
++++ b/include/linux/binfmts.h
+@@ -87,6 +87,9 @@ struct coredump_params {
+       loff_t written;
+       loff_t pos;
+       loff_t to_skip;
++      int vma_count;
++      size_t vma_data_size;
++      struct core_vma_metadata *vma_meta;
+ };
+ /*
+--- a/include/linux/coredump.h
++++ b/include/linux/coredump.h
+@@ -25,9 +25,6 @@ extern int dump_emit(struct coredump_par
+ extern int dump_align(struct coredump_params *cprm, int align);
+ int dump_user_range(struct coredump_params *cprm, unsigned long start,
+                   unsigned long len);
+-int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
+-                    struct core_vma_metadata **vma_meta,
+-                    size_t *vma_data_size_ptr);
+ extern void do_coredump(const kernel_siginfo_t *siginfo);
+ #else
+ static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
index 7c7b71a148dae0a8679bc5fdc5003d66b6cf56c5..9d40df1e891a049932ae633103623e3199063141 100644 (file)
@@ -1121,3 +1121,4 @@ revert-nbd-fix-possible-overflow-on-first_minor-in-nbd_dev_add.patch
 mmc-rtsx-let-mmc-core-handle-runtime-pm.patch
 mmc-rtsx-fix-build-errors-warnings-for-unused-variable.patch
 coredump-snapshot-the-vmas-in-do_coredump.patch
+coredump-remove-the-warn_on-in-dump_vma_snapshot.patch