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