~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/kexec_elf.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/kexec_elf.c (Version linux-6.12-rc7) and /kernel/kexec_elf.c (Version linux-6.2.16)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*                                                  2 /*
  3  * Load ELF vmlinux file for the kexec_file_lo      3  * Load ELF vmlinux file for the kexec_file_load syscall.
  4  *                                                  4  *
  5  * Copyright (C) 2004  Adam Litke (agl@us.ibm.      5  * Copyright (C) 2004  Adam Litke (agl@us.ibm.com)
  6  * Copyright (C) 2004  IBM Corp.                    6  * Copyright (C) 2004  IBM Corp.
  7  * Copyright (C) 2005  R Sharada (sharada@in.i      7  * Copyright (C) 2005  R Sharada (sharada@in.ibm.com)
  8  * Copyright (C) 2006  Mohan Kumar M (mohan@in      8  * Copyright (C) 2006  Mohan Kumar M (mohan@in.ibm.com)
  9  * Copyright (C) 2016  IBM Corporation              9  * Copyright (C) 2016  IBM Corporation
 10  *                                                 10  *
 11  * Based on kexec-tools' kexec-elf-exec.c and      11  * Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
 12  * Heavily modified for the kernel by              12  * Heavily modified for the kernel by
 13  * Thiago Jung Bauermann <bauerman@linux.vnet.     13  * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>.
 14  */                                                14  */
 15                                                    15 
 16 #define pr_fmt(fmt)     "kexec_elf: " fmt          16 #define pr_fmt(fmt)     "kexec_elf: " fmt
 17                                                    17 
 18 #include <linux/elf.h>                             18 #include <linux/elf.h>
 19 #include <linux/kexec.h>                           19 #include <linux/kexec.h>
 20 #include <linux/module.h>                          20 #include <linux/module.h>
 21 #include <linux/slab.h>                            21 #include <linux/slab.h>
 22 #include <linux/types.h>                           22 #include <linux/types.h>
 23                                                    23 
 24 static inline bool elf_is_elf_file(const struc     24 static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
 25 {                                                  25 {
 26         return memcmp(ehdr->e_ident, ELFMAG, S     26         return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
 27 }                                                  27 }
 28                                                    28 
 29 static uint64_t elf64_to_cpu(const struct elfh     29 static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
 30 {                                                  30 {
 31         if (ehdr->e_ident[EI_DATA] == ELFDATA2     31         if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
 32                 value = le64_to_cpu(value);        32                 value = le64_to_cpu(value);
 33         else if (ehdr->e_ident[EI_DATA] == ELF     33         else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
 34                 value = be64_to_cpu(value);        34                 value = be64_to_cpu(value);
 35                                                    35 
 36         return value;                              36         return value;
 37 }                                                  37 }
 38                                                    38 
 39 static uint32_t elf32_to_cpu(const struct elfh     39 static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
 40 {                                                  40 {
 41         if (ehdr->e_ident[EI_DATA] == ELFDATA2     41         if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
 42                 value = le32_to_cpu(value);        42                 value = le32_to_cpu(value);
 43         else if (ehdr->e_ident[EI_DATA] == ELF     43         else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
 44                 value = be32_to_cpu(value);        44                 value = be32_to_cpu(value);
 45                                                    45 
 46         return value;                              46         return value;
 47 }                                                  47 }
 48                                                    48 
 49 static uint16_t elf16_to_cpu(const struct elfh     49 static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
 50 {                                                  50 {
 51         if (ehdr->e_ident[EI_DATA] == ELFDATA2     51         if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
 52                 value = le16_to_cpu(value);        52                 value = le16_to_cpu(value);
 53         else if (ehdr->e_ident[EI_DATA] == ELF     53         else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
 54                 value = be16_to_cpu(value);        54                 value = be16_to_cpu(value);
 55                                                    55 
 56         return value;                              56         return value;
 57 }                                                  57 }
 58                                                    58 
 59 /**                                                59 /**
 60  * elf_is_ehdr_sane - check that it is safe to     60  * elf_is_ehdr_sane - check that it is safe to use the ELF header
 61  * @buf_len:    size of the buffer in which th     61  * @buf_len:    size of the buffer in which the ELF file is loaded.
 62  */                                                62  */
 63 static bool elf_is_ehdr_sane(const struct elfh     63 static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
 64 {                                                  64 {
 65         if (ehdr->e_phnum > 0 && ehdr->e_phent     65         if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
 66                 pr_debug("Bad program header s     66                 pr_debug("Bad program header size.\n");
 67                 return false;                      67                 return false;
 68         } else if (ehdr->e_shnum > 0 &&            68         } else if (ehdr->e_shnum > 0 &&
 69                    ehdr->e_shentsize != sizeof     69                    ehdr->e_shentsize != sizeof(struct elf_shdr)) {
 70                 pr_debug("Bad section header s     70                 pr_debug("Bad section header size.\n");
 71                 return false;                      71                 return false;
 72         } else if (ehdr->e_ident[EI_VERSION] !     72         } else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
 73                    ehdr->e_version != EV_CURRE     73                    ehdr->e_version != EV_CURRENT) {
 74                 pr_debug("Unknown ELF version.     74                 pr_debug("Unknown ELF version.\n");
 75                 return false;                      75                 return false;
 76         }                                          76         }
 77                                                    77 
 78         if (ehdr->e_phoff > 0 && ehdr->e_phnum     78         if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
 79                 size_t phdr_size;                  79                 size_t phdr_size;
 80                                                    80 
 81                 /*                                 81                 /*
 82                  * e_phnum is at most 65535 so     82                  * e_phnum is at most 65535 so calculating the size of the
 83                  * program header cannot overf     83                  * program header cannot overflow.
 84                  */                                84                  */
 85                 phdr_size = sizeof(struct elf_     85                 phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
 86                                                    86 
 87                 /* Sanity check the program he     87                 /* Sanity check the program header table location. */
 88                 if (ehdr->e_phoff + phdr_size      88                 if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
 89                         pr_debug("Program head     89                         pr_debug("Program headers at invalid location.\n");
 90                         return false;              90                         return false;
 91                 } else if (ehdr->e_phoff + phd     91                 } else if (ehdr->e_phoff + phdr_size > buf_len) {
 92                         pr_debug("Program head     92                         pr_debug("Program headers truncated.\n");
 93                         return false;              93                         return false;
 94                 }                                  94                 }
 95         }                                          95         }
 96                                                    96 
 97         if (ehdr->e_shoff > 0 && ehdr->e_shnum     97         if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
 98                 size_t shdr_size;                  98                 size_t shdr_size;
 99                                                    99 
100                 /*                                100                 /*
101                  * e_shnum is at most 65536 so    101                  * e_shnum is at most 65536 so calculating
102                  * the size of the section hea    102                  * the size of the section header cannot overflow.
103                  */                               103                  */
104                 shdr_size = sizeof(struct elf_    104                 shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
105                                                   105 
106                 /* Sanity check the section he    106                 /* Sanity check the section header table location. */
107                 if (ehdr->e_shoff + shdr_size     107                 if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
108                         pr_debug("Section head    108                         pr_debug("Section headers at invalid location.\n");
109                         return false;             109                         return false;
110                 } else if (ehdr->e_shoff + shd    110                 } else if (ehdr->e_shoff + shdr_size > buf_len) {
111                         pr_debug("Section head    111                         pr_debug("Section headers truncated.\n");
112                         return false;             112                         return false;
113                 }                                 113                 }
114         }                                         114         }
115                                                   115 
116         return true;                              116         return true;
117 }                                                 117 }
118                                                   118 
119 static int elf_read_ehdr(const char *buf, size    119 static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
120 {                                                 120 {
121         struct elfhdr *buf_ehdr;                  121         struct elfhdr *buf_ehdr;
122                                                   122 
123         if (len < sizeof(*buf_ehdr)) {            123         if (len < sizeof(*buf_ehdr)) {
124                 pr_debug("Buffer is too small     124                 pr_debug("Buffer is too small to hold ELF header.\n");
125                 return -ENOEXEC;                  125                 return -ENOEXEC;
126         }                                         126         }
127                                                   127 
128         memset(ehdr, 0, sizeof(*ehdr));           128         memset(ehdr, 0, sizeof(*ehdr));
129         memcpy(ehdr->e_ident, buf, sizeof(ehdr    129         memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
130         if (!elf_is_elf_file(ehdr)) {             130         if (!elf_is_elf_file(ehdr)) {
131                 pr_debug("No ELF header magic.    131                 pr_debug("No ELF header magic.\n");
132                 return -ENOEXEC;                  132                 return -ENOEXEC;
133         }                                         133         }
134                                                   134 
135         if (ehdr->e_ident[EI_CLASS] != ELF_CLA    135         if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
136                 pr_debug("Not a supported ELF     136                 pr_debug("Not a supported ELF class.\n");
137                 return -ENOEXEC;                  137                 return -ENOEXEC;
138         } else  if (ehdr->e_ident[EI_DATA] !=     138         } else  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
139                 ehdr->e_ident[EI_DATA] != ELFD    139                 ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
140                 pr_debug("Not a supported ELF     140                 pr_debug("Not a supported ELF data format.\n");
141                 return -ENOEXEC;                  141                 return -ENOEXEC;
142         }                                         142         }
143                                                   143 
144         buf_ehdr = (struct elfhdr *) buf;         144         buf_ehdr = (struct elfhdr *) buf;
145         if (elf16_to_cpu(ehdr, buf_ehdr->e_ehs    145         if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
146                 pr_debug("Bad ELF header size.    146                 pr_debug("Bad ELF header size.\n");
147                 return -ENOEXEC;                  147                 return -ENOEXEC;
148         }                                         148         }
149                                                   149 
150         ehdr->e_type      = elf16_to_cpu(ehdr,    150         ehdr->e_type      = elf16_to_cpu(ehdr, buf_ehdr->e_type);
151         ehdr->e_machine   = elf16_to_cpu(ehdr,    151         ehdr->e_machine   = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
152         ehdr->e_version   = elf32_to_cpu(ehdr,    152         ehdr->e_version   = elf32_to_cpu(ehdr, buf_ehdr->e_version);
153         ehdr->e_flags     = elf32_to_cpu(ehdr,    153         ehdr->e_flags     = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
154         ehdr->e_phentsize = elf16_to_cpu(ehdr,    154         ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
155         ehdr->e_phnum     = elf16_to_cpu(ehdr,    155         ehdr->e_phnum     = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
156         ehdr->e_shentsize = elf16_to_cpu(ehdr,    156         ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
157         ehdr->e_shnum     = elf16_to_cpu(ehdr,    157         ehdr->e_shnum     = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
158         ehdr->e_shstrndx  = elf16_to_cpu(ehdr,    158         ehdr->e_shstrndx  = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
159                                                   159 
160         switch (ehdr->e_ident[EI_CLASS]) {        160         switch (ehdr->e_ident[EI_CLASS]) {
161         case ELFCLASS64:                          161         case ELFCLASS64:
162                 ehdr->e_entry = elf64_to_cpu(e    162                 ehdr->e_entry = elf64_to_cpu(ehdr, buf_ehdr->e_entry);
163                 ehdr->e_phoff = elf64_to_cpu(e    163                 ehdr->e_phoff = elf64_to_cpu(ehdr, buf_ehdr->e_phoff);
164                 ehdr->e_shoff = elf64_to_cpu(e    164                 ehdr->e_shoff = elf64_to_cpu(ehdr, buf_ehdr->e_shoff);
165                 break;                            165                 break;
166                                                   166 
167         case ELFCLASS32:                          167         case ELFCLASS32:
168                 ehdr->e_entry = elf32_to_cpu(e    168                 ehdr->e_entry = elf32_to_cpu(ehdr, buf_ehdr->e_entry);
169                 ehdr->e_phoff = elf32_to_cpu(e    169                 ehdr->e_phoff = elf32_to_cpu(ehdr, buf_ehdr->e_phoff);
170                 ehdr->e_shoff = elf32_to_cpu(e    170                 ehdr->e_shoff = elf32_to_cpu(ehdr, buf_ehdr->e_shoff);
171                 break;                            171                 break;
172                                                   172 
173         default:                                  173         default:
174                 pr_debug("Unknown ELF class.\n    174                 pr_debug("Unknown ELF class.\n");
175                 return -EINVAL;                   175                 return -EINVAL;
176         }                                         176         }
177                                                   177 
178         return elf_is_ehdr_sane(ehdr, len) ? 0    178         return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
179 }                                                 179 }
180                                                   180 
181 /**                                               181 /**
182  * elf_is_phdr_sane - check that it is safe to    182  * elf_is_phdr_sane - check that it is safe to use the program header
183  * @buf_len:    size of the buffer in which th    183  * @buf_len:    size of the buffer in which the ELF file is loaded.
184  */                                               184  */
185 static bool elf_is_phdr_sane(const struct elf_    185 static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
186 {                                                 186 {
187                                                   187 
188         if (phdr->p_offset + phdr->p_filesz <     188         if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
189                 pr_debug("ELF segment location    189                 pr_debug("ELF segment location wraps around.\n");
190                 return false;                     190                 return false;
191         } else if (phdr->p_offset + phdr->p_fi    191         } else if (phdr->p_offset + phdr->p_filesz > buf_len) {
192                 pr_debug("ELF segment not in f    192                 pr_debug("ELF segment not in file.\n");
193                 return false;                     193                 return false;
194         } else if (phdr->p_paddr + phdr->p_mem    194         } else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
195                 pr_debug("ELF segment address     195                 pr_debug("ELF segment address wraps around.\n");
196                 return false;                     196                 return false;
197         }                                         197         }
198                                                   198 
199         return true;                              199         return true;
200 }                                                 200 }
201                                                   201 
202 static int elf_read_phdr(const char *buf, size    202 static int elf_read_phdr(const char *buf, size_t len,
203                          struct kexec_elf_info    203                          struct kexec_elf_info *elf_info,
204                          int idx)                 204                          int idx)
205 {                                                 205 {
206         /* Override the const in proghdrs, we     206         /* Override the const in proghdrs, we are the ones doing the loading. */
207         struct elf_phdr *phdr = (struct elf_ph    207         struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
208         const struct elfhdr *ehdr = elf_info->    208         const struct elfhdr *ehdr = elf_info->ehdr;
209         const char *pbuf;                         209         const char *pbuf;
210         struct elf_phdr *buf_phdr;                210         struct elf_phdr *buf_phdr;
211                                                   211 
212         pbuf = buf + elf_info->ehdr->e_phoff +    212         pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
213         buf_phdr = (struct elf_phdr *) pbuf;      213         buf_phdr = (struct elf_phdr *) pbuf;
214                                                   214 
215         phdr->p_type   = elf32_to_cpu(elf_info    215         phdr->p_type   = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
216         phdr->p_flags  = elf32_to_cpu(elf_info    216         phdr->p_flags  = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
217                                                   217 
218         switch (ehdr->e_ident[EI_CLASS]) {        218         switch (ehdr->e_ident[EI_CLASS]) {
219         case ELFCLASS64:                          219         case ELFCLASS64:
220                 phdr->p_offset = elf64_to_cpu(    220                 phdr->p_offset = elf64_to_cpu(ehdr, buf_phdr->p_offset);
221                 phdr->p_paddr  = elf64_to_cpu(    221                 phdr->p_paddr  = elf64_to_cpu(ehdr, buf_phdr->p_paddr);
222                 phdr->p_vaddr  = elf64_to_cpu(    222                 phdr->p_vaddr  = elf64_to_cpu(ehdr, buf_phdr->p_vaddr);
223                 phdr->p_filesz = elf64_to_cpu(    223                 phdr->p_filesz = elf64_to_cpu(ehdr, buf_phdr->p_filesz);
224                 phdr->p_memsz  = elf64_to_cpu(    224                 phdr->p_memsz  = elf64_to_cpu(ehdr, buf_phdr->p_memsz);
225                 phdr->p_align  = elf64_to_cpu(    225                 phdr->p_align  = elf64_to_cpu(ehdr, buf_phdr->p_align);
226                 break;                            226                 break;
227                                                   227 
228         case ELFCLASS32:                          228         case ELFCLASS32:
229                 phdr->p_offset = elf32_to_cpu(    229                 phdr->p_offset = elf32_to_cpu(ehdr, buf_phdr->p_offset);
230                 phdr->p_paddr  = elf32_to_cpu(    230                 phdr->p_paddr  = elf32_to_cpu(ehdr, buf_phdr->p_paddr);
231                 phdr->p_vaddr  = elf32_to_cpu(    231                 phdr->p_vaddr  = elf32_to_cpu(ehdr, buf_phdr->p_vaddr);
232                 phdr->p_filesz = elf32_to_cpu(    232                 phdr->p_filesz = elf32_to_cpu(ehdr, buf_phdr->p_filesz);
233                 phdr->p_memsz  = elf32_to_cpu(    233                 phdr->p_memsz  = elf32_to_cpu(ehdr, buf_phdr->p_memsz);
234                 phdr->p_align  = elf32_to_cpu(    234                 phdr->p_align  = elf32_to_cpu(ehdr, buf_phdr->p_align);
235                 break;                            235                 break;
236                                                   236 
237         default:                                  237         default:
238                 pr_debug("Unknown ELF class.\n    238                 pr_debug("Unknown ELF class.\n");
239                 return -EINVAL;                   239                 return -EINVAL;
240         }                                         240         }
241                                                   241 
242         return elf_is_phdr_sane(phdr, len) ? 0    242         return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
243 }                                                 243 }
244                                                   244 
245 /**                                               245 /**
246  * elf_read_phdrs - read the program headers f    246  * elf_read_phdrs - read the program headers from the buffer
247  *                                                247  *
248  * This function assumes that the program head    248  * This function assumes that the program header table was checked for sanity.
249  * Use elf_is_ehdr_sane() if it wasn't.           249  * Use elf_is_ehdr_sane() if it wasn't.
250  */                                               250  */
251 static int elf_read_phdrs(const char *buf, siz    251 static int elf_read_phdrs(const char *buf, size_t len,
252                           struct kexec_elf_inf    252                           struct kexec_elf_info *elf_info)
253 {                                                 253 {
254         size_t phdr_size, i;                      254         size_t phdr_size, i;
255         const struct elfhdr *ehdr = elf_info->    255         const struct elfhdr *ehdr = elf_info->ehdr;
256                                                   256 
257         /*                                        257         /*
258          * e_phnum is at most 65535 so calcula    258          * e_phnum is at most 65535 so calculating the size of the
259          * program header cannot overflow.        259          * program header cannot overflow.
260          */                                       260          */
261         phdr_size = sizeof(struct elf_phdr) *     261         phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
262                                                   262 
263         elf_info->proghdrs = kzalloc(phdr_size    263         elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
264         if (!elf_info->proghdrs)                  264         if (!elf_info->proghdrs)
265                 return -ENOMEM;                   265                 return -ENOMEM;
266                                                   266 
267         for (i = 0; i < ehdr->e_phnum; i++) {     267         for (i = 0; i < ehdr->e_phnum; i++) {
268                 int ret;                          268                 int ret;
269                                                   269 
270                 ret = elf_read_phdr(buf, len,     270                 ret = elf_read_phdr(buf, len, elf_info, i);
271                 if (ret) {                        271                 if (ret) {
272                         kfree(elf_info->proghd    272                         kfree(elf_info->proghdrs);
273                         elf_info->proghdrs = N    273                         elf_info->proghdrs = NULL;
274                         return ret;               274                         return ret;
275                 }                                 275                 }
276         }                                         276         }
277                                                   277 
278         return 0;                                 278         return 0;
279 }                                                 279 }
280                                                   280 
281 /**                                               281 /**
282  * elf_read_from_buffer - read ELF file and se    282  * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
283  * @buf:        Buffer to read ELF file from.     283  * @buf:        Buffer to read ELF file from.
284  * @len:        Size of @buf.                     284  * @len:        Size of @buf.
285  * @ehdr:       Pointer to existing struct whi    285  * @ehdr:       Pointer to existing struct which will be populated.
286  * @elf_info:   Pointer to existing struct whi    286  * @elf_info:   Pointer to existing struct which will be populated.
287  *                                                287  *
288  * This function allows reading ELF files with    288  * This function allows reading ELF files with different byte order than
289  * the kernel, byte-swapping the fields as nee    289  * the kernel, byte-swapping the fields as needed.
290  *                                                290  *
291  * Return:                                        291  * Return:
292  * On success returns 0, and the caller should    292  * On success returns 0, and the caller should call
293  * kexec_free_elf_info(elf_info) to free the m    293  * kexec_free_elf_info(elf_info) to free the memory allocated for the section
294  * and program headers.                           294  * and program headers.
295  */                                               295  */
296 static int elf_read_from_buffer(const char *bu    296 static int elf_read_from_buffer(const char *buf, size_t len,
297                                 struct elfhdr     297                                 struct elfhdr *ehdr,
298                                 struct kexec_e    298                                 struct kexec_elf_info *elf_info)
299 {                                                 299 {
300         int ret;                                  300         int ret;
301                                                   301 
302         ret = elf_read_ehdr(buf, len, ehdr);      302         ret = elf_read_ehdr(buf, len, ehdr);
303         if (ret)                                  303         if (ret)
304                 return ret;                       304                 return ret;
305                                                   305 
306         elf_info->buffer = buf;                   306         elf_info->buffer = buf;
307         elf_info->ehdr = ehdr;                    307         elf_info->ehdr = ehdr;
308         if (ehdr->e_phoff > 0 && ehdr->e_phnum    308         if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
309                 ret = elf_read_phdrs(buf, len,    309                 ret = elf_read_phdrs(buf, len, elf_info);
310                 if (ret)                          310                 if (ret)
311                         return ret;               311                         return ret;
312         }                                         312         }
313         return 0;                                 313         return 0;
314 }                                                 314 }
315                                                   315 
316 /**                                               316 /**
317  * kexec_free_elf_info - free memory allocated    317  * kexec_free_elf_info - free memory allocated by elf_read_from_buffer
318  */                                               318  */
319 void kexec_free_elf_info(struct kexec_elf_info    319 void kexec_free_elf_info(struct kexec_elf_info *elf_info)
320 {                                                 320 {
321         kfree(elf_info->proghdrs);                321         kfree(elf_info->proghdrs);
322         memset(elf_info, 0, sizeof(*elf_info))    322         memset(elf_info, 0, sizeof(*elf_info));
323 }                                                 323 }
324 /**                                               324 /**
325  * kexec_build_elf_info - read ELF executable     325  * kexec_build_elf_info - read ELF executable and check that we can use it
326  */                                               326  */
327 int kexec_build_elf_info(const char *buf, size    327 int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr,
328                                struct kexec_el    328                                struct kexec_elf_info *elf_info)
329 {                                                 329 {
330         int i;                                    330         int i;
331         int ret;                                  331         int ret;
332                                                   332 
333         ret = elf_read_from_buffer(buf, len, e    333         ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
334         if (ret)                                  334         if (ret)
335                 return ret;                       335                 return ret;
336                                                   336 
337         /* Big endian vmlinux has type ET_DYN.    337         /* Big endian vmlinux has type ET_DYN. */
338         if (ehdr->e_type != ET_EXEC && ehdr->e    338         if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
339                 pr_err("Not an ELF executable.    339                 pr_err("Not an ELF executable.\n");
340                 goto error;                       340                 goto error;
341         } else if (!elf_info->proghdrs) {         341         } else if (!elf_info->proghdrs) {
342                 pr_err("No ELF program header.    342                 pr_err("No ELF program header.\n");
343                 goto error;                       343                 goto error;
344         }                                         344         }
345                                                   345 
346         for (i = 0; i < ehdr->e_phnum; i++) {     346         for (i = 0; i < ehdr->e_phnum; i++) {
347                 /*                                347                 /*
348                  * Kexec does not support load    348                  * Kexec does not support loading interpreters.
349                  * In addition this check keep    349                  * In addition this check keeps us from attempting
350                  * to kexec ordinay executable    350                  * to kexec ordinay executables.
351                  */                               351                  */
352                 if (elf_info->proghdrs[i].p_ty    352                 if (elf_info->proghdrs[i].p_type == PT_INTERP) {
353                         pr_err("Requires an EL    353                         pr_err("Requires an ELF interpreter.\n");
354                         goto error;               354                         goto error;
355                 }                                 355                 }
356         }                                         356         }
357                                                   357 
358         return 0;                                 358         return 0;
359 error:                                            359 error:
360         kexec_free_elf_info(elf_info);            360         kexec_free_elf_info(elf_info);
361         return -ENOEXEC;                          361         return -ENOEXEC;
362 }                                                 362 }
363                                                   363 
364                                                   364 
365 int kexec_elf_probe(const char *buf, unsigned     365 int kexec_elf_probe(const char *buf, unsigned long len)
366 {                                                 366 {
367         struct elfhdr ehdr;                       367         struct elfhdr ehdr;
368         struct kexec_elf_info elf_info;           368         struct kexec_elf_info elf_info;
369         int ret;                                  369         int ret;
370                                                   370 
371         ret = kexec_build_elf_info(buf, len, &    371         ret = kexec_build_elf_info(buf, len, &ehdr, &elf_info);
372         if (ret)                                  372         if (ret)
373                 return ret;                       373                 return ret;
374                                                   374 
375         kexec_free_elf_info(&elf_info);           375         kexec_free_elf_info(&elf_info);
376                                                   376 
377         return elf_check_arch(&ehdr) ? 0 : -EN    377         return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
378 }                                                 378 }
379                                                   379 
380 /**                                               380 /**
381  * kexec_elf_load - load ELF executable image     381  * kexec_elf_load - load ELF executable image
382  * @lowest_load_addr:   On return, will be the    382  * @lowest_load_addr:   On return, will be the address where the first PT_LOAD
383  *                      section will be loaded    383  *                      section will be loaded in memory.
384  *                                                384  *
385  * Return:                                        385  * Return:
386  * 0 on success, negative value on failure.       386  * 0 on success, negative value on failure.
387  */                                               387  */
388 int kexec_elf_load(struct kimage *image, struc    388 int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
389                          struct kexec_elf_info    389                          struct kexec_elf_info *elf_info,
390                          struct kexec_buf *kbu    390                          struct kexec_buf *kbuf,
391                          unsigned long *lowest    391                          unsigned long *lowest_load_addr)
392 {                                                 392 {
393         unsigned long lowest_addr = UINT_MAX;     393         unsigned long lowest_addr = UINT_MAX;
394         int ret;                                  394         int ret;
395         size_t i;                                 395         size_t i;
396                                                   396 
397         /* Read in the PT_LOAD segments. */       397         /* Read in the PT_LOAD segments. */
398         for (i = 0; i < ehdr->e_phnum; i++) {     398         for (i = 0; i < ehdr->e_phnum; i++) {
399                 unsigned long load_addr;          399                 unsigned long load_addr;
400                 size_t size;                      400                 size_t size;
401                 const struct elf_phdr *phdr;      401                 const struct elf_phdr *phdr;
402                                                   402 
403                 phdr = &elf_info->proghdrs[i];    403                 phdr = &elf_info->proghdrs[i];
404                 if (phdr->p_type != PT_LOAD)      404                 if (phdr->p_type != PT_LOAD)
405                         continue;                 405                         continue;
406                                                   406 
407                 size = phdr->p_filesz;            407                 size = phdr->p_filesz;
408                 if (size > phdr->p_memsz)         408                 if (size > phdr->p_memsz)
409                         size = phdr->p_memsz;     409                         size = phdr->p_memsz;
410                                                   410 
411                 kbuf->buffer = (void *) elf_in    411                 kbuf->buffer = (void *) elf_info->buffer + phdr->p_offset;
412                 kbuf->bufsz = size;               412                 kbuf->bufsz = size;
413                 kbuf->memsz = phdr->p_memsz;      413                 kbuf->memsz = phdr->p_memsz;
414                 kbuf->buf_align = phdr->p_alig    414                 kbuf->buf_align = phdr->p_align;
415                 kbuf->buf_min = phdr->p_paddr;    415                 kbuf->buf_min = phdr->p_paddr;
416                 kbuf->mem = KEXEC_BUF_MEM_UNKN    416                 kbuf->mem = KEXEC_BUF_MEM_UNKNOWN;
417                 ret = kexec_add_buffer(kbuf);     417                 ret = kexec_add_buffer(kbuf);
418                 if (ret)                          418                 if (ret)
419                         goto out;                 419                         goto out;
420                 load_addr = kbuf->mem;            420                 load_addr = kbuf->mem;
421                                                   421 
422                 if (load_addr < lowest_addr)      422                 if (load_addr < lowest_addr)
423                         lowest_addr = load_add    423                         lowest_addr = load_addr;
424         }                                         424         }
425                                                   425 
426         *lowest_load_addr = lowest_addr;          426         *lowest_load_addr = lowest_addr;
427         ret = 0;                                  427         ret = 0;
428  out:                                             428  out:
429         return ret;                               429         return ret;
430 }                                                 430 }
431                                                   431 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php