1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 #include "elfparse.h" 7 8 int is_elf_magic (const uint8_t *buf) 9 { 10 return (buf[EI_MAG0] == ELFMAG0) && 11 (buf[EI_MAG1] == ELFMAG1) && 12 (buf[EI_MAG2] == ELFMAG2) && 13 (buf[EI_MAG3] == ELFMAG3); 14 } 15 16 #define parseElftemplate(bit) \ 17 ElfType parseElf ## bit(FILE *elf_file, uint8_t *pHead, int little_endian) \ 18 { \ 19 ElfType ret = ELFSTATIC; \ 20 Minijail_Elf ## bit ## _Ehdr *pHeader = NULL; \ 21 Minijail_Elf ## bit ## _Phdr pheader = { 0 }; \ 22 uint32_t i = 0; \ 23 \ 24 if (!elf_file || !pHead) \ 25 return ELFERROR; \ 26 \ 27 pHeader = (Minijail_Elf ## bit ## _Ehdr *)pHead; \ 28 if (little_endian) { \ 29 pHeader->e_phoff = le ## bit ## toh(pHeader->e_phoff); \ 30 pHeader->e_phentsize = le16toh(pHeader->e_phentsize); \ 31 pHeader->e_phnum = le16toh(pHeader->e_phnum); \ 32 } else { \ 33 pHeader->e_phoff = be ## bit ## toh(pHeader->e_phoff); \ 34 pHeader->e_phentsize = be16toh(pHeader->e_phentsize); \ 35 pHeader->e_phnum = be16toh(pHeader->e_phnum); \ 36 } \ 37 if (pHeader->e_phentsize != sizeof(Minijail_Elf ## bit ## _Phdr)) \ 38 return ELFERROR; \ 39 \ 40 if (fseek(elf_file, pHeader->e_phoff, SEEK_SET) != 0) \ 41 return ELFERROR; \ 42 \ 43 for (i = 0; i < pHeader->e_phnum; i++) { \ 44 if (fread(&pheader, sizeof(pheader), 1, elf_file) == 1) { \ 45 if (pheader.p_type == PT_INTERP) { \ 46 ret = ELFDYNAMIC; \ 47 break; \ 48 } \ 49 } else { \ 50 ret = ELFERROR; \ 51 break; \ 52 } \ 53 } \ 54 return ret; \ 55 } 56 parseElftemplate(64) 57 parseElftemplate(32) 58 59 /* Public function to determine the linkage of an ELF. */ 60 ElfType get_elf_linkage(const char *path) 61 { 62 ElfType ret = ELFERROR; 63 FILE *elf_file = NULL; 64 uint8_t pHeader[HEADERSIZE] = ""; 65 66 elf_file = fopen(path, "r"); 67 if (elf_file) { 68 if (fread(pHeader, 1, HEADERSIZE, elf_file) == HEADERSIZE) { 69 if (is_elf_magic(pHeader)) { 70 if ((pHeader[EI_DATA] == ELFDATA2LSB) && 71 (pHeader[EI_CLASS] == ELFCLASS64)) { 72 /* 64 bit little endian */ 73 ret = parseElf64(elf_file, pHeader, 1); 74 } else if ((pHeader[EI_DATA] == ELFDATA2MSB) && 75 (pHeader[EI_CLASS] == ELFCLASS64)) { 76 /* 64 bit big endian */ 77 ret = parseElf64(elf_file, pHeader, 0); 78 } else if ((pHeader[EI_DATA] == ELFDATA2LSB) && 79 (pHeader[EI_CLASS] == ELFCLASS32)) { 80 /* 32 bit little endian */ 81 ret = parseElf32(elf_file, pHeader, 1); 82 } else if ((pHeader[EI_DATA] == ELFDATA2MSB) && 83 (pHeader[EI_CLASS] == ELFCLASS32)) { 84 /* 32 bit big endian */ 85 ret = parseElf32(elf_file, pHeader, 0); 86 } 87 } else { 88 /* 89 * The binary is not an ELF. We assume it's a 90 * script. We should parse the #! line and 91 * check the interpreter to guard against 92 * static interpreters escaping the sandbox. 93 * As minijail is only called from rootfs 94 * it was deemed not necessary to check this. 95 * So we will just let execve decided if this 96 * is valid. 97 */ 98 ret = ELFDYNAMIC; 99 } 100 } else { 101 /* 102 * The file is smaller than |HEADERSIZE| bytes. 103 * We assume it's a short script. See above for 104 * reasoning on scripts. 105 */ 106 ret = ELFDYNAMIC; 107 } 108 fclose(elf_file); 109 } 110 return ret; 111 } 112