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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.