Serenity Operating System
at master 306 lines 10 kB view raw
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}