PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
elf64_validate.c
Go to the documentation of this file.
1#include "common/elf.h"
2
4{
5 // This is a big function, but all it does just verify that every single thing that i can think of is as it should
6 // be.
7 if (elf == NULL || data == NULL || size < sizeof(Elf64_Ehdr))
8 {
9 return 200;
10 }
11
12 elf->symtab = NULL;
13 elf->dynsym = NULL;
14
15 Elf64_Ehdr* header = (Elf64_Ehdr*)data;
16 if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 ||
17 header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3)
18 {
19 return 1;
20 }
21
22 if (header->e_ident[EI_CLASS] != ELFCLASS64)
23 {
24 return 2;
25 }
26
27 if (header->e_ident[EI_DATA] != ELFDATALSB)
28 {
29 return 3;
30 }
31
32 if (header->e_ident[EI_VERSION] != EV_CURRENT || header->e_version != EV_CURRENT)
33 {
34 return 4;
35 }
36
37 if (header->e_ident[EI_OSABI] != ELFOSABI_NONE && header->e_ident[EI_OSABI] != ELFOSABI_GNU)
38 {
39 return 5;
40 }
41
42 if (header->e_shnum > 0 && header->e_shentsize > UINT64_MAX / header->e_shnum)
43 {
44 return 6;
45 }
46 if (header->e_shoff > size || (header->e_shentsize * header->e_shnum) > size - header->e_shoff)
47 {
48 return 7;
49 }
50 if (header->e_shnum > 0 && header->e_shentsize < sizeof(Elf64_Shdr))
51 {
52 return 8;
53 }
54
55 if (header->e_phnum > 0 && header->e_phentsize > UINT64_MAX / header->e_phnum)
56 {
57 return 9;
58 }
59 if (header->e_phoff > size || (header->e_phentsize * header->e_phnum) > size - header->e_phoff)
60 {
61 return 10;
62 }
63 if (header->e_phnum > 0 && header->e_phentsize < sizeof(Elf64_Phdr))
64 {
65 return 11;
66 }
67
68 Elf64_Shdr* shstrHdr = NULL;
69 uint64_t shstrndx = header->e_shstrndx;
70
71 if (shstrndx == SHN_XINDEX)
72 {
73 if (header->e_shnum == 0)
74 {
75 return 12;
76 }
77 Elf64_Shdr* firstShdr = (Elf64_Shdr*)((uintptr_t)data + header->e_shoff);
78 shstrndx = firstShdr->sh_link;
79 }
80
81 if (shstrndx != SHN_UNDEF)
82 {
83 if (shstrndx >= header->e_shnum)
84 {
85 return 13;
86 }
87 shstrHdr = (Elf64_Shdr*)((uintptr_t)data + header->e_shoff + (shstrndx * header->e_shentsize));
88
89 if (shstrHdr->sh_type != SHT_STRTAB)
90 {
91 return 14;
92 }
93
94 if (shstrHdr->sh_offset > size || shstrHdr->sh_size > size - shstrHdr->sh_offset)
95 {
96 return 15;
97 }
98
99 if (shstrHdr->sh_size == 0)
100 {
101 return 16;
102 }
103 char* strTable = (char*)((uintptr_t)data + shstrHdr->sh_offset);
104 if (strTable[shstrHdr->sh_size - 1] != '\0')
105 {
106 return 17;
107 }
108 }
109
110 uint64_t symtabCount = 0;
111 uint64_t dynsymCount = 0;
112 for (uint64_t i = 0; i < header->e_shnum; i++)
113 {
114 Elf64_Shdr* shdr = (Elf64_Shdr*)((uintptr_t)data + header->e_shoff + (i * header->e_shentsize));
115
116 if (shdr->sh_type != SHT_NOBITS && (shdr->sh_offset > size || shdr->sh_size > size - shdr->sh_offset))
117 {
118 return 18;
119 }
120
121 if (shstrHdr == NULL && shdr->sh_name != 0)
122 {
123 return 19;
124 }
125 if (shstrHdr != NULL && shdr->sh_name >= shstrHdr->sh_size)
126 {
127 return 20;
128 }
129
130 switch (shdr->sh_type)
131 {
132 case SHT_STRTAB:
133 if (shdr->sh_size == 0)
134 {
135 return 21;
136 }
137 char* strTable = (char*)((uintptr_t)data + shdr->sh_offset);
138 if (strTable[shdr->sh_size - 1] != '\0')
139 {
140 return 22;
141 }
142 break;
143 case SHT_SYMTAB:
144 case SHT_DYNSYM:
145 if (shdr->sh_type == SHT_SYMTAB)
146 {
147 symtabCount++;
148 elf->symtab = shdr;
149 }
150 else
151 {
152 dynsymCount++;
153 elf->dynsym = shdr;
154 }
155 if (dynsymCount > 1)
156 {
157 return 23;
158 }
159 if (symtabCount > 1)
160 {
161 return 24;
162 }
163
164 if (shdr->sh_entsize < sizeof(Elf64_Sym))
165 {
166 return 25;
167 }
168 if (shdr->sh_size % shdr->sh_entsize != 0)
169 {
170 return 26;
171 }
172
173 if (shdr->sh_link >= header->e_shnum)
174 {
175 return 27;
176 }
177 Elf64_Shdr* strtabHdr =
178 (Elf64_Shdr*)((uintptr_t)data + header->e_shoff + (shdr->sh_link * header->e_shentsize));
179 if (strtabHdr->sh_type != SHT_STRTAB)
180 {
181 return 28;
182 }
183
184 uint64_t symCount = shdr->sh_size / shdr->sh_entsize;
185 void* symTableBase = (void*)((uintptr_t)data + shdr->sh_offset);
186 for (uint64_t j = 0; j < symCount; j++)
187 {
188 Elf64_Sym* currentSym = (Elf64_Sym*)((uintptr_t)symTableBase + (j * shdr->sh_entsize));
189 if (currentSym->st_name >= strtabHdr->sh_size)
190 {
191 return 29;
192 }
193 }
194 break;
195 case SHT_RELA:
196 if (shdr->sh_entsize < sizeof(Elf64_Rela))
197 {
198 return 30;
199 }
200 if (shdr->sh_size % shdr->sh_entsize != 0)
201 {
202 return 31;
203 }
204 if (shdr->sh_link >= header->e_shnum)
205 {
206 return 32;
207 }
208 Elf64_Shdr* symtabHdr =
209 (Elf64_Shdr*)((uintptr_t)data + header->e_shoff + (shdr->sh_link * header->e_shentsize));
210 if (symtabHdr->sh_type != SHT_SYMTAB && symtabHdr->sh_type != SHT_DYNSYM)
211 {
212 return 33;
213 }
214 if (shdr->sh_info >= header->e_shnum)
215 {
216 return 34;
217 }
218 break;
219 case SHT_REL:
220 if (shdr->sh_entsize < sizeof(Elf64_Rel))
221 {
222 return 35;
223 }
224 if (shdr->sh_size % shdr->sh_entsize != 0)
225 {
226 return 36;
227 }
228 if (shdr->sh_link >= header->e_shnum)
229 {
230 return 37;
231 }
232 Elf64_Shdr* symtabHdrRel =
233 (Elf64_Shdr*)((uintptr_t)data + header->e_shoff + (shdr->sh_link * header->e_shentsize));
234 if (symtabHdrRel->sh_type != SHT_SYMTAB && symtabHdrRel->sh_type != SHT_DYNSYM)
235 {
236 return 38;
237 }
238 if (shdr->sh_info >= header->e_shnum)
239 {
240 return 39;
241 }
242 break;
243 default:
244 break;
245 }
246 }
247
248 for (uint64_t i = 0; i < header->e_phnum; i++)
249 {
250 Elf64_Phdr* phdr = (Elf64_Phdr*)((uintptr_t)data + header->e_phoff + (i * header->e_phentsize));
251 if (phdr->p_offset > size || phdr->p_filesz > size - phdr->p_offset)
252 {
253 return 40;
254 }
255 switch (phdr->p_type)
256 {
257 case PT_LOAD:
258 if (phdr->p_memsz < phdr->p_filesz)
259 {
260 return 41;
261 }
262 break;
263 case PT_INTERP:
264 if (phdr->p_filesz == 0)
265 {
266 return 42;
267 }
268 unsigned char* interpData = (unsigned char*)((uintptr_t)data + phdr->p_offset);
269 if (elf_memchr(interpData, '\0', phdr->p_filesz) == NULL)
270 {
271 return 43;
272 }
273 break;
274 case PT_PHDR:
275 if (phdr->p_offset != header->e_phoff || phdr->p_filesz != (uint64_t)header->e_phnum * header->e_phentsize)
276 {
277 return 44;
278 }
279 break;
280 default:
281 break;
282 }
283 }
284
285 elf->header = data;
286 elf->size = size;
287 return 0;
288}
static fd_t data
Definition dwm.c:21
uint64_t elf64_validate(Elf64_File *elf, void *data, uint64_t size)
Validate a files content and initalize a ELF64_File structure using it.
@ ELFMAG1
Expected value for e_ident[EI_MAG1]
Definition elf.h:133
@ ELFMAG0
Expected value for e_ident[EI_MAG0]
Definition elf.h:132
@ ELFMAG3
Expected value for e_ident[EI_MAG3]
Definition elf.h:135
@ ELFMAG2
Expected value for e_ident[EI_MAG2]
Definition elf.h:134
@ SHN_XINDEX
Indicates that the actual index is too large to fit and is stored elsewhere.
Definition elf.h:454
@ SHN_UNDEF
Undefined section.
Definition elf.h:446
@ ELFCLASS64
64-bit objects, we always expect this value
Definition elf.h:149
@ ELFDATALSB
Little-endian encoding, we always expect this value.
Definition elf.h:162
@ EV_CURRENT
Current version, we always expect this value.
Definition elf.h:173
@ EI_MAG1
Index of magic number byte 1.
Definition elf.h:75
@ EI_DATA
Index of the data encoding byte.
Definition elf.h:79
@ EI_MAG0
Index of magic number byte 0.
Definition elf.h:74
@ EI_MAG3
Index of magic number byte 3.
Definition elf.h:77
@ EI_CLASS
Index of the file class byte.
Definition elf.h:78
@ EI_OSABI
Index of the OS/ABI identification byte.
Definition elf.h:81
@ EI_VERSION
Index of the file version byte.
Definition elf.h:80
@ EI_MAG2
Index of magic number byte 2.
Definition elf.h:76
@ PT_PHDR
Location and size of program header table.
Definition elf.h:753
@ PT_INTERP
Program interpreter path name.
Definition elf.h:750
@ PT_LOAD
Loadable segment.
Definition elf.h:748
@ ELFOSABI_NONE
No extensions or unspecified.
Definition elf.h:190
@ ELFOSABI_GNU
GNU, we always expect this value.
Definition elf.h:193
@ SHT_RELA
Contains relocation entries with explicit addends.
Definition elf.h:493
@ SHT_STRTAB
Contains a string table.
Definition elf.h:492
@ SHT_REL
Contains relocation entries without explicit addends.
Definition elf.h:498
@ SHT_SYMTAB
Contains a symbol table, only 1 per file.
Definition elf.h:491
@ SHT_NOBITS
Acts like SHT_PROGBITS but does not occupy any space in the file.
Definition elf.h:497
@ SHT_DYNSYM
Acts like SHT_SYMTAB but holds a minimal set of dynamic linking symbols, only 1 per file.
Definition elf.h:500
#define NULL
Pointer error value.
Definition NULL.h:23
#define elf_memchr
Definition elf.h:37
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
#define UINT64_MAX
Definition stdint.h:74
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
ELF64 Header.
Definition elf.h:95
Elf64_Half e_shentsize
Size in bytes of one entry in the files section header table.
Definition elf.h:107
Elf64_Half e_shnum
Definition elf.h:114
Elf64_Word e_version
Object file version.
Definition elf.h:99
Elf64_Off e_shoff
Section header table's file offset in bytes, or 0 if there are no section headers.
Definition elf.h:102
Elf64_Half e_phentsize
Size in bytes of one entry in the files program header table.
Definition elf.h:105
unsigned char e_ident[EI_NIDENT]
Identification bytes.
Definition elf.h:96
Elf64_Off e_phoff
Program header tables's file offset in bytes, or 0 if there are no program headers.
Definition elf.h:101
Elf64_Half e_shstrndx
Definition elf.h:123
Elf64_Half e_phnum
Number of entries in the program header table.
Definition elf.h:106
ELF File Helper structure.
Definition elf.h:781
uint64_t size
The size of the file in bytes.
Definition elf.h:783
Elf64_Shdr * dynsym
The dynamic symbol table section, or NULL if not found.
Definition elf.h:785
Elf64_Ehdr * header
The data in the file, pointed to the start of the ELF header.
Definition elf.h:782
Elf64_Shdr * symtab
The symbol table section, or NULL if not found.
Definition elf.h:784
ELF64 Program Header.
Definition elf.h:730
Elf64_Xword p_memsz
Size of segment in memory in bytes.
Definition elf.h:737
Elf64_Off p_offset
Segment file offset in bytes.
Definition elf.h:733
Elf64_Word p_type
Segment type.
Definition elf.h:731
Elf64_Xword p_filesz
Size of segment in file in bytes.
Definition elf.h:736
ELF64 Rel Entry without addend.
Definition elf.h:616
ELF64 Rela Entry with addend.
Definition elf.h:626
ELF64 Section Header.
Definition elf.h:468
Elf64_Word sh_name
Index of the section name in the string table.
Definition elf.h:469
Elf64_Word sh_link
Definition elf.h:475
Elf64_Word sh_type
Section type.
Definition elf.h:470
Elf64_Word sh_info
Depends on section type.
Definition elf.h:477
Elf64_Xword sh_entsize
Definition elf.h:479
Elf64_Xword sh_size
Section size in bytes.
Definition elf.h:474
Elf64_Off sh_offset
Section's file offset in bytes.
Definition elf.h:473
ELF64 Symbol Table Entry.
Definition elf.h:543
Elf64_Word st_name
Definition elf.h:544