Serenity Operating System
1/*
2 * Copyright (c) 2021, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibCore/DeprecatedFile.h>
8#include <LibTest/TestCase.h>
9#include <elf.h>
10#include <fcntl.h>
11#include <stdio.h>
12#include <string.h>
13#include <unistd.h>
14
15TEST_CASE(test_interp_header_tiny_p_filesz)
16{
17 char buffer[0x2000];
18
19 auto& header = *(Elf32_Ehdr*)buffer;
20 header.e_ident[EI_MAG0] = ELFMAG0;
21 header.e_ident[EI_MAG1] = ELFMAG1;
22 header.e_ident[EI_MAG2] = ELFMAG2;
23 header.e_ident[EI_MAG3] = ELFMAG3;
24 header.e_ident[EI_CLASS] = ELFCLASS32;
25 header.e_ident[EI_DATA] = ELFDATA2LSB;
26 header.e_ident[EI_VERSION] = EV_CURRENT;
27 header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
28 header.e_ident[EI_ABIVERSION] = 0;
29 header.e_type = ET_REL;
30 header.e_version = EV_CURRENT;
31 header.e_ehsize = sizeof(Elf32_Ehdr);
32 header.e_machine = EM_386;
33 header.e_shentsize = sizeof(Elf32_Shdr);
34 header.e_phnum = 1;
35 header.e_phoff = 52; // inaccurate
36 header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
37 header.e_shnum = 3; // inaccurate
38 header.e_shoff = 1024; // inaccurate
39 header.e_shstrndx = 2; // inaccurate
40 header.e_entry = 1024; // inaccurate
41
42 auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
43 ph[0].p_flags = PF_R | PF_X;
44 ph[0].p_vaddr = 0x00d4;
45 ph[0].p_align = PAGE_SIZE;
46 ph[0].p_type = PT_INTERP;
47 ph[0].p_memsz = 0xffff0000;
48 ph[0].p_offset = 0x100;
49
50 // p_filesz (1 or less) to trigger crash
51 ph[0].p_filesz = 1;
52
53 char path[] = "/tmp/test-elf.XXXXXX";
54 auto fd = mkstemp(path);
55 EXPECT_NE(fd, -1);
56 EXPECT_EQ(fchmod(fd, 0700), 0);
57
58 int nwritten = write(fd, buffer, sizeof(buffer));
59 EXPECT(nwritten);
60
61 auto elf_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
62 EXPECT(!elf_path_or_error.is_error());
63
64 auto elf_path = elf_path_or_error.release_value();
65 EXPECT(elf_path.characters());
66
67 int rc = execl(elf_path.characters(), "test-elf", nullptr);
68 EXPECT_EQ(rc, -1);
69 EXPECT_EQ(errno, 8);
70
71 EXPECT_EQ(unlink(path), 0);
72}
73
74TEST_CASE(test_interp_header_p_filesz_larger_than_p_memsz)
75{
76 char buffer[0x2000];
77
78 auto& header = *(Elf32_Ehdr*)buffer;
79 header.e_ident[EI_MAG0] = ELFMAG0;
80 header.e_ident[EI_MAG1] = ELFMAG1;
81 header.e_ident[EI_MAG2] = ELFMAG2;
82 header.e_ident[EI_MAG3] = ELFMAG3;
83 header.e_ident[EI_CLASS] = ELFCLASS32;
84 header.e_ident[EI_DATA] = ELFDATA2LSB;
85 header.e_ident[EI_VERSION] = EV_CURRENT;
86 header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
87 header.e_ident[EI_ABIVERSION] = 0;
88 header.e_type = ET_REL;
89 header.e_version = EV_CURRENT;
90 header.e_ehsize = sizeof(Elf32_Ehdr);
91 header.e_machine = EM_386;
92 header.e_shentsize = sizeof(Elf32_Shdr);
93 header.e_phnum = 1;
94 header.e_phoff = 52; // inaccurate
95 header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
96 header.e_shnum = 3; // inaccurate
97 header.e_shoff = 1024; // inaccurate
98 header.e_shstrndx = 2; // inaccurate
99 header.e_entry = 1024; // inaccurate
100
101 auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
102 ph[0].p_flags = PF_R | PF_X;
103 ph[0].p_vaddr = 0x00d4;
104 ph[0].p_align = PAGE_SIZE;
105 ph[0].p_type = PT_INTERP;
106 ph[0].p_memsz = 0xffff0000;
107 ph[0].p_offset = 0x1000;
108 ph[0].p_filesz = 0x1000;
109
110 char path[] = "/tmp/test-elf.XXXXXX";
111 auto fd = mkstemp(path);
112 EXPECT_NE(fd, -1);
113 EXPECT_EQ(fchmod(fd, 0700), 0);
114
115 int nwritten = write(fd, buffer, sizeof(buffer));
116 EXPECT(nwritten);
117
118 auto elf_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
119 EXPECT(!elf_path_or_error.is_error());
120
121 auto elf_path = elf_path_or_error.release_value();
122 EXPECT(elf_path.characters());
123
124 int rc = execl(elf_path.characters(), "test-elf", nullptr);
125 EXPECT_EQ(rc, -1);
126 EXPECT_EQ(errno, 8);
127
128 EXPECT_EQ(unlink(path), 0);
129}
130
131TEST_CASE(test_interp_header_p_filesz_plus_p_offset_overflow_p_memsz)
132{
133 char buffer[0x2000];
134
135 auto& header = *(Elf32_Ehdr*)buffer;
136 header.e_ident[EI_MAG0] = ELFMAG0;
137 header.e_ident[EI_MAG1] = ELFMAG1;
138 header.e_ident[EI_MAG2] = ELFMAG2;
139 header.e_ident[EI_MAG3] = ELFMAG3;
140 header.e_ident[EI_CLASS] = ELFCLASS32;
141 header.e_ident[EI_DATA] = ELFDATA2LSB;
142 header.e_ident[EI_VERSION] = EV_CURRENT;
143 header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
144 header.e_ident[EI_ABIVERSION] = 0;
145 header.e_type = ET_REL;
146 header.e_version = EV_CURRENT;
147 header.e_ehsize = sizeof(Elf32_Ehdr);
148 header.e_machine = EM_386;
149 header.e_shentsize = sizeof(Elf32_Shdr);
150 header.e_phoff = 52; // inaccurate
151 header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
152 header.e_shnum = 3; // inaccurate
153 header.e_shoff = 1024; // inaccurate
154 header.e_shstrndx = 2; // inaccurate
155 header.e_entry = 1024; // inaccurate
156
157 auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
158 ph[0].p_flags = PF_R | PF_X;
159 ph[0].p_vaddr = 0x00d4;
160 ph[0].p_align = PAGE_SIZE;
161 ph[0].p_type = PT_INTERP;
162
163 // p_memsz must be of sufficient size to hold maxint - 0x1000
164 ph[0].p_memsz = 0xfffff000;
165
166 // p_offset + p_filesz must not exceed buffer size in order to pass buffer size check in ELF::validate_program_headers().
167 // p_memsz + p_offset must be sufficiently large to overflow maxint.
168 ph[0].p_offset = 0x1234;
169 ph[0].p_filesz = -0x1000;
170
171 char path[] = "/tmp/test-elf.XXXXXX";
172 auto fd = mkstemp(path);
173 EXPECT_NE(fd, -1);
174 EXPECT_EQ(fchmod(fd, 0700), 0);
175
176 int nwritten = write(fd, buffer, sizeof(buffer));
177 EXPECT(nwritten);
178
179 auto elf_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
180 EXPECT(!elf_path_or_error.is_error());
181
182 auto elf_path = elf_path_or_error.release_value();
183 EXPECT(elf_path.characters());
184
185 int rc = execl(elf_path.characters(), "test-elf", nullptr);
186 EXPECT_EQ(rc, -1);
187 EXPECT_EQ(errno, 8);
188
189 EXPECT_EQ(unlink(path), 0);
190}
191
192TEST_CASE(test_load_header_p_memsz_zero)
193{
194 char buffer[0x2000];
195
196 auto& header = *(Elf32_Ehdr*)buffer;
197 header.e_ident[EI_MAG0] = ELFMAG0;
198 header.e_ident[EI_MAG1] = ELFMAG1;
199 header.e_ident[EI_MAG2] = ELFMAG2;
200 header.e_ident[EI_MAG3] = ELFMAG3;
201 header.e_ident[EI_CLASS] = ELFCLASS32;
202 header.e_ident[EI_DATA] = ELFDATA2LSB;
203 header.e_ident[EI_VERSION] = EV_CURRENT;
204 header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
205 header.e_ident[EI_ABIVERSION] = 0;
206 header.e_type = ET_REL;
207 header.e_version = EV_CURRENT;
208 header.e_ehsize = sizeof(Elf32_Ehdr);
209 header.e_machine = EM_386;
210 header.e_shentsize = sizeof(Elf32_Shdr);
211 header.e_phoff = 52; // inaccurate
212 header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
213 header.e_shnum = 3; // inaccurate
214 header.e_shoff = 1024; // inaccurate
215 header.e_shstrndx = 2; // inaccurate
216 header.e_entry = 1024; // inaccurate
217
218 auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
219 ph[0].p_flags = PF_R | PF_X;
220 ph[0].p_vaddr = 0x00d4;
221 ph[0].p_align = PAGE_SIZE;
222 ph[0].p_type = PT_LOAD;
223 ph[0].p_offset = 0;
224 ph[0].p_filesz = 0;
225
226 // p_memsz zero to trigger crash
227 ph[0].p_memsz = 0;
228
229 char path[] = "/tmp/test-elf.XXXXXX";
230 auto fd = mkstemp(path);
231 EXPECT_NE(fd, -1);
232 EXPECT_EQ(fchmod(fd, 0700), 0);
233
234 int nwritten = write(fd, buffer, sizeof(buffer));
235 EXPECT(nwritten);
236
237 auto elf_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
238 EXPECT(!elf_path_or_error.is_error());
239
240 auto elf_path = elf_path_or_error.release_value();
241 EXPECT(elf_path.characters());
242
243 int rc = execl(elf_path.characters(), "test-elf", nullptr);
244 EXPECT_EQ(rc, -1);
245 EXPECT_EQ(errno, 8);
246
247 EXPECT_EQ(unlink(path), 0);
248}
249
250TEST_CASE(test_load_header_p_memsz_not_equal_to_p_align)
251{
252 char buffer[0x2000];
253
254 auto& header = *(Elf32_Ehdr*)buffer;
255 header.e_ident[EI_MAG0] = ELFMAG0;
256 header.e_ident[EI_MAG1] = ELFMAG1;
257 header.e_ident[EI_MAG2] = ELFMAG2;
258 header.e_ident[EI_MAG3] = ELFMAG3;
259 header.e_ident[EI_CLASS] = ELFCLASS32;
260 header.e_ident[EI_DATA] = ELFDATA2LSB;
261 header.e_ident[EI_VERSION] = EV_CURRENT;
262 header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
263 header.e_ident[EI_ABIVERSION] = 0;
264 header.e_type = ET_REL;
265 header.e_version = EV_CURRENT;
266 header.e_ehsize = sizeof(Elf32_Ehdr);
267 header.e_machine = EM_386;
268 header.e_shentsize = sizeof(Elf32_Shdr);
269 header.e_phoff = 52; // inaccurate
270 header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
271 header.e_shnum = 3; // inaccurate
272 header.e_shoff = 1024; // inaccurate
273 header.e_shstrndx = 2; // inaccurate
274 header.e_entry = 1024; // inaccurate
275
276 auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
277 ph[0].p_flags = PF_R | PF_X;
278 ph[0].p_vaddr = 0x00d4;
279 ph[0].p_type = PT_LOAD;
280 ph[0].p_memsz = 0xffff0000;
281 ph[0].p_offset = 0x1000;
282 ph[0].p_filesz = 0x1000;
283
284 // p_align not equal to PAGE_SIZE to trigger crash
285 ph[0].p_align = PAGE_SIZE / 2;
286
287 char path[] = "/tmp/test-elf.XXXXXX";
288 auto fd = mkstemp(path);
289 EXPECT_NE(fd, -1);
290 EXPECT_EQ(fchmod(fd, 0700), 0);
291
292 int nwritten = write(fd, buffer, sizeof(buffer));
293 EXPECT(nwritten);
294
295 auto elf_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
296 EXPECT(!elf_path_or_error.is_error());
297
298 auto elf_path = elf_path_or_error.release_value();
299 EXPECT(elf_path.characters());
300
301 int rc = execl(elf_path.characters(), "test-elf", nullptr);
302 EXPECT_EQ(rc, -1);
303 EXPECT_EQ(errno, 8);
304
305 EXPECT_EQ(unlink(path), 0);
306}