Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kexec_elf: support 32 bit ELF files

The powerpc version only supported 64 bit. Add some
code to switch decoding of fields during runtime so
we can kexec a 32 bit kernel from a 64 bit kernel and
vice versa.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
Reviewed-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Sven Schnelle and committed by
Helge Deller
ea46a13e 571ceb7d

+42 -15
+42 -15
kernel/kexec_elf.c
··· 21 21 #include <linux/slab.h> 22 22 #include <linux/types.h> 23 23 24 - #define elf_addr_to_cpu elf64_to_cpu 25 - 26 24 static inline bool elf_is_elf_file(const struct elfhdr *ehdr) 27 25 { 28 26 return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0; ··· 150 152 ehdr->e_type = elf16_to_cpu(ehdr, buf_ehdr->e_type); 151 153 ehdr->e_machine = elf16_to_cpu(ehdr, buf_ehdr->e_machine); 152 154 ehdr->e_version = elf32_to_cpu(ehdr, buf_ehdr->e_version); 153 - ehdr->e_entry = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry); 154 - ehdr->e_phoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff); 155 - ehdr->e_shoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff); 156 155 ehdr->e_flags = elf32_to_cpu(ehdr, buf_ehdr->e_flags); 157 156 ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize); 158 157 ehdr->e_phnum = elf16_to_cpu(ehdr, buf_ehdr->e_phnum); 159 158 ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize); 160 159 ehdr->e_shnum = elf16_to_cpu(ehdr, buf_ehdr->e_shnum); 161 160 ehdr->e_shstrndx = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx); 161 + 162 + switch (ehdr->e_ident[EI_CLASS]) { 163 + case ELFCLASS64: 164 + ehdr->e_entry = elf64_to_cpu(ehdr, buf_ehdr->e_entry); 165 + ehdr->e_phoff = elf64_to_cpu(ehdr, buf_ehdr->e_phoff); 166 + ehdr->e_shoff = elf64_to_cpu(ehdr, buf_ehdr->e_shoff); 167 + break; 168 + 169 + case ELFCLASS32: 170 + ehdr->e_entry = elf32_to_cpu(ehdr, buf_ehdr->e_entry); 171 + ehdr->e_phoff = elf32_to_cpu(ehdr, buf_ehdr->e_phoff); 172 + ehdr->e_shoff = elf32_to_cpu(ehdr, buf_ehdr->e_shoff); 173 + break; 174 + 175 + default: 176 + pr_debug("Unknown ELF class.\n"); 177 + return -EINVAL; 178 + } 162 179 163 180 return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC; 164 181 } ··· 205 192 { 206 193 /* Override the const in proghdrs, we are the ones doing the loading. */ 207 194 struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx]; 195 + const struct elfhdr *ehdr = elf_info->ehdr; 208 196 const char *pbuf; 209 197 struct elf_phdr *buf_phdr; 210 198 ··· 213 199 buf_phdr = (struct elf_phdr *) pbuf; 214 200 215 201 phdr->p_type = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type); 216 - phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset); 217 - phdr->p_paddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr); 218 - phdr->p_vaddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr); 219 202 phdr->p_flags = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags); 220 203 221 - /* 222 - * The following fields have a type equivalent to Elf_Addr 223 - * both in 32 bit and 64 bit ELF. 224 - */ 225 - phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz); 226 - phdr->p_memsz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz); 227 - phdr->p_align = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align); 204 + switch (ehdr->e_ident[EI_CLASS]) { 205 + case ELFCLASS64: 206 + phdr->p_offset = elf64_to_cpu(ehdr, buf_phdr->p_offset); 207 + phdr->p_paddr = elf64_to_cpu(ehdr, buf_phdr->p_paddr); 208 + phdr->p_vaddr = elf64_to_cpu(ehdr, buf_phdr->p_vaddr); 209 + phdr->p_filesz = elf64_to_cpu(ehdr, buf_phdr->p_filesz); 210 + phdr->p_memsz = elf64_to_cpu(ehdr, buf_phdr->p_memsz); 211 + phdr->p_align = elf64_to_cpu(ehdr, buf_phdr->p_align); 212 + break; 213 + 214 + case ELFCLASS32: 215 + phdr->p_offset = elf32_to_cpu(ehdr, buf_phdr->p_offset); 216 + phdr->p_paddr = elf32_to_cpu(ehdr, buf_phdr->p_paddr); 217 + phdr->p_vaddr = elf32_to_cpu(ehdr, buf_phdr->p_vaddr); 218 + phdr->p_filesz = elf32_to_cpu(ehdr, buf_phdr->p_filesz); 219 + phdr->p_memsz = elf32_to_cpu(ehdr, buf_phdr->p_memsz); 220 + phdr->p_align = elf32_to_cpu(ehdr, buf_phdr->p_align); 221 + break; 222 + 223 + default: 224 + pr_debug("Unknown ELF class.\n"); 225 + return -EINVAL; 226 + } 228 227 229 228 return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC; 230 229 }