~ [ 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-4.18.20)


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