test-elf.cpp 9.4 KB

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