Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  fs/proc/vmcore.c Interface for accessing the crash
0004  *               dump from the system's previous life.
0005  *  Heavily borrowed from fs/proc/kcore.c
0006  *  Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
0007  *  Copyright (C) IBM Corporation, 2004. All rights reserved
0008  *
0009  */
0010 
0011 #include <linux/mm.h>
0012 #include <linux/kcore.h>
0013 #include <linux/user.h>
0014 #include <linux/elf.h>
0015 #include <linux/elfcore.h>
0016 #include <linux/export.h>
0017 #include <linux/slab.h>
0018 #include <linux/highmem.h>
0019 #include <linux/printk.h>
0020 #include <linux/memblock.h>
0021 #include <linux/init.h>
0022 #include <linux/crash_dump.h>
0023 #include <linux/list.h>
0024 #include <linux/moduleparam.h>
0025 #include <linux/mutex.h>
0026 #include <linux/vmalloc.h>
0027 #include <linux/pagemap.h>
0028 #include <linux/uio.h>
0029 #include <linux/cc_platform.h>
0030 #include <asm/io.h>
0031 #include "internal.h"
0032 
0033 /* List representing chunks of contiguous memory areas and their offsets in
0034  * vmcore file.
0035  */
0036 static LIST_HEAD(vmcore_list);
0037 
0038 /* Stores the pointer to the buffer containing kernel elf core headers. */
0039 static char *elfcorebuf;
0040 static size_t elfcorebuf_sz;
0041 static size_t elfcorebuf_sz_orig;
0042 
0043 static char *elfnotes_buf;
0044 static size_t elfnotes_sz;
0045 /* Size of all notes minus the device dump notes */
0046 static size_t elfnotes_orig_sz;
0047 
0048 /* Total size of vmcore file. */
0049 static u64 vmcore_size;
0050 
0051 static struct proc_dir_entry *proc_vmcore;
0052 
0053 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
0054 /* Device Dump list and mutex to synchronize access to list */
0055 static LIST_HEAD(vmcoredd_list);
0056 static DEFINE_MUTEX(vmcoredd_mutex);
0057 
0058 static bool vmcoredd_disabled;
0059 core_param(novmcoredd, vmcoredd_disabled, bool, 0);
0060 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
0061 
0062 /* Device Dump Size */
0063 static size_t vmcoredd_orig_sz;
0064 
0065 static DEFINE_SPINLOCK(vmcore_cb_lock);
0066 DEFINE_STATIC_SRCU(vmcore_cb_srcu);
0067 /* List of registered vmcore callbacks. */
0068 static LIST_HEAD(vmcore_cb_list);
0069 /* Whether the vmcore has been opened once. */
0070 static bool vmcore_opened;
0071 
0072 void register_vmcore_cb(struct vmcore_cb *cb)
0073 {
0074     INIT_LIST_HEAD(&cb->next);
0075     spin_lock(&vmcore_cb_lock);
0076     list_add_tail(&cb->next, &vmcore_cb_list);
0077     /*
0078      * Registering a vmcore callback after the vmcore was opened is
0079      * very unusual (e.g., manual driver loading).
0080      */
0081     if (vmcore_opened)
0082         pr_warn_once("Unexpected vmcore callback registration\n");
0083     spin_unlock(&vmcore_cb_lock);
0084 }
0085 EXPORT_SYMBOL_GPL(register_vmcore_cb);
0086 
0087 void unregister_vmcore_cb(struct vmcore_cb *cb)
0088 {
0089     spin_lock(&vmcore_cb_lock);
0090     list_del_rcu(&cb->next);
0091     /*
0092      * Unregistering a vmcore callback after the vmcore was opened is
0093      * very unusual (e.g., forced driver removal), but we cannot stop
0094      * unregistering.
0095      */
0096     if (vmcore_opened)
0097         pr_warn_once("Unexpected vmcore callback unregistration\n");
0098     spin_unlock(&vmcore_cb_lock);
0099 
0100     synchronize_srcu(&vmcore_cb_srcu);
0101 }
0102 EXPORT_SYMBOL_GPL(unregister_vmcore_cb);
0103 
0104 static bool pfn_is_ram(unsigned long pfn)
0105 {
0106     struct vmcore_cb *cb;
0107     bool ret = true;
0108 
0109     list_for_each_entry_srcu(cb, &vmcore_cb_list, next,
0110                  srcu_read_lock_held(&vmcore_cb_srcu)) {
0111         if (unlikely(!cb->pfn_is_ram))
0112             continue;
0113         ret = cb->pfn_is_ram(cb, pfn);
0114         if (!ret)
0115             break;
0116     }
0117 
0118     return ret;
0119 }
0120 
0121 static int open_vmcore(struct inode *inode, struct file *file)
0122 {
0123     spin_lock(&vmcore_cb_lock);
0124     vmcore_opened = true;
0125     spin_unlock(&vmcore_cb_lock);
0126 
0127     return 0;
0128 }
0129 
0130 /* Reads a page from the oldmem device from given offset. */
0131 ssize_t read_from_oldmem(struct iov_iter *iter, size_t count,
0132              u64 *ppos, bool encrypted)
0133 {
0134     unsigned long pfn, offset;
0135     size_t nr_bytes;
0136     ssize_t read = 0, tmp;
0137     int idx;
0138 
0139     if (!count)
0140         return 0;
0141 
0142     offset = (unsigned long)(*ppos % PAGE_SIZE);
0143     pfn = (unsigned long)(*ppos / PAGE_SIZE);
0144 
0145     idx = srcu_read_lock(&vmcore_cb_srcu);
0146     do {
0147         if (count > (PAGE_SIZE - offset))
0148             nr_bytes = PAGE_SIZE - offset;
0149         else
0150             nr_bytes = count;
0151 
0152         /* If pfn is not ram, return zeros for sparse dump files */
0153         if (!pfn_is_ram(pfn)) {
0154             tmp = iov_iter_zero(nr_bytes, iter);
0155         } else {
0156             if (encrypted)
0157                 tmp = copy_oldmem_page_encrypted(iter, pfn,
0158                                  nr_bytes,
0159                                  offset);
0160             else
0161                 tmp = copy_oldmem_page(iter, pfn, nr_bytes,
0162                                offset);
0163         }
0164         if (tmp < nr_bytes) {
0165             srcu_read_unlock(&vmcore_cb_srcu, idx);
0166             return -EFAULT;
0167         }
0168 
0169         *ppos += nr_bytes;
0170         count -= nr_bytes;
0171         read += nr_bytes;
0172         ++pfn;
0173         offset = 0;
0174     } while (count);
0175     srcu_read_unlock(&vmcore_cb_srcu, idx);
0176 
0177     return read;
0178 }
0179 
0180 /*
0181  * Architectures may override this function to allocate ELF header in 2nd kernel
0182  */
0183 int __weak elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
0184 {
0185     return 0;
0186 }
0187 
0188 /*
0189  * Architectures may override this function to free header
0190  */
0191 void __weak elfcorehdr_free(unsigned long long addr)
0192 {}
0193 
0194 /*
0195  * Architectures may override this function to read from ELF header
0196  */
0197 ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos)
0198 {
0199     struct kvec kvec = { .iov_base = buf, .iov_len = count };
0200     struct iov_iter iter;
0201 
0202     iov_iter_kvec(&iter, READ, &kvec, 1, count);
0203 
0204     return read_from_oldmem(&iter, count, ppos, false);
0205 }
0206 
0207 /*
0208  * Architectures may override this function to read from notes sections
0209  */
0210 ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
0211 {
0212     struct kvec kvec = { .iov_base = buf, .iov_len = count };
0213     struct iov_iter iter;
0214 
0215     iov_iter_kvec(&iter, READ, &kvec, 1, count);
0216 
0217     return read_from_oldmem(&iter, count, ppos,
0218             cc_platform_has(CC_ATTR_MEM_ENCRYPT));
0219 }
0220 
0221 /*
0222  * Architectures may override this function to map oldmem
0223  */
0224 int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma,
0225                   unsigned long from, unsigned long pfn,
0226                   unsigned long size, pgprot_t prot)
0227 {
0228     prot = pgprot_encrypted(prot);
0229     return remap_pfn_range(vma, from, pfn, size, prot);
0230 }
0231 
0232 /*
0233  * Architectures which support memory encryption override this.
0234  */
0235 ssize_t __weak copy_oldmem_page_encrypted(struct iov_iter *iter,
0236         unsigned long pfn, size_t csize, unsigned long offset)
0237 {
0238     return copy_oldmem_page(iter, pfn, csize, offset);
0239 }
0240 
0241 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
0242 static int vmcoredd_copy_dumps(struct iov_iter *iter, u64 start, size_t size)
0243 {
0244     struct vmcoredd_node *dump;
0245     u64 offset = 0;
0246     int ret = 0;
0247     size_t tsz;
0248     char *buf;
0249 
0250     mutex_lock(&vmcoredd_mutex);
0251     list_for_each_entry(dump, &vmcoredd_list, list) {
0252         if (start < offset + dump->size) {
0253             tsz = min(offset + (u64)dump->size - start, (u64)size);
0254             buf = dump->buf + start - offset;
0255             if (copy_to_iter(buf, tsz, iter) < tsz) {
0256                 ret = -EFAULT;
0257                 goto out_unlock;
0258             }
0259 
0260             size -= tsz;
0261             start += tsz;
0262 
0263             /* Leave now if buffer filled already */
0264             if (!size)
0265                 goto out_unlock;
0266         }
0267         offset += dump->size;
0268     }
0269 
0270 out_unlock:
0271     mutex_unlock(&vmcoredd_mutex);
0272     return ret;
0273 }
0274 
0275 #ifdef CONFIG_MMU
0276 static int vmcoredd_mmap_dumps(struct vm_area_struct *vma, unsigned long dst,
0277                    u64 start, size_t size)
0278 {
0279     struct vmcoredd_node *dump;
0280     u64 offset = 0;
0281     int ret = 0;
0282     size_t tsz;
0283     char *buf;
0284 
0285     mutex_lock(&vmcoredd_mutex);
0286     list_for_each_entry(dump, &vmcoredd_list, list) {
0287         if (start < offset + dump->size) {
0288             tsz = min(offset + (u64)dump->size - start, (u64)size);
0289             buf = dump->buf + start - offset;
0290             if (remap_vmalloc_range_partial(vma, dst, buf, 0,
0291                             tsz)) {
0292                 ret = -EFAULT;
0293                 goto out_unlock;
0294             }
0295 
0296             size -= tsz;
0297             start += tsz;
0298             dst += tsz;
0299 
0300             /* Leave now if buffer filled already */
0301             if (!size)
0302                 goto out_unlock;
0303         }
0304         offset += dump->size;
0305     }
0306 
0307 out_unlock:
0308     mutex_unlock(&vmcoredd_mutex);
0309     return ret;
0310 }
0311 #endif /* CONFIG_MMU */
0312 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
0313 
0314 /* Read from the ELF header and then the crash dump. On error, negative value is
0315  * returned otherwise number of bytes read are returned.
0316  */
0317 static ssize_t __read_vmcore(struct iov_iter *iter, loff_t *fpos)
0318 {
0319     ssize_t acc = 0, tmp;
0320     size_t tsz;
0321     u64 start;
0322     struct vmcore *m = NULL;
0323 
0324     if (!iov_iter_count(iter) || *fpos >= vmcore_size)
0325         return 0;
0326 
0327     iov_iter_truncate(iter, vmcore_size - *fpos);
0328 
0329     /* Read ELF core header */
0330     if (*fpos < elfcorebuf_sz) {
0331         tsz = min(elfcorebuf_sz - (size_t)*fpos, iov_iter_count(iter));
0332         if (copy_to_iter(elfcorebuf + *fpos, tsz, iter) < tsz)
0333             return -EFAULT;
0334         *fpos += tsz;
0335         acc += tsz;
0336 
0337         /* leave now if filled buffer already */
0338         if (!iov_iter_count(iter))
0339             return acc;
0340     }
0341 
0342     /* Read Elf note segment */
0343     if (*fpos < elfcorebuf_sz + elfnotes_sz) {
0344         void *kaddr;
0345 
0346         /* We add device dumps before other elf notes because the
0347          * other elf notes may not fill the elf notes buffer
0348          * completely and we will end up with zero-filled data
0349          * between the elf notes and the device dumps. Tools will
0350          * then try to decode this zero-filled data as valid notes
0351          * and we don't want that. Hence, adding device dumps before
0352          * the other elf notes ensure that zero-filled data can be
0353          * avoided.
0354          */
0355 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
0356         /* Read device dumps */
0357         if (*fpos < elfcorebuf_sz + vmcoredd_orig_sz) {
0358             tsz = min(elfcorebuf_sz + vmcoredd_orig_sz -
0359                   (size_t)*fpos, iov_iter_count(iter));
0360             start = *fpos - elfcorebuf_sz;
0361             if (vmcoredd_copy_dumps(iter, start, tsz))
0362                 return -EFAULT;
0363 
0364             *fpos += tsz;
0365             acc += tsz;
0366 
0367             /* leave now if filled buffer already */
0368             if (!iov_iter_count(iter))
0369                 return acc;
0370         }
0371 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
0372 
0373         /* Read remaining elf notes */
0374         tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)*fpos,
0375               iov_iter_count(iter));
0376         kaddr = elfnotes_buf + *fpos - elfcorebuf_sz - vmcoredd_orig_sz;
0377         if (copy_to_iter(kaddr, tsz, iter) < tsz)
0378             return -EFAULT;
0379 
0380         *fpos += tsz;
0381         acc += tsz;
0382 
0383         /* leave now if filled buffer already */
0384         if (!iov_iter_count(iter))
0385             return acc;
0386     }
0387 
0388     list_for_each_entry(m, &vmcore_list, list) {
0389         if (*fpos < m->offset + m->size) {
0390             tsz = (size_t)min_t(unsigned long long,
0391                         m->offset + m->size - *fpos,
0392                         iov_iter_count(iter));
0393             start = m->paddr + *fpos - m->offset;
0394             tmp = read_from_oldmem(iter, tsz, &start,
0395                     cc_platform_has(CC_ATTR_MEM_ENCRYPT));
0396             if (tmp < 0)
0397                 return tmp;
0398             *fpos += tsz;
0399             acc += tsz;
0400 
0401             /* leave now if filled buffer already */
0402             if (!iov_iter_count(iter))
0403                 return acc;
0404         }
0405     }
0406 
0407     return acc;
0408 }
0409 
0410 static ssize_t read_vmcore(struct kiocb *iocb, struct iov_iter *iter)
0411 {
0412     return __read_vmcore(iter, &iocb->ki_pos);
0413 }
0414 
0415 /*
0416  * The vmcore fault handler uses the page cache and fills data using the
0417  * standard __read_vmcore() function.
0418  *
0419  * On s390 the fault handler is used for memory regions that can't be mapped
0420  * directly with remap_pfn_range().
0421  */
0422 static vm_fault_t mmap_vmcore_fault(struct vm_fault *vmf)
0423 {
0424 #ifdef CONFIG_S390
0425     struct address_space *mapping = vmf->vma->vm_file->f_mapping;
0426     pgoff_t index = vmf->pgoff;
0427     struct iov_iter iter;
0428     struct kvec kvec;
0429     struct page *page;
0430     loff_t offset;
0431     int rc;
0432 
0433     page = find_or_create_page(mapping, index, GFP_KERNEL);
0434     if (!page)
0435         return VM_FAULT_OOM;
0436     if (!PageUptodate(page)) {
0437         offset = (loff_t) index << PAGE_SHIFT;
0438         kvec.iov_base = page_address(page);
0439         kvec.iov_len = PAGE_SIZE;
0440         iov_iter_kvec(&iter, READ, &kvec, 1, PAGE_SIZE);
0441 
0442         rc = __read_vmcore(&iter, &offset);
0443         if (rc < 0) {
0444             unlock_page(page);
0445             put_page(page);
0446             return vmf_error(rc);
0447         }
0448         SetPageUptodate(page);
0449     }
0450     unlock_page(page);
0451     vmf->page = page;
0452     return 0;
0453 #else
0454     return VM_FAULT_SIGBUS;
0455 #endif
0456 }
0457 
0458 static const struct vm_operations_struct vmcore_mmap_ops = {
0459     .fault = mmap_vmcore_fault,
0460 };
0461 
0462 /**
0463  * vmcore_alloc_buf - allocate buffer in vmalloc memory
0464  * @size: size of buffer
0465  *
0466  * If CONFIG_MMU is defined, use vmalloc_user() to allow users to mmap
0467  * the buffer to user-space by means of remap_vmalloc_range().
0468  *
0469  * If CONFIG_MMU is not defined, use vzalloc() since mmap_vmcore() is
0470  * disabled and there's no need to allow users to mmap the buffer.
0471  */
0472 static inline char *vmcore_alloc_buf(size_t size)
0473 {
0474 #ifdef CONFIG_MMU
0475     return vmalloc_user(size);
0476 #else
0477     return vzalloc(size);
0478 #endif
0479 }
0480 
0481 /*
0482  * Disable mmap_vmcore() if CONFIG_MMU is not defined. MMU is
0483  * essential for mmap_vmcore() in order to map physically
0484  * non-contiguous objects (ELF header, ELF note segment and memory
0485  * regions in the 1st kernel pointed to by PT_LOAD entries) into
0486  * virtually contiguous user-space in ELF layout.
0487  */
0488 #ifdef CONFIG_MMU
0489 /*
0490  * remap_oldmem_pfn_checked - do remap_oldmem_pfn_range replacing all pages
0491  * reported as not being ram with the zero page.
0492  *
0493  * @vma: vm_area_struct describing requested mapping
0494  * @from: start remapping from
0495  * @pfn: page frame number to start remapping to
0496  * @size: remapping size
0497  * @prot: protection bits
0498  *
0499  * Returns zero on success, -EAGAIN on failure.
0500  */
0501 static int remap_oldmem_pfn_checked(struct vm_area_struct *vma,
0502                     unsigned long from, unsigned long pfn,
0503                     unsigned long size, pgprot_t prot)
0504 {
0505     unsigned long map_size;
0506     unsigned long pos_start, pos_end, pos;
0507     unsigned long zeropage_pfn = my_zero_pfn(0);
0508     size_t len = 0;
0509 
0510     pos_start = pfn;
0511     pos_end = pfn + (size >> PAGE_SHIFT);
0512 
0513     for (pos = pos_start; pos < pos_end; ++pos) {
0514         if (!pfn_is_ram(pos)) {
0515             /*
0516              * We hit a page which is not ram. Remap the continuous
0517              * region between pos_start and pos-1 and replace
0518              * the non-ram page at pos with the zero page.
0519              */
0520             if (pos > pos_start) {
0521                 /* Remap continuous region */
0522                 map_size = (pos - pos_start) << PAGE_SHIFT;
0523                 if (remap_oldmem_pfn_range(vma, from + len,
0524                                pos_start, map_size,
0525                                prot))
0526                     goto fail;
0527                 len += map_size;
0528             }
0529             /* Remap the zero page */
0530             if (remap_oldmem_pfn_range(vma, from + len,
0531                            zeropage_pfn,
0532                            PAGE_SIZE, prot))
0533                 goto fail;
0534             len += PAGE_SIZE;
0535             pos_start = pos + 1;
0536         }
0537     }
0538     if (pos > pos_start) {
0539         /* Remap the rest */
0540         map_size = (pos - pos_start) << PAGE_SHIFT;
0541         if (remap_oldmem_pfn_range(vma, from + len, pos_start,
0542                        map_size, prot))
0543             goto fail;
0544     }
0545     return 0;
0546 fail:
0547     do_munmap(vma->vm_mm, from, len, NULL);
0548     return -EAGAIN;
0549 }
0550 
0551 static int vmcore_remap_oldmem_pfn(struct vm_area_struct *vma,
0552                 unsigned long from, unsigned long pfn,
0553                 unsigned long size, pgprot_t prot)
0554 {
0555     int ret, idx;
0556 
0557     /*
0558      * Check if a callback was registered to avoid looping over all
0559      * pages without a reason.
0560      */
0561     idx = srcu_read_lock(&vmcore_cb_srcu);
0562     if (!list_empty(&vmcore_cb_list))
0563         ret = remap_oldmem_pfn_checked(vma, from, pfn, size, prot);
0564     else
0565         ret = remap_oldmem_pfn_range(vma, from, pfn, size, prot);
0566     srcu_read_unlock(&vmcore_cb_srcu, idx);
0567     return ret;
0568 }
0569 
0570 static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
0571 {
0572     size_t size = vma->vm_end - vma->vm_start;
0573     u64 start, end, len, tsz;
0574     struct vmcore *m;
0575 
0576     start = (u64)vma->vm_pgoff << PAGE_SHIFT;
0577     end = start + size;
0578 
0579     if (size > vmcore_size || end > vmcore_size)
0580         return -EINVAL;
0581 
0582     if (vma->vm_flags & (VM_WRITE | VM_EXEC))
0583         return -EPERM;
0584 
0585     vma->vm_flags &= ~(VM_MAYWRITE | VM_MAYEXEC);
0586     vma->vm_flags |= VM_MIXEDMAP;
0587     vma->vm_ops = &vmcore_mmap_ops;
0588 
0589     len = 0;
0590 
0591     if (start < elfcorebuf_sz) {
0592         u64 pfn;
0593 
0594         tsz = min(elfcorebuf_sz - (size_t)start, size);
0595         pfn = __pa(elfcorebuf + start) >> PAGE_SHIFT;
0596         if (remap_pfn_range(vma, vma->vm_start, pfn, tsz,
0597                     vma->vm_page_prot))
0598             return -EAGAIN;
0599         size -= tsz;
0600         start += tsz;
0601         len += tsz;
0602 
0603         if (size == 0)
0604             return 0;
0605     }
0606 
0607     if (start < elfcorebuf_sz + elfnotes_sz) {
0608         void *kaddr;
0609 
0610         /* We add device dumps before other elf notes because the
0611          * other elf notes may not fill the elf notes buffer
0612          * completely and we will end up with zero-filled data
0613          * between the elf notes and the device dumps. Tools will
0614          * then try to decode this zero-filled data as valid notes
0615          * and we don't want that. Hence, adding device dumps before
0616          * the other elf notes ensure that zero-filled data can be
0617          * avoided. This also ensures that the device dumps and
0618          * other elf notes can be properly mmaped at page aligned
0619          * address.
0620          */
0621 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
0622         /* Read device dumps */
0623         if (start < elfcorebuf_sz + vmcoredd_orig_sz) {
0624             u64 start_off;
0625 
0626             tsz = min(elfcorebuf_sz + vmcoredd_orig_sz -
0627                   (size_t)start, size);
0628             start_off = start - elfcorebuf_sz;
0629             if (vmcoredd_mmap_dumps(vma, vma->vm_start + len,
0630                         start_off, tsz))
0631                 goto fail;
0632 
0633             size -= tsz;
0634             start += tsz;
0635             len += tsz;
0636 
0637             /* leave now if filled buffer already */
0638             if (!size)
0639                 return 0;
0640         }
0641 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
0642 
0643         /* Read remaining elf notes */
0644         tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)start, size);
0645         kaddr = elfnotes_buf + start - elfcorebuf_sz - vmcoredd_orig_sz;
0646         if (remap_vmalloc_range_partial(vma, vma->vm_start + len,
0647                         kaddr, 0, tsz))
0648             goto fail;
0649 
0650         size -= tsz;
0651         start += tsz;
0652         len += tsz;
0653 
0654         if (size == 0)
0655             return 0;
0656     }
0657 
0658     list_for_each_entry(m, &vmcore_list, list) {
0659         if (start < m->offset + m->size) {
0660             u64 paddr = 0;
0661 
0662             tsz = (size_t)min_t(unsigned long long,
0663                         m->offset + m->size - start, size);
0664             paddr = m->paddr + start - m->offset;
0665             if (vmcore_remap_oldmem_pfn(vma, vma->vm_start + len,
0666                             paddr >> PAGE_SHIFT, tsz,
0667                             vma->vm_page_prot))
0668                 goto fail;
0669             size -= tsz;
0670             start += tsz;
0671             len += tsz;
0672 
0673             if (size == 0)
0674                 return 0;
0675         }
0676     }
0677 
0678     return 0;
0679 fail:
0680     do_munmap(vma->vm_mm, vma->vm_start, len, NULL);
0681     return -EAGAIN;
0682 }
0683 #else
0684 static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
0685 {
0686     return -ENOSYS;
0687 }
0688 #endif
0689 
0690 static const struct proc_ops vmcore_proc_ops = {
0691     .proc_open  = open_vmcore,
0692     .proc_read_iter = read_vmcore,
0693     .proc_lseek = default_llseek,
0694     .proc_mmap  = mmap_vmcore,
0695 };
0696 
0697 static struct vmcore* __init get_new_element(void)
0698 {
0699     return kzalloc(sizeof(struct vmcore), GFP_KERNEL);
0700 }
0701 
0702 static u64 get_vmcore_size(size_t elfsz, size_t elfnotesegsz,
0703                struct list_head *vc_list)
0704 {
0705     u64 size;
0706     struct vmcore *m;
0707 
0708     size = elfsz + elfnotesegsz;
0709     list_for_each_entry(m, vc_list, list) {
0710         size += m->size;
0711     }
0712     return size;
0713 }
0714 
0715 /**
0716  * update_note_header_size_elf64 - update p_memsz member of each PT_NOTE entry
0717  *
0718  * @ehdr_ptr: ELF header
0719  *
0720  * This function updates p_memsz member of each PT_NOTE entry in the
0721  * program header table pointed to by @ehdr_ptr to real size of ELF
0722  * note segment.
0723  */
0724 static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
0725 {
0726     int i, rc=0;
0727     Elf64_Phdr *phdr_ptr;
0728     Elf64_Nhdr *nhdr_ptr;
0729 
0730     phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
0731     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
0732         void *notes_section;
0733         u64 offset, max_sz, sz, real_sz = 0;
0734         if (phdr_ptr->p_type != PT_NOTE)
0735             continue;
0736         max_sz = phdr_ptr->p_memsz;
0737         offset = phdr_ptr->p_offset;
0738         notes_section = kmalloc(max_sz, GFP_KERNEL);
0739         if (!notes_section)
0740             return -ENOMEM;
0741         rc = elfcorehdr_read_notes(notes_section, max_sz, &offset);
0742         if (rc < 0) {
0743             kfree(notes_section);
0744             return rc;
0745         }
0746         nhdr_ptr = notes_section;
0747         while (nhdr_ptr->n_namesz != 0) {
0748             sz = sizeof(Elf64_Nhdr) +
0749                 (((u64)nhdr_ptr->n_namesz + 3) & ~3) +
0750                 (((u64)nhdr_ptr->n_descsz + 3) & ~3);
0751             if ((real_sz + sz) > max_sz) {
0752                 pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
0753                     nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
0754                 break;
0755             }
0756             real_sz += sz;
0757             nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
0758         }
0759         kfree(notes_section);
0760         phdr_ptr->p_memsz = real_sz;
0761         if (real_sz == 0) {
0762             pr_warn("Warning: Zero PT_NOTE entries found\n");
0763         }
0764     }
0765 
0766     return 0;
0767 }
0768 
0769 /**
0770  * get_note_number_and_size_elf64 - get the number of PT_NOTE program
0771  * headers and sum of real size of their ELF note segment headers and
0772  * data.
0773  *
0774  * @ehdr_ptr: ELF header
0775  * @nr_ptnote: buffer for the number of PT_NOTE program headers
0776  * @sz_ptnote: buffer for size of unique PT_NOTE program header
0777  *
0778  * This function is used to merge multiple PT_NOTE program headers
0779  * into a unique single one. The resulting unique entry will have
0780  * @sz_ptnote in its phdr->p_mem.
0781  *
0782  * It is assumed that program headers with PT_NOTE type pointed to by
0783  * @ehdr_ptr has already been updated by update_note_header_size_elf64
0784  * and each of PT_NOTE program headers has actual ELF note segment
0785  * size in its p_memsz member.
0786  */
0787 static int __init get_note_number_and_size_elf64(const Elf64_Ehdr *ehdr_ptr,
0788                          int *nr_ptnote, u64 *sz_ptnote)
0789 {
0790     int i;
0791     Elf64_Phdr *phdr_ptr;
0792 
0793     *nr_ptnote = *sz_ptnote = 0;
0794 
0795     phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
0796     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
0797         if (phdr_ptr->p_type != PT_NOTE)
0798             continue;
0799         *nr_ptnote += 1;
0800         *sz_ptnote += phdr_ptr->p_memsz;
0801     }
0802 
0803     return 0;
0804 }
0805 
0806 /**
0807  * copy_notes_elf64 - copy ELF note segments in a given buffer
0808  *
0809  * @ehdr_ptr: ELF header
0810  * @notes_buf: buffer into which ELF note segments are copied
0811  *
0812  * This function is used to copy ELF note segment in the 1st kernel
0813  * into the buffer @notes_buf in the 2nd kernel. It is assumed that
0814  * size of the buffer @notes_buf is equal to or larger than sum of the
0815  * real ELF note segment headers and data.
0816  *
0817  * It is assumed that program headers with PT_NOTE type pointed to by
0818  * @ehdr_ptr has already been updated by update_note_header_size_elf64
0819  * and each of PT_NOTE program headers has actual ELF note segment
0820  * size in its p_memsz member.
0821  */
0822 static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf)
0823 {
0824     int i, rc=0;
0825     Elf64_Phdr *phdr_ptr;
0826 
0827     phdr_ptr = (Elf64_Phdr*)(ehdr_ptr + 1);
0828 
0829     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
0830         u64 offset;
0831         if (phdr_ptr->p_type != PT_NOTE)
0832             continue;
0833         offset = phdr_ptr->p_offset;
0834         rc = elfcorehdr_read_notes(notes_buf, phdr_ptr->p_memsz,
0835                        &offset);
0836         if (rc < 0)
0837             return rc;
0838         notes_buf += phdr_ptr->p_memsz;
0839     }
0840 
0841     return 0;
0842 }
0843 
0844 /* Merges all the PT_NOTE headers into one. */
0845 static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
0846                        char **notes_buf, size_t *notes_sz)
0847 {
0848     int i, nr_ptnote=0, rc=0;
0849     char *tmp;
0850     Elf64_Ehdr *ehdr_ptr;
0851     Elf64_Phdr phdr;
0852     u64 phdr_sz = 0, note_off;
0853 
0854     ehdr_ptr = (Elf64_Ehdr *)elfptr;
0855 
0856     rc = update_note_header_size_elf64(ehdr_ptr);
0857     if (rc < 0)
0858         return rc;
0859 
0860     rc = get_note_number_and_size_elf64(ehdr_ptr, &nr_ptnote, &phdr_sz);
0861     if (rc < 0)
0862         return rc;
0863 
0864     *notes_sz = roundup(phdr_sz, PAGE_SIZE);
0865     *notes_buf = vmcore_alloc_buf(*notes_sz);
0866     if (!*notes_buf)
0867         return -ENOMEM;
0868 
0869     rc = copy_notes_elf64(ehdr_ptr, *notes_buf);
0870     if (rc < 0)
0871         return rc;
0872 
0873     /* Prepare merged PT_NOTE program header. */
0874     phdr.p_type    = PT_NOTE;
0875     phdr.p_flags   = 0;
0876     note_off = sizeof(Elf64_Ehdr) +
0877             (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
0878     phdr.p_offset  = roundup(note_off, PAGE_SIZE);
0879     phdr.p_vaddr   = phdr.p_paddr = 0;
0880     phdr.p_filesz  = phdr.p_memsz = phdr_sz;
0881     phdr.p_align   = 0;
0882 
0883     /* Add merged PT_NOTE program header*/
0884     tmp = elfptr + sizeof(Elf64_Ehdr);
0885     memcpy(tmp, &phdr, sizeof(phdr));
0886     tmp += sizeof(phdr);
0887 
0888     /* Remove unwanted PT_NOTE program headers. */
0889     i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
0890     *elfsz = *elfsz - i;
0891     memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
0892     memset(elfptr + *elfsz, 0, i);
0893     *elfsz = roundup(*elfsz, PAGE_SIZE);
0894 
0895     /* Modify e_phnum to reflect merged headers. */
0896     ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
0897 
0898     /* Store the size of all notes.  We need this to update the note
0899      * header when the device dumps will be added.
0900      */
0901     elfnotes_orig_sz = phdr.p_memsz;
0902 
0903     return 0;
0904 }
0905 
0906 /**
0907  * update_note_header_size_elf32 - update p_memsz member of each PT_NOTE entry
0908  *
0909  * @ehdr_ptr: ELF header
0910  *
0911  * This function updates p_memsz member of each PT_NOTE entry in the
0912  * program header table pointed to by @ehdr_ptr to real size of ELF
0913  * note segment.
0914  */
0915 static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
0916 {
0917     int i, rc=0;
0918     Elf32_Phdr *phdr_ptr;
0919     Elf32_Nhdr *nhdr_ptr;
0920 
0921     phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
0922     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
0923         void *notes_section;
0924         u64 offset, max_sz, sz, real_sz = 0;
0925         if (phdr_ptr->p_type != PT_NOTE)
0926             continue;
0927         max_sz = phdr_ptr->p_memsz;
0928         offset = phdr_ptr->p_offset;
0929         notes_section = kmalloc(max_sz, GFP_KERNEL);
0930         if (!notes_section)
0931             return -ENOMEM;
0932         rc = elfcorehdr_read_notes(notes_section, max_sz, &offset);
0933         if (rc < 0) {
0934             kfree(notes_section);
0935             return rc;
0936         }
0937         nhdr_ptr = notes_section;
0938         while (nhdr_ptr->n_namesz != 0) {
0939             sz = sizeof(Elf32_Nhdr) +
0940                 (((u64)nhdr_ptr->n_namesz + 3) & ~3) +
0941                 (((u64)nhdr_ptr->n_descsz + 3) & ~3);
0942             if ((real_sz + sz) > max_sz) {
0943                 pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
0944                     nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
0945                 break;
0946             }
0947             real_sz += sz;
0948             nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
0949         }
0950         kfree(notes_section);
0951         phdr_ptr->p_memsz = real_sz;
0952         if (real_sz == 0) {
0953             pr_warn("Warning: Zero PT_NOTE entries found\n");
0954         }
0955     }
0956 
0957     return 0;
0958 }
0959 
0960 /**
0961  * get_note_number_and_size_elf32 - get the number of PT_NOTE program
0962  * headers and sum of real size of their ELF note segment headers and
0963  * data.
0964  *
0965  * @ehdr_ptr: ELF header
0966  * @nr_ptnote: buffer for the number of PT_NOTE program headers
0967  * @sz_ptnote: buffer for size of unique PT_NOTE program header
0968  *
0969  * This function is used to merge multiple PT_NOTE program headers
0970  * into a unique single one. The resulting unique entry will have
0971  * @sz_ptnote in its phdr->p_mem.
0972  *
0973  * It is assumed that program headers with PT_NOTE type pointed to by
0974  * @ehdr_ptr has already been updated by update_note_header_size_elf32
0975  * and each of PT_NOTE program headers has actual ELF note segment
0976  * size in its p_memsz member.
0977  */
0978 static int __init get_note_number_and_size_elf32(const Elf32_Ehdr *ehdr_ptr,
0979                          int *nr_ptnote, u64 *sz_ptnote)
0980 {
0981     int i;
0982     Elf32_Phdr *phdr_ptr;
0983 
0984     *nr_ptnote = *sz_ptnote = 0;
0985 
0986     phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
0987     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
0988         if (phdr_ptr->p_type != PT_NOTE)
0989             continue;
0990         *nr_ptnote += 1;
0991         *sz_ptnote += phdr_ptr->p_memsz;
0992     }
0993 
0994     return 0;
0995 }
0996 
0997 /**
0998  * copy_notes_elf32 - copy ELF note segments in a given buffer
0999  *
1000  * @ehdr_ptr: ELF header
1001  * @notes_buf: buffer into which ELF note segments are copied
1002  *
1003  * This function is used to copy ELF note segment in the 1st kernel
1004  * into the buffer @notes_buf in the 2nd kernel. It is assumed that
1005  * size of the buffer @notes_buf is equal to or larger than sum of the
1006  * real ELF note segment headers and data.
1007  *
1008  * It is assumed that program headers with PT_NOTE type pointed to by
1009  * @ehdr_ptr has already been updated by update_note_header_size_elf32
1010  * and each of PT_NOTE program headers has actual ELF note segment
1011  * size in its p_memsz member.
1012  */
1013 static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf)
1014 {
1015     int i, rc=0;
1016     Elf32_Phdr *phdr_ptr;
1017 
1018     phdr_ptr = (Elf32_Phdr*)(ehdr_ptr + 1);
1019 
1020     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
1021         u64 offset;
1022         if (phdr_ptr->p_type != PT_NOTE)
1023             continue;
1024         offset = phdr_ptr->p_offset;
1025         rc = elfcorehdr_read_notes(notes_buf, phdr_ptr->p_memsz,
1026                        &offset);
1027         if (rc < 0)
1028             return rc;
1029         notes_buf += phdr_ptr->p_memsz;
1030     }
1031 
1032     return 0;
1033 }
1034 
1035 /* Merges all the PT_NOTE headers into one. */
1036 static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
1037                        char **notes_buf, size_t *notes_sz)
1038 {
1039     int i, nr_ptnote=0, rc=0;
1040     char *tmp;
1041     Elf32_Ehdr *ehdr_ptr;
1042     Elf32_Phdr phdr;
1043     u64 phdr_sz = 0, note_off;
1044 
1045     ehdr_ptr = (Elf32_Ehdr *)elfptr;
1046 
1047     rc = update_note_header_size_elf32(ehdr_ptr);
1048     if (rc < 0)
1049         return rc;
1050 
1051     rc = get_note_number_and_size_elf32(ehdr_ptr, &nr_ptnote, &phdr_sz);
1052     if (rc < 0)
1053         return rc;
1054 
1055     *notes_sz = roundup(phdr_sz, PAGE_SIZE);
1056     *notes_buf = vmcore_alloc_buf(*notes_sz);
1057     if (!*notes_buf)
1058         return -ENOMEM;
1059 
1060     rc = copy_notes_elf32(ehdr_ptr, *notes_buf);
1061     if (rc < 0)
1062         return rc;
1063 
1064     /* Prepare merged PT_NOTE program header. */
1065     phdr.p_type    = PT_NOTE;
1066     phdr.p_flags   = 0;
1067     note_off = sizeof(Elf32_Ehdr) +
1068             (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
1069     phdr.p_offset  = roundup(note_off, PAGE_SIZE);
1070     phdr.p_vaddr   = phdr.p_paddr = 0;
1071     phdr.p_filesz  = phdr.p_memsz = phdr_sz;
1072     phdr.p_align   = 0;
1073 
1074     /* Add merged PT_NOTE program header*/
1075     tmp = elfptr + sizeof(Elf32_Ehdr);
1076     memcpy(tmp, &phdr, sizeof(phdr));
1077     tmp += sizeof(phdr);
1078 
1079     /* Remove unwanted PT_NOTE program headers. */
1080     i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
1081     *elfsz = *elfsz - i;
1082     memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
1083     memset(elfptr + *elfsz, 0, i);
1084     *elfsz = roundup(*elfsz, PAGE_SIZE);
1085 
1086     /* Modify e_phnum to reflect merged headers. */
1087     ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
1088 
1089     /* Store the size of all notes.  We need this to update the note
1090      * header when the device dumps will be added.
1091      */
1092     elfnotes_orig_sz = phdr.p_memsz;
1093 
1094     return 0;
1095 }
1096 
1097 /* Add memory chunks represented by program headers to vmcore list. Also update
1098  * the new offset fields of exported program headers. */
1099 static int __init process_ptload_program_headers_elf64(char *elfptr,
1100                         size_t elfsz,
1101                         size_t elfnotes_sz,
1102                         struct list_head *vc_list)
1103 {
1104     int i;
1105     Elf64_Ehdr *ehdr_ptr;
1106     Elf64_Phdr *phdr_ptr;
1107     loff_t vmcore_off;
1108     struct vmcore *new;
1109 
1110     ehdr_ptr = (Elf64_Ehdr *)elfptr;
1111     phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
1112 
1113     /* Skip Elf header, program headers and Elf note segment. */
1114     vmcore_off = elfsz + elfnotes_sz;
1115 
1116     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
1117         u64 paddr, start, end, size;
1118 
1119         if (phdr_ptr->p_type != PT_LOAD)
1120             continue;
1121 
1122         paddr = phdr_ptr->p_offset;
1123         start = rounddown(paddr, PAGE_SIZE);
1124         end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
1125         size = end - start;
1126 
1127         /* Add this contiguous chunk of memory to vmcore list.*/
1128         new = get_new_element();
1129         if (!new)
1130             return -ENOMEM;
1131         new->paddr = start;
1132         new->size = size;
1133         list_add_tail(&new->list, vc_list);
1134 
1135         /* Update the program header offset. */
1136         phdr_ptr->p_offset = vmcore_off + (paddr - start);
1137         vmcore_off = vmcore_off + size;
1138     }
1139     return 0;
1140 }
1141 
1142 static int __init process_ptload_program_headers_elf32(char *elfptr,
1143                         size_t elfsz,
1144                         size_t elfnotes_sz,
1145                         struct list_head *vc_list)
1146 {
1147     int i;
1148     Elf32_Ehdr *ehdr_ptr;
1149     Elf32_Phdr *phdr_ptr;
1150     loff_t vmcore_off;
1151     struct vmcore *new;
1152 
1153     ehdr_ptr = (Elf32_Ehdr *)elfptr;
1154     phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
1155 
1156     /* Skip Elf header, program headers and Elf note segment. */
1157     vmcore_off = elfsz + elfnotes_sz;
1158 
1159     for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
1160         u64 paddr, start, end, size;
1161 
1162         if (phdr_ptr->p_type != PT_LOAD)
1163             continue;
1164 
1165         paddr = phdr_ptr->p_offset;
1166         start = rounddown(paddr, PAGE_SIZE);
1167         end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
1168         size = end - start;
1169 
1170         /* Add this contiguous chunk of memory to vmcore list.*/
1171         new = get_new_element();
1172         if (!new)
1173             return -ENOMEM;
1174         new->paddr = start;
1175         new->size = size;
1176         list_add_tail(&new->list, vc_list);
1177 
1178         /* Update the program header offset */
1179         phdr_ptr->p_offset = vmcore_off + (paddr - start);
1180         vmcore_off = vmcore_off + size;
1181     }
1182     return 0;
1183 }
1184 
1185 /* Sets offset fields of vmcore elements. */
1186 static void set_vmcore_list_offsets(size_t elfsz, size_t elfnotes_sz,
1187                     struct list_head *vc_list)
1188 {
1189     loff_t vmcore_off;
1190     struct vmcore *m;
1191 
1192     /* Skip Elf header, program headers and Elf note segment. */
1193     vmcore_off = elfsz + elfnotes_sz;
1194 
1195     list_for_each_entry(m, vc_list, list) {
1196         m->offset = vmcore_off;
1197         vmcore_off += m->size;
1198     }
1199 }
1200 
1201 static void free_elfcorebuf(void)
1202 {
1203     free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig));
1204     elfcorebuf = NULL;
1205     vfree(elfnotes_buf);
1206     elfnotes_buf = NULL;
1207 }
1208 
1209 static int __init parse_crash_elf64_headers(void)
1210 {
1211     int rc=0;
1212     Elf64_Ehdr ehdr;
1213     u64 addr;
1214 
1215     addr = elfcorehdr_addr;
1216 
1217     /* Read Elf header */
1218     rc = elfcorehdr_read((char *)&ehdr, sizeof(Elf64_Ehdr), &addr);
1219     if (rc < 0)
1220         return rc;
1221 
1222     /* Do some basic Verification. */
1223     if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
1224         (ehdr.e_type != ET_CORE) ||
1225         !vmcore_elf64_check_arch(&ehdr) ||
1226         ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
1227         ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
1228         ehdr.e_version != EV_CURRENT ||
1229         ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
1230         ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
1231         ehdr.e_phnum == 0) {
1232         pr_warn("Warning: Core image elf header is not sane\n");
1233         return -EINVAL;
1234     }
1235 
1236     /* Read in all elf headers. */
1237     elfcorebuf_sz_orig = sizeof(Elf64_Ehdr) +
1238                 ehdr.e_phnum * sizeof(Elf64_Phdr);
1239     elfcorebuf_sz = elfcorebuf_sz_orig;
1240     elfcorebuf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
1241                           get_order(elfcorebuf_sz_orig));
1242     if (!elfcorebuf)
1243         return -ENOMEM;
1244     addr = elfcorehdr_addr;
1245     rc = elfcorehdr_read(elfcorebuf, elfcorebuf_sz_orig, &addr);
1246     if (rc < 0)
1247         goto fail;
1248 
1249     /* Merge all PT_NOTE headers into one. */
1250     rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz,
1251                       &elfnotes_buf, &elfnotes_sz);
1252     if (rc)
1253         goto fail;
1254     rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
1255                           elfnotes_sz, &vmcore_list);
1256     if (rc)
1257         goto fail;
1258     set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
1259     return 0;
1260 fail:
1261     free_elfcorebuf();
1262     return rc;
1263 }
1264 
1265 static int __init parse_crash_elf32_headers(void)
1266 {
1267     int rc=0;
1268     Elf32_Ehdr ehdr;
1269     u64 addr;
1270 
1271     addr = elfcorehdr_addr;
1272 
1273     /* Read Elf header */
1274     rc = elfcorehdr_read((char *)&ehdr, sizeof(Elf32_Ehdr), &addr);
1275     if (rc < 0)
1276         return rc;
1277 
1278     /* Do some basic Verification. */
1279     if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
1280         (ehdr.e_type != ET_CORE) ||
1281         !vmcore_elf32_check_arch(&ehdr) ||
1282         ehdr.e_ident[EI_CLASS] != ELFCLASS32||
1283         ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
1284         ehdr.e_version != EV_CURRENT ||
1285         ehdr.e_ehsize != sizeof(Elf32_Ehdr) ||
1286         ehdr.e_phentsize != sizeof(Elf32_Phdr) ||
1287         ehdr.e_phnum == 0) {
1288         pr_warn("Warning: Core image elf header is not sane\n");
1289         return -EINVAL;
1290     }
1291 
1292     /* Read in all elf headers. */
1293     elfcorebuf_sz_orig = sizeof(Elf32_Ehdr) + ehdr.e_phnum * sizeof(Elf32_Phdr);
1294     elfcorebuf_sz = elfcorebuf_sz_orig;
1295     elfcorebuf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
1296                           get_order(elfcorebuf_sz_orig));
1297     if (!elfcorebuf)
1298         return -ENOMEM;
1299     addr = elfcorehdr_addr;
1300     rc = elfcorehdr_read(elfcorebuf, elfcorebuf_sz_orig, &addr);
1301     if (rc < 0)
1302         goto fail;
1303 
1304     /* Merge all PT_NOTE headers into one. */
1305     rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz,
1306                       &elfnotes_buf, &elfnotes_sz);
1307     if (rc)
1308         goto fail;
1309     rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
1310                           elfnotes_sz, &vmcore_list);
1311     if (rc)
1312         goto fail;
1313     set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
1314     return 0;
1315 fail:
1316     free_elfcorebuf();
1317     return rc;
1318 }
1319 
1320 static int __init parse_crash_elf_headers(void)
1321 {
1322     unsigned char e_ident[EI_NIDENT];
1323     u64 addr;
1324     int rc=0;
1325 
1326     addr = elfcorehdr_addr;
1327     rc = elfcorehdr_read(e_ident, EI_NIDENT, &addr);
1328     if (rc < 0)
1329         return rc;
1330     if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
1331         pr_warn("Warning: Core image elf header not found\n");
1332         return -EINVAL;
1333     }
1334 
1335     if (e_ident[EI_CLASS] == ELFCLASS64) {
1336         rc = parse_crash_elf64_headers();
1337         if (rc)
1338             return rc;
1339     } else if (e_ident[EI_CLASS] == ELFCLASS32) {
1340         rc = parse_crash_elf32_headers();
1341         if (rc)
1342             return rc;
1343     } else {
1344         pr_warn("Warning: Core image elf header is not sane\n");
1345         return -EINVAL;
1346     }
1347 
1348     /* Determine vmcore size. */
1349     vmcore_size = get_vmcore_size(elfcorebuf_sz, elfnotes_sz,
1350                       &vmcore_list);
1351 
1352     return 0;
1353 }
1354 
1355 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
1356 /**
1357  * vmcoredd_write_header - Write vmcore device dump header at the
1358  * beginning of the dump's buffer.
1359  * @buf: Output buffer where the note is written
1360  * @data: Dump info
1361  * @size: Size of the dump
1362  *
1363  * Fills beginning of the dump's buffer with vmcore device dump header.
1364  */
1365 static void vmcoredd_write_header(void *buf, struct vmcoredd_data *data,
1366                   u32 size)
1367 {
1368     struct vmcoredd_header *vdd_hdr = (struct vmcoredd_header *)buf;
1369 
1370     vdd_hdr->n_namesz = sizeof(vdd_hdr->name);
1371     vdd_hdr->n_descsz = size + sizeof(vdd_hdr->dump_name);
1372     vdd_hdr->n_type = NT_VMCOREDD;
1373 
1374     strncpy((char *)vdd_hdr->name, VMCOREDD_NOTE_NAME,
1375         sizeof(vdd_hdr->name));
1376     memcpy(vdd_hdr->dump_name, data->dump_name, sizeof(vdd_hdr->dump_name));
1377 }
1378 
1379 /**
1380  * vmcoredd_update_program_headers - Update all Elf program headers
1381  * @elfptr: Pointer to elf header
1382  * @elfnotesz: Size of elf notes aligned to page size
1383  * @vmcoreddsz: Size of device dumps to be added to elf note header
1384  *
1385  * Determine type of Elf header (Elf64 or Elf32) and update the elf note size.
1386  * Also update the offsets of all the program headers after the elf note header.
1387  */
1388 static void vmcoredd_update_program_headers(char *elfptr, size_t elfnotesz,
1389                         size_t vmcoreddsz)
1390 {
1391     unsigned char *e_ident = (unsigned char *)elfptr;
1392     u64 start, end, size;
1393     loff_t vmcore_off;
1394     u32 i;
1395 
1396     vmcore_off = elfcorebuf_sz + elfnotesz;
1397 
1398     if (e_ident[EI_CLASS] == ELFCLASS64) {
1399         Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elfptr;
1400         Elf64_Phdr *phdr = (Elf64_Phdr *)(elfptr + sizeof(Elf64_Ehdr));
1401 
1402         /* Update all program headers */
1403         for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
1404             if (phdr->p_type == PT_NOTE) {
1405                 /* Update note size */
1406                 phdr->p_memsz = elfnotes_orig_sz + vmcoreddsz;
1407                 phdr->p_filesz = phdr->p_memsz;
1408                 continue;
1409             }
1410 
1411             start = rounddown(phdr->p_offset, PAGE_SIZE);
1412             end = roundup(phdr->p_offset + phdr->p_memsz,
1413                       PAGE_SIZE);
1414             size = end - start;
1415             phdr->p_offset = vmcore_off + (phdr->p_offset - start);
1416             vmcore_off += size;
1417         }
1418     } else {
1419         Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfptr;
1420         Elf32_Phdr *phdr = (Elf32_Phdr *)(elfptr + sizeof(Elf32_Ehdr));
1421 
1422         /* Update all program headers */
1423         for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
1424             if (phdr->p_type == PT_NOTE) {
1425                 /* Update note size */
1426                 phdr->p_memsz = elfnotes_orig_sz + vmcoreddsz;
1427                 phdr->p_filesz = phdr->p_memsz;
1428                 continue;
1429             }
1430 
1431             start = rounddown(phdr->p_offset, PAGE_SIZE);
1432             end = roundup(phdr->p_offset + phdr->p_memsz,
1433                       PAGE_SIZE);
1434             size = end - start;
1435             phdr->p_offset = vmcore_off + (phdr->p_offset - start);
1436             vmcore_off += size;
1437         }
1438     }
1439 }
1440 
1441 /**
1442  * vmcoredd_update_size - Update the total size of the device dumps and update
1443  * Elf header
1444  * @dump_size: Size of the current device dump to be added to total size
1445  *
1446  * Update the total size of all the device dumps and update the Elf program
1447  * headers. Calculate the new offsets for the vmcore list and update the
1448  * total vmcore size.
1449  */
1450 static void vmcoredd_update_size(size_t dump_size)
1451 {
1452     vmcoredd_orig_sz += dump_size;
1453     elfnotes_sz = roundup(elfnotes_orig_sz, PAGE_SIZE) + vmcoredd_orig_sz;
1454     vmcoredd_update_program_headers(elfcorebuf, elfnotes_sz,
1455                     vmcoredd_orig_sz);
1456 
1457     /* Update vmcore list offsets */
1458     set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
1459 
1460     vmcore_size = get_vmcore_size(elfcorebuf_sz, elfnotes_sz,
1461                       &vmcore_list);
1462     proc_vmcore->size = vmcore_size;
1463 }
1464 
1465 /**
1466  * vmcore_add_device_dump - Add a buffer containing device dump to vmcore
1467  * @data: dump info.
1468  *
1469  * Allocate a buffer and invoke the calling driver's dump collect routine.
1470  * Write Elf note at the beginning of the buffer to indicate vmcore device
1471  * dump and add the dump to global list.
1472  */
1473 int vmcore_add_device_dump(struct vmcoredd_data *data)
1474 {
1475     struct vmcoredd_node *dump;
1476     void *buf = NULL;
1477     size_t data_size;
1478     int ret;
1479 
1480     if (vmcoredd_disabled) {
1481         pr_err_once("Device dump is disabled\n");
1482         return -EINVAL;
1483     }
1484 
1485     if (!data || !strlen(data->dump_name) ||
1486         !data->vmcoredd_callback || !data->size)
1487         return -EINVAL;
1488 
1489     dump = vzalloc(sizeof(*dump));
1490     if (!dump) {
1491         ret = -ENOMEM;
1492         goto out_err;
1493     }
1494 
1495     /* Keep size of the buffer page aligned so that it can be mmaped */
1496     data_size = roundup(sizeof(struct vmcoredd_header) + data->size,
1497                 PAGE_SIZE);
1498 
1499     /* Allocate buffer for driver's to write their dumps */
1500     buf = vmcore_alloc_buf(data_size);
1501     if (!buf) {
1502         ret = -ENOMEM;
1503         goto out_err;
1504     }
1505 
1506     vmcoredd_write_header(buf, data, data_size -
1507                   sizeof(struct vmcoredd_header));
1508 
1509     /* Invoke the driver's dump collection routing */
1510     ret = data->vmcoredd_callback(data, buf +
1511                       sizeof(struct vmcoredd_header));
1512     if (ret)
1513         goto out_err;
1514 
1515     dump->buf = buf;
1516     dump->size = data_size;
1517 
1518     /* Add the dump to driver sysfs list */
1519     mutex_lock(&vmcoredd_mutex);
1520     list_add_tail(&dump->list, &vmcoredd_list);
1521     mutex_unlock(&vmcoredd_mutex);
1522 
1523     vmcoredd_update_size(data_size);
1524     return 0;
1525 
1526 out_err:
1527     vfree(buf);
1528     vfree(dump);
1529 
1530     return ret;
1531 }
1532 EXPORT_SYMBOL(vmcore_add_device_dump);
1533 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
1534 
1535 /* Free all dumps in vmcore device dump list */
1536 static void vmcore_free_device_dumps(void)
1537 {
1538 #ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
1539     mutex_lock(&vmcoredd_mutex);
1540     while (!list_empty(&vmcoredd_list)) {
1541         struct vmcoredd_node *dump;
1542 
1543         dump = list_first_entry(&vmcoredd_list, struct vmcoredd_node,
1544                     list);
1545         list_del(&dump->list);
1546         vfree(dump->buf);
1547         vfree(dump);
1548     }
1549     mutex_unlock(&vmcoredd_mutex);
1550 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
1551 }
1552 
1553 /* Init function for vmcore module. */
1554 static int __init vmcore_init(void)
1555 {
1556     int rc = 0;
1557 
1558     /* Allow architectures to allocate ELF header in 2nd kernel */
1559     rc = elfcorehdr_alloc(&elfcorehdr_addr, &elfcorehdr_size);
1560     if (rc)
1561         return rc;
1562     /*
1563      * If elfcorehdr= has been passed in cmdline or created in 2nd kernel,
1564      * then capture the dump.
1565      */
1566     if (!(is_vmcore_usable()))
1567         return rc;
1568     rc = parse_crash_elf_headers();
1569     if (rc) {
1570         pr_warn("Kdump: vmcore not initialized\n");
1571         return rc;
1572     }
1573     elfcorehdr_free(elfcorehdr_addr);
1574     elfcorehdr_addr = ELFCORE_ADDR_ERR;
1575 
1576     proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &vmcore_proc_ops);
1577     if (proc_vmcore)
1578         proc_vmcore->size = vmcore_size;
1579     return 0;
1580 }
1581 fs_initcall(vmcore_init);
1582 
1583 /* Cleanup function for vmcore module. */
1584 void vmcore_cleanup(void)
1585 {
1586     if (proc_vmcore) {
1587         proc_remove(proc_vmcore);
1588         proc_vmcore = NULL;
1589     }
1590 
1591     /* clear the vmcore list. */
1592     while (!list_empty(&vmcore_list)) {
1593         struct vmcore *m;
1594 
1595         m = list_first_entry(&vmcore_list, struct vmcore, list);
1596         list_del(&m->list);
1597         kfree(m);
1598     }
1599     free_elfcorebuf();
1600 
1601     /* clear vmcore device dump list */
1602     vmcore_free_device_dumps();
1603 }