Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * ELF loader for kexec_file_load system call.
0004  *
0005  * Copyright IBM Corp. 2018
0006  *
0007  * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
0008  */
0009 
0010 #include <linux/errno.h>
0011 #include <linux/kernel.h>
0012 #include <linux/kexec.h>
0013 #include <asm/ipl.h>
0014 #include <asm/setup.h>
0015 
0016 static int kexec_file_add_kernel_elf(struct kimage *image,
0017                      struct s390_load_data *data)
0018 {
0019     struct kexec_buf buf;
0020     const Elf_Ehdr *ehdr;
0021     const Elf_Phdr *phdr;
0022     Elf_Addr entry;
0023     void *kernel;
0024     int i, ret;
0025 
0026     kernel = image->kernel_buf;
0027     ehdr = (Elf_Ehdr *)kernel;
0028     buf.image = image;
0029     if (image->type == KEXEC_TYPE_CRASH)
0030         entry = STARTUP_KDUMP_OFFSET;
0031     else
0032         entry = ehdr->e_entry;
0033 
0034     phdr = (void *)ehdr + ehdr->e_phoff;
0035     for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
0036         if (phdr->p_type != PT_LOAD)
0037             continue;
0038 
0039         buf.buffer = kernel + phdr->p_offset;
0040         buf.bufsz = phdr->p_filesz;
0041 
0042         buf.mem = ALIGN(phdr->p_paddr, phdr->p_align);
0043         if (image->type == KEXEC_TYPE_CRASH)
0044             buf.mem += crashk_res.start;
0045         buf.memsz = phdr->p_memsz;
0046         data->memsz = ALIGN(data->memsz, phdr->p_align) + buf.memsz;
0047 
0048         if (entry - phdr->p_paddr < phdr->p_memsz) {
0049             data->kernel_buf = buf.buffer;
0050             data->kernel_mem = buf.mem;
0051             data->parm = buf.buffer + PARMAREA;
0052         }
0053 
0054         ipl_report_add_component(data->report, &buf,
0055                      IPL_RB_COMPONENT_FLAG_SIGNED |
0056                      IPL_RB_COMPONENT_FLAG_VERIFIED,
0057                      IPL_RB_CERT_UNKNOWN);
0058         ret = kexec_add_buffer(&buf);
0059         if (ret)
0060             return ret;
0061     }
0062 
0063     return data->memsz ? 0 : -EINVAL;
0064 }
0065 
0066 static void *s390_elf_load(struct kimage *image,
0067                char *kernel, unsigned long kernel_len,
0068                char *initrd, unsigned long initrd_len,
0069                char *cmdline, unsigned long cmdline_len)
0070 {
0071     const Elf_Ehdr *ehdr;
0072     const Elf_Phdr *phdr;
0073     size_t size;
0074     int i;
0075 
0076     /* image->fobs->probe already checked for valid ELF magic number. */
0077     ehdr = (Elf_Ehdr *)kernel;
0078 
0079     if (ehdr->e_type != ET_EXEC ||
0080         ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
0081         !elf_check_arch(ehdr))
0082         return ERR_PTR(-EINVAL);
0083 
0084     if (!ehdr->e_phnum || ehdr->e_phentsize != sizeof(Elf_Phdr))
0085         return ERR_PTR(-EINVAL);
0086 
0087     size = ehdr->e_ehsize + ehdr->e_phoff;
0088     size += ehdr->e_phentsize * ehdr->e_phnum;
0089     if (size > kernel_len)
0090         return ERR_PTR(-EINVAL);
0091 
0092     phdr = (void *)ehdr + ehdr->e_phoff;
0093     size = ALIGN(size, phdr->p_align);
0094     for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
0095         if (phdr->p_type == PT_INTERP)
0096             return ERR_PTR(-EINVAL);
0097 
0098         if (phdr->p_offset > kernel_len)
0099             return ERR_PTR(-EINVAL);
0100 
0101         size += ALIGN(phdr->p_filesz, phdr->p_align);
0102     }
0103 
0104     if (size > kernel_len)
0105         return ERR_PTR(-EINVAL);
0106 
0107     return kexec_file_add_components(image, kexec_file_add_kernel_elf);
0108 }
0109 
0110 static int s390_elf_probe(const char *buf, unsigned long len)
0111 {
0112     const Elf_Ehdr *ehdr;
0113 
0114     if (len < sizeof(Elf_Ehdr))
0115         return -ENOEXEC;
0116 
0117     ehdr = (Elf_Ehdr *)buf;
0118 
0119     /* Only check the ELF magic number here and do proper validity check
0120      * in the loader. Any check here that fails would send the erroneous
0121      * ELF file to the image loader that does not care what it gets.
0122      * (Most likely) causing behavior not intended by the user.
0123      */
0124     if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0)
0125         return -ENOEXEC;
0126 
0127     return 0;
0128 }
0129 
0130 const struct kexec_file_ops s390_kexec_elf_ops = {
0131     .probe = s390_elf_probe,
0132     .load = s390_elf_load,
0133 #ifdef CONFIG_KEXEC_SIG
0134     .verify_sig = s390_verify_sig,
0135 #endif /* CONFIG_KEXEC_SIG */
0136 };