*   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;
        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);
                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++;
        }
 
         * 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,
        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;
        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++;
        }
 
 #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;
                        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);
        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.
                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);