Emulator_syscalls.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Emulator.h"
  7. #include "MmapRegion.h"
  8. #include "SimpleRegion.h"
  9. #include <AK/Debug.h>
  10. #include <AK/FileStream.h>
  11. #include <AK/Format.h>
  12. #include <fcntl.h>
  13. #include <sched.h>
  14. #include <serenity.h>
  15. #include <strings.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/mman.h>
  18. #include <sys/select.h>
  19. #include <sys/socket.h>
  20. #include <sys/stat.h>
  21. #include <sys/time.h>
  22. #include <sys/uio.h>
  23. #include <syscall.h>
  24. #include <termios.h>
  25. #if defined(__GNUC__) && !defined(__clang__)
  26. # pragma GCC optimize("O3")
  27. #endif
  28. namespace UserspaceEmulator {
  29. u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
  30. {
  31. if constexpr (SPAM_DEBUG)
  32. reportln("Syscall: {} ({:x})", Syscall::to_string((Syscall::Function)function), function);
  33. switch (function) {
  34. case SC_chdir:
  35. return virt$chdir(arg1, arg2);
  36. case SC_dup2:
  37. return virt$dup2(arg1, arg2);
  38. case SC_get_stack_bounds:
  39. return virt$get_stack_bounds(arg1, arg2);
  40. case SC_access:
  41. return virt$access(arg1, arg2, arg3);
  42. case SC_waitid:
  43. return virt$waitid(arg1);
  44. case SC_getcwd:
  45. return virt$getcwd(arg1, arg2);
  46. case SC_ttyname:
  47. return virt$ttyname(arg1, arg2, arg3);
  48. case SC_getpgrp:
  49. return virt$getpgrp();
  50. case SC_getpgid:
  51. return virt$getpgid(arg1);
  52. case SC_setpgid:
  53. return virt$setpgid(arg1, arg2);
  54. case SC_execve:
  55. return virt$execve(arg1);
  56. case SC_sigaction:
  57. return virt$sigaction(arg1, arg2, arg3);
  58. case SC_sigreturn:
  59. return virt$sigreturn();
  60. case SC_stat:
  61. return virt$stat(arg1);
  62. case SC_realpath:
  63. return virt$realpath(arg1);
  64. case SC_gethostname:
  65. return virt$gethostname(arg1, arg2);
  66. case SC_ioctl:
  67. return virt$ioctl(arg1, arg2, arg3);
  68. case SC_get_dir_entries:
  69. return virt$get_dir_entries(arg1, arg2, arg3);
  70. case SC_profiling_enable:
  71. return virt$profiling_enable(arg1);
  72. case SC_profiling_disable:
  73. return virt$profiling_disable(arg1);
  74. case SC_disown:
  75. return virt$disown(arg1);
  76. case SC_purge:
  77. return virt$purge(arg1);
  78. case SC_mmap:
  79. return virt$mmap(arg1);
  80. case SC_mount:
  81. return virt$mount(arg1);
  82. case SC_munmap:
  83. return virt$munmap(arg1, arg2);
  84. case SC_mremap:
  85. return virt$mremap(arg1);
  86. case SC_gettid:
  87. return virt$gettid();
  88. case SC_getpid:
  89. return virt$getpid();
  90. case SC_getsid:
  91. return virt$getsid(arg1);
  92. case SC_pledge:
  93. return virt$pledge(arg1);
  94. case SC_unveil:
  95. return virt$unveil(arg1);
  96. case SC_getuid:
  97. return virt$getuid();
  98. case SC_geteuid:
  99. return virt$geteuid();
  100. case SC_getgid:
  101. return virt$getgid();
  102. case SC_getegid:
  103. return virt$getegid();
  104. case SC_setuid:
  105. return virt$setuid(arg1);
  106. case SC_setgid:
  107. return virt$setgid(arg2);
  108. case SC_close:
  109. return virt$close(arg1);
  110. case SC_fstat:
  111. return virt$fstat(arg1, arg2);
  112. case SC_mkdir:
  113. return virt$mkdir(arg1, arg2, arg3);
  114. case SC_rmdir:
  115. return virt$rmdir(arg1, arg2);
  116. case SC_unlink:
  117. return virt$unlink(arg1, arg2);
  118. case SC_symlink:
  119. return virt$symlink(arg1);
  120. case SC_rename:
  121. return virt$rename(arg1);
  122. case SC_set_coredump_metadata:
  123. return virt$set_coredump_metadata(arg1);
  124. case SC_write:
  125. return virt$write(arg1, arg2, arg3);
  126. case SC_read:
  127. return virt$read(arg1, arg2, arg3);
  128. case SC_mprotect:
  129. return virt$mprotect(arg1, arg2, arg3);
  130. case SC_madvise:
  131. return virt$madvise(arg1, arg2, arg3);
  132. case SC_anon_create:
  133. return virt$anon_create(arg1, arg2);
  134. case SC_sendfd:
  135. return virt$sendfd(arg1, arg2);
  136. case SC_recvfd:
  137. return virt$recvfd(arg1, arg2);
  138. case SC_open:
  139. return virt$open(arg1);
  140. case SC_pipe:
  141. return virt$pipe(arg1, arg2);
  142. case SC_fcntl:
  143. return virt$fcntl(arg1, arg2, arg3);
  144. case SC_getgroups:
  145. return virt$getgroups(arg1, arg2);
  146. case SC_setgroups:
  147. return virt$setgroups(arg1, arg2);
  148. case SC_lseek:
  149. return virt$lseek(arg1, arg2, arg3);
  150. case SC_socket:
  151. return virt$socket(arg1, arg2, arg3);
  152. case SC_getsockopt:
  153. return virt$getsockopt(arg1);
  154. case SC_get_process_name:
  155. return virt$get_process_name(arg1, arg2);
  156. case SC_set_process_name:
  157. return virt$set_process_name(arg1, arg2);
  158. case SC_dbgputstr:
  159. return virt$dbgputstr(arg1, arg2);
  160. case SC_dbgputch:
  161. return virt$dbgputch(arg1);
  162. case SC_chmod:
  163. return virt$chmod(arg1, arg2, arg3);
  164. case SC_fchmod:
  165. return virt$fchmod(arg1, arg2);
  166. case SC_fchown:
  167. return virt$fchown(arg1, arg2, arg3);
  168. case SC_accept4:
  169. return virt$accept4(arg1);
  170. case SC_setsockopt:
  171. return virt$setsockopt(arg1);
  172. case SC_getsockname:
  173. return virt$getsockname(arg1);
  174. case SC_getpeername:
  175. return virt$getpeername(arg1);
  176. case SC_bind:
  177. return virt$bind(arg1, arg2, arg3);
  178. case SC_connect:
  179. return virt$connect(arg1, arg2, arg3);
  180. case SC_shutdown:
  181. return virt$shutdown(arg1, arg2);
  182. case SC_listen:
  183. return virt$listen(arg1, arg2);
  184. case SC_select:
  185. return virt$select(arg1);
  186. case SC_recvmsg:
  187. return virt$recvmsg(arg1, arg2, arg3);
  188. case SC_sendmsg:
  189. return virt$sendmsg(arg1, arg2, arg3);
  190. case SC_kill:
  191. return virt$kill(arg1, arg2);
  192. case SC_killpg:
  193. return virt$killpg(arg1, arg2);
  194. case SC_set_mmap_name:
  195. return virt$set_mmap_name(arg1);
  196. case SC_sync:
  197. virt$sync();
  198. return 0;
  199. case SC_exit:
  200. virt$exit((int)arg1);
  201. return 0;
  202. case SC_clock_gettime:
  203. return virt$clock_gettime(arg1, arg2);
  204. case SC_clock_settime:
  205. return virt$clock_settime(arg1, arg2);
  206. case SC_getrandom:
  207. return virt$getrandom(arg1, arg2, arg3);
  208. case SC_fork:
  209. return virt$fork();
  210. case SC_emuctl:
  211. return virt$emuctl(arg1, arg2, arg3);
  212. case SC_sched_getparam:
  213. return virt$sched_getparam(arg1, arg2);
  214. case SC_sched_setparam:
  215. return virt$sched_setparam(arg1, arg2);
  216. case SC_set_thread_name:
  217. return virt$set_thread_name(arg1, arg2, arg3);
  218. case SC_setsid:
  219. return virt$setsid();
  220. case SC_create_inode_watcher:
  221. return virt$create_inode_watcher(arg1);
  222. case SC_inode_watcher_add_watch:
  223. return virt$inode_watcher_add_watch(arg1);
  224. case SC_inode_watcher_remove_watch:
  225. return virt$inode_watcher_remove_watch(arg1, arg2);
  226. case SC_clock_nanosleep:
  227. return virt$clock_nanosleep(arg1);
  228. case SC_readlink:
  229. return virt$readlink(arg1);
  230. case SC_ptsname:
  231. return virt$ptsname(arg1, arg2, arg3);
  232. case SC_allocate_tls:
  233. return virt$allocate_tls(arg1, arg2);
  234. case SC_beep:
  235. return virt$beep();
  236. case SC_ftruncate:
  237. return virt$ftruncate(arg1, arg2);
  238. case SC_umask:
  239. return virt$umask(arg1);
  240. case SC_chown:
  241. return virt$chown(arg1);
  242. case SC_msyscall:
  243. return virt$msyscall(arg1);
  244. case SC_futex:
  245. return virt$futex(arg1);
  246. case SC_map_time_page:
  247. return -ENOSYS;
  248. default:
  249. reportln("\n=={}== \033[31;1mUnimplemented syscall: {}\033[0m, {:p}", getpid(), Syscall::to_string((Syscall::Function)function), function);
  250. dump_backtrace();
  251. TODO();
  252. }
  253. }
  254. int Emulator::virt$anon_create(size_t size, int options)
  255. {
  256. return syscall(SC_anon_create, size, options);
  257. }
  258. int Emulator::virt$sendfd(int socket, int fd)
  259. {
  260. return syscall(SC_sendfd, socket, fd);
  261. }
  262. int Emulator::virt$recvfd(int socket, int options)
  263. {
  264. return syscall(SC_recvfd, socket, options);
  265. }
  266. int Emulator::virt$profiling_enable(pid_t pid)
  267. {
  268. return syscall(SC_profiling_enable, pid);
  269. }
  270. int Emulator::virt$profiling_disable(pid_t pid)
  271. {
  272. return syscall(SC_profiling_disable, pid);
  273. }
  274. int Emulator::virt$disown(pid_t pid)
  275. {
  276. return syscall(SC_disown, pid);
  277. }
  278. int Emulator::virt$purge(int mode)
  279. {
  280. return syscall(SC_purge, mode);
  281. }
  282. int Emulator::virt$fstat(int fd, FlatPtr statbuf)
  283. {
  284. struct stat local_statbuf;
  285. int rc = syscall(SC_fstat, fd, &local_statbuf);
  286. if (rc < 0)
  287. return rc;
  288. mmu().copy_to_vm(statbuf, &local_statbuf, sizeof(local_statbuf));
  289. return rc;
  290. }
  291. int Emulator::virt$close(int fd)
  292. {
  293. return syscall(SC_close, fd);
  294. }
  295. int Emulator::virt$mkdir(FlatPtr path, size_t path_length, mode_t mode)
  296. {
  297. auto buffer = mmu().copy_buffer_from_vm(path, path_length);
  298. return syscall(SC_mkdir, buffer.data(), buffer.size(), mode);
  299. }
  300. int Emulator::virt$rmdir(FlatPtr path, size_t path_length)
  301. {
  302. auto buffer = mmu().copy_buffer_from_vm(path, path_length);
  303. return syscall(SC_rmdir, buffer.data(), buffer.size());
  304. }
  305. int Emulator::virt$unlink(FlatPtr path, size_t path_length)
  306. {
  307. auto buffer = mmu().copy_buffer_from_vm(path, path_length);
  308. return syscall(SC_unlink, buffer.data(), buffer.size());
  309. }
  310. int Emulator::virt$symlink(FlatPtr params_addr)
  311. {
  312. Syscall::SC_symlink_params params;
  313. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  314. auto target = mmu().copy_buffer_from_vm((FlatPtr)params.target.characters, params.target.length);
  315. params.target.characters = (const char*)target.data();
  316. params.target.length = target.size();
  317. auto link = mmu().copy_buffer_from_vm((FlatPtr)params.linkpath.characters, params.linkpath.length);
  318. params.linkpath.characters = (const char*)link.data();
  319. params.linkpath.length = link.size();
  320. return syscall(SC_symlink, &params);
  321. }
  322. int Emulator::virt$rename(FlatPtr params_addr)
  323. {
  324. Syscall::SC_rename_params params;
  325. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  326. auto new_path = mmu().copy_buffer_from_vm((FlatPtr)params.new_path.characters, params.new_path.length);
  327. params.new_path.characters = (const char*)new_path.data();
  328. params.new_path.length = new_path.size();
  329. auto old_path = mmu().copy_buffer_from_vm((FlatPtr)params.old_path.characters, params.old_path.length);
  330. params.old_path.characters = (const char*)old_path.data();
  331. params.old_path.length = old_path.size();
  332. return syscall(SC_rename, &params);
  333. }
  334. int Emulator::virt$set_coredump_metadata(FlatPtr params_addr)
  335. {
  336. Syscall::SC_set_coredump_metadata_params params;
  337. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  338. auto key = mmu().copy_buffer_from_vm((FlatPtr)params.key.characters, params.key.length);
  339. params.key.characters = (const char*)key.data();
  340. params.key.length = key.size();
  341. auto value = mmu().copy_buffer_from_vm((FlatPtr)params.value.characters, params.value.length);
  342. params.value.characters = (const char*)value.data();
  343. params.value.length = value.size();
  344. return syscall(SC_set_coredump_metadata, &params);
  345. }
  346. int Emulator::virt$dbgputstr(FlatPtr characters, int length)
  347. {
  348. auto buffer = mmu().copy_buffer_from_vm(characters, length);
  349. dbgputstr((const char*)buffer.data(), buffer.size());
  350. return 0;
  351. }
  352. int Emulator::virt$chmod(FlatPtr path_addr, size_t path_length, mode_t mode)
  353. {
  354. auto path = mmu().copy_buffer_from_vm(path_addr, path_length);
  355. return syscall(SC_chmod, path.data(), path.size(), mode);
  356. }
  357. int Emulator::virt$chown(FlatPtr params_addr)
  358. {
  359. Syscall::SC_chown_params params;
  360. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  361. auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
  362. params.path.characters = (const char*)path.data();
  363. params.path.length = path.size();
  364. return syscall(SC_chown, &params);
  365. }
  366. int Emulator::virt$fchmod(int fd, mode_t mode)
  367. {
  368. return syscall(SC_fchmod, fd, mode);
  369. }
  370. int Emulator::virt$fchown(int fd, uid_t uid, gid_t gid)
  371. {
  372. return syscall(SC_fchown, fd, uid, gid);
  373. }
  374. int Emulator::virt$setsockopt(FlatPtr params_addr)
  375. {
  376. Syscall::SC_setsockopt_params params;
  377. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  378. if (params.option == SO_RCVTIMEO || params.option == SO_TIMESTAMP) {
  379. auto host_value_buffer_result = ByteBuffer::create_zeroed(params.value_size);
  380. if (!host_value_buffer_result.has_value())
  381. return -ENOMEM;
  382. auto& host_value_buffer = host_value_buffer_result.value();
  383. mmu().copy_from_vm(host_value_buffer.data(), (FlatPtr)params.value, params.value_size);
  384. int rc = setsockopt(params.sockfd, params.level, params.option, host_value_buffer.data(), host_value_buffer.size());
  385. if (rc < 0)
  386. return -errno;
  387. return rc;
  388. }
  389. if (params.option == SO_BINDTODEVICE) {
  390. auto ifname = mmu().copy_buffer_from_vm((FlatPtr)params.value, params.value_size);
  391. params.value = ifname.data();
  392. params.value_size = ifname.size();
  393. return syscall(SC_setsockopt, &params);
  394. }
  395. TODO();
  396. }
  397. int Emulator::virt$get_stack_bounds(FlatPtr base, FlatPtr size)
  398. {
  399. auto* region = mmu().find_region({ m_cpu.ss(), m_cpu.esp().value() });
  400. FlatPtr b = region->base();
  401. size_t s = region->size();
  402. mmu().copy_to_vm(base, &b, sizeof(b));
  403. mmu().copy_to_vm(size, &s, sizeof(s));
  404. return 0;
  405. }
  406. int Emulator::virt$ftruncate(int fd, FlatPtr length_addr)
  407. {
  408. off_t length;
  409. mmu().copy_from_vm(&length, length_addr, sizeof(off_t));
  410. return syscall(SC_ftruncate, fd, &length);
  411. }
  412. mode_t Emulator::virt$umask(mode_t mask)
  413. {
  414. return syscall(SC_umask, mask);
  415. }
  416. int Emulator::virt$accept4(FlatPtr params_addr)
  417. {
  418. Syscall::SC_accept4_params params;
  419. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  420. sockaddr_storage addr = {};
  421. socklen_t addrlen;
  422. mmu().copy_from_vm(&addrlen, (FlatPtr)params.addrlen, sizeof(socklen_t));
  423. VERIFY(addrlen <= sizeof(addr));
  424. int rc = accept4(params.sockfd, (sockaddr*)&addr, &addrlen, params.flags);
  425. if (rc == 0) {
  426. mmu().copy_to_vm((FlatPtr)params.addr, &addr, addrlen);
  427. mmu().copy_to_vm((FlatPtr)params.addrlen, &addrlen, sizeof(socklen_t));
  428. }
  429. return rc < 0 ? -errno : rc;
  430. }
  431. int Emulator::virt$bind(int sockfd, FlatPtr address, socklen_t address_length)
  432. {
  433. auto buffer = mmu().copy_buffer_from_vm(address, address_length);
  434. return syscall(SC_bind, sockfd, buffer.data(), buffer.size());
  435. }
  436. int Emulator::virt$connect(int sockfd, FlatPtr address, socklen_t address_size)
  437. {
  438. auto buffer = mmu().copy_buffer_from_vm(address, address_size);
  439. return syscall(SC_connect, sockfd, buffer.data(), buffer.size());
  440. }
  441. int Emulator::virt$shutdown(int sockfd, int how)
  442. {
  443. return syscall(SC_shutdown, sockfd, how);
  444. }
  445. int Emulator::virt$dbgputch(char ch)
  446. {
  447. dbgputch(ch);
  448. return 0;
  449. }
  450. int Emulator::virt$listen(int fd, int backlog)
  451. {
  452. return syscall(SC_listen, fd, backlog);
  453. }
  454. int Emulator::virt$kill(pid_t pid, int signal)
  455. {
  456. return syscall(SC_kill, pid, signal);
  457. }
  458. int Emulator::virt$killpg(int pgrp, int sig)
  459. {
  460. return syscall(SC_killpg, pgrp, sig);
  461. }
  462. int Emulator::virt$clock_gettime(int clockid, FlatPtr timespec)
  463. {
  464. struct timespec host_timespec;
  465. int rc = syscall(SC_clock_gettime, clockid, &host_timespec);
  466. if (rc < 0)
  467. return rc;
  468. mmu().copy_to_vm(timespec, &host_timespec, sizeof(host_timespec));
  469. return rc;
  470. }
  471. int Emulator::virt$clock_settime(uint32_t clock_id, FlatPtr user_ts)
  472. {
  473. struct timespec user_timespec;
  474. mmu().copy_from_vm(&user_timespec, user_ts, sizeof(user_timespec));
  475. int rc = syscall(SC_clock_settime, clock_id, &user_timespec);
  476. return rc;
  477. }
  478. int Emulator::virt$set_mmap_name(FlatPtr params_addr)
  479. {
  480. Syscall::SC_set_mmap_name_params params {};
  481. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  482. auto name = mmu().copy_buffer_from_vm((FlatPtr)params.name.characters, params.name.length);
  483. auto* region = mmu().find_region({ 0x23, (FlatPtr)params.addr });
  484. if (!region || !is<MmapRegion>(*region))
  485. return -EINVAL;
  486. static_cast<MmapRegion&>(*region).set_name(String::copy(name));
  487. return 0;
  488. }
  489. int Emulator::virt$get_process_name(FlatPtr buffer, int size)
  490. {
  491. if (size < 0)
  492. return -EINVAL;
  493. auto host_buffer_result = ByteBuffer::create_zeroed((size_t)size);
  494. if (!host_buffer_result.has_value())
  495. return -ENOMEM;
  496. auto& host_buffer = host_buffer_result.value();
  497. int rc = syscall(SC_get_process_name, host_buffer.data(), host_buffer.size());
  498. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  499. return rc;
  500. }
  501. int Emulator::virt$set_process_name(FlatPtr user_buffer, int size)
  502. {
  503. if (size < 0)
  504. return -EINVAL;
  505. auto host_buffer = mmu().copy_buffer_from_vm(user_buffer, size);
  506. auto name = String::formatted("(UE) {}", StringView { host_buffer.data(), host_buffer.size() });
  507. return syscall(SC_set_process_name, name.characters(), name.length());
  508. }
  509. int Emulator::virt$lseek(int fd, FlatPtr offset_addr, int whence)
  510. {
  511. off_t offset;
  512. mmu().copy_from_vm(&offset, offset_addr, sizeof(off_t));
  513. auto rc = syscall(SC_lseek, fd, &offset, whence);
  514. mmu().copy_to_vm(offset_addr, &offset, sizeof(off_t));
  515. return rc;
  516. }
  517. int Emulator::virt$socket(int domain, int type, int protocol)
  518. {
  519. return syscall(SC_socket, domain, type, protocol);
  520. }
  521. int Emulator::virt$recvmsg(int sockfd, FlatPtr msg_addr, int flags)
  522. {
  523. msghdr mmu_msg;
  524. mmu().copy_from_vm(&mmu_msg, msg_addr, sizeof(mmu_msg));
  525. Vector<iovec, 1> mmu_iovs;
  526. mmu_iovs.resize(mmu_msg.msg_iovlen);
  527. mmu().copy_from_vm(mmu_iovs.data(), (FlatPtr)mmu_msg.msg_iov, mmu_msg.msg_iovlen * sizeof(iovec));
  528. Vector<ByteBuffer, 1> buffers;
  529. Vector<iovec, 1> iovs;
  530. for (const auto& iov : mmu_iovs) {
  531. auto buffer_result = ByteBuffer::create_uninitialized(iov.iov_len);
  532. if (!buffer_result.has_value())
  533. return -ENOMEM;
  534. buffers.append(buffer_result.release_value());
  535. iovs.append({ buffers.last().data(), buffers.last().size() });
  536. }
  537. ByteBuffer control_buffer;
  538. if (mmu_msg.msg_control) {
  539. auto buffer_result = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
  540. if (!buffer_result.has_value())
  541. return -ENOMEM;
  542. control_buffer = buffer_result.release_value();
  543. }
  544. sockaddr_storage addr;
  545. msghdr msg = { &addr, sizeof(addr), iovs.data(), (int)iovs.size(), mmu_msg.msg_control ? control_buffer.data() : nullptr, mmu_msg.msg_controllen, mmu_msg.msg_flags };
  546. int rc = recvmsg(sockfd, &msg, flags);
  547. if (rc < 0)
  548. return -errno;
  549. for (size_t i = 0; i < buffers.size(); ++i)
  550. mmu().copy_to_vm((FlatPtr)mmu_iovs[i].iov_base, buffers[i].data(), mmu_iovs[i].iov_len);
  551. if (mmu_msg.msg_name)
  552. mmu().copy_to_vm((FlatPtr)mmu_msg.msg_name, &addr, min(sizeof(addr), (size_t)mmu_msg.msg_namelen));
  553. if (mmu_msg.msg_control)
  554. mmu().copy_to_vm((FlatPtr)mmu_msg.msg_control, control_buffer.data(), min(mmu_msg.msg_controllen, msg.msg_controllen));
  555. mmu_msg.msg_namelen = msg.msg_namelen;
  556. mmu_msg.msg_controllen = msg.msg_controllen;
  557. mmu_msg.msg_flags = msg.msg_flags;
  558. mmu().copy_to_vm(msg_addr, &mmu_msg, sizeof(mmu_msg));
  559. return rc;
  560. }
  561. int Emulator::virt$sendmsg(int sockfd, FlatPtr msg_addr, int flags)
  562. {
  563. msghdr mmu_msg;
  564. mmu().copy_from_vm(&mmu_msg, msg_addr, sizeof(mmu_msg));
  565. Vector<iovec, 1> iovs;
  566. iovs.resize(mmu_msg.msg_iovlen);
  567. mmu().copy_from_vm(iovs.data(), (FlatPtr)mmu_msg.msg_iov, mmu_msg.msg_iovlen * sizeof(iovec));
  568. Vector<ByteBuffer, 1> buffers;
  569. for (auto& iov : iovs) {
  570. buffers.append(mmu().copy_buffer_from_vm((FlatPtr)iov.iov_base, iov.iov_len));
  571. iov = { buffers.last().data(), buffers.last().size() };
  572. }
  573. ByteBuffer control_buffer;
  574. if (mmu_msg.msg_control) {
  575. auto buffer_result = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
  576. if (!buffer_result.has_value())
  577. return -ENOMEM;
  578. control_buffer = buffer_result.release_value();
  579. }
  580. sockaddr_storage address;
  581. socklen_t address_length = 0;
  582. if (mmu_msg.msg_name) {
  583. address_length = min(sizeof(address), (size_t)mmu_msg.msg_namelen);
  584. mmu().copy_from_vm(&address, (FlatPtr)mmu_msg.msg_name, address_length);
  585. }
  586. msghdr msg = { mmu_msg.msg_name ? &address : nullptr, address_length, iovs.data(), (int)iovs.size(), mmu_msg.msg_control ? control_buffer.data() : nullptr, mmu_msg.msg_controllen, mmu_msg.msg_flags };
  587. return sendmsg(sockfd, &msg, flags);
  588. }
  589. int Emulator::virt$select(FlatPtr params_addr)
  590. {
  591. Syscall::SC_select_params params;
  592. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  593. fd_set readfds {};
  594. fd_set writefds {};
  595. fd_set exceptfds {};
  596. struct timespec timeout;
  597. u32 sigmask;
  598. if (params.readfds)
  599. mmu().copy_from_vm(&readfds, (FlatPtr)params.readfds, sizeof(readfds));
  600. if (params.writefds)
  601. mmu().copy_from_vm(&writefds, (FlatPtr)params.writefds, sizeof(writefds));
  602. if (params.exceptfds)
  603. mmu().copy_from_vm(&exceptfds, (FlatPtr)params.exceptfds, sizeof(exceptfds));
  604. if (params.timeout)
  605. mmu().copy_from_vm(&timeout, (FlatPtr)params.timeout, sizeof(timeout));
  606. if (params.sigmask)
  607. mmu().copy_from_vm(&sigmask, (FlatPtr)params.sigmask, sizeof(sigmask));
  608. int rc = pselect(params.nfds, &readfds, &writefds, &exceptfds, params.timeout ? &timeout : nullptr, params.sigmask ? &sigmask : nullptr);
  609. if (rc < 0)
  610. return -errno;
  611. if (params.readfds)
  612. mmu().copy_to_vm((FlatPtr)params.readfds, &readfds, sizeof(readfds));
  613. if (params.writefds)
  614. mmu().copy_to_vm((FlatPtr)params.writefds, &writefds, sizeof(writefds));
  615. if (params.exceptfds)
  616. mmu().copy_to_vm((FlatPtr)params.exceptfds, &exceptfds, sizeof(exceptfds));
  617. if (params.timeout)
  618. mmu().copy_to_vm((FlatPtr)params.timeout, &timeout, sizeof(timeout));
  619. return rc;
  620. }
  621. int Emulator::virt$getsockopt(FlatPtr params_addr)
  622. {
  623. Syscall::SC_getsockopt_params params;
  624. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  625. if (params.option == SO_PEERCRED) {
  626. struct ucred creds = {};
  627. socklen_t creds_size = sizeof(creds);
  628. int rc = getsockopt(params.sockfd, params.level, SO_PEERCRED, &creds, &creds_size);
  629. if (rc < 0)
  630. return -errno;
  631. // FIXME: Check params.value_size
  632. mmu().copy_to_vm((FlatPtr)params.value, &creds, sizeof(creds));
  633. return rc;
  634. }
  635. TODO();
  636. }
  637. int Emulator::virt$getsockname(FlatPtr params_addr)
  638. {
  639. Syscall::SC_getsockname_params params;
  640. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  641. sockaddr_storage addr = {};
  642. socklen_t addrlen;
  643. mmu().copy_from_vm(&addrlen, (FlatPtr)params.addrlen, sizeof(socklen_t));
  644. VERIFY(addrlen <= sizeof(addr));
  645. auto rc = getsockname(params.sockfd, (sockaddr*)&addr, &addrlen);
  646. if (rc == 0) {
  647. mmu().copy_to_vm((FlatPtr)params.addr, &addr, sizeof(addr));
  648. mmu().copy_to_vm((FlatPtr)params.addrlen, &addrlen, sizeof(addrlen));
  649. }
  650. return rc < 0 ? -errno : rc;
  651. }
  652. int Emulator::virt$getpeername(FlatPtr params_addr)
  653. {
  654. Syscall::SC_getpeername_params params;
  655. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  656. sockaddr_storage addr = {};
  657. socklen_t addrlen;
  658. mmu().copy_from_vm(&addrlen, (FlatPtr)params.addrlen, sizeof(socklen_t));
  659. VERIFY(addrlen <= sizeof(addr));
  660. auto rc = getpeername(params.sockfd, (sockaddr*)&addr, &addrlen);
  661. if (rc == 0) {
  662. mmu().copy_to_vm((FlatPtr)params.addr, &addr, sizeof(addr));
  663. mmu().copy_to_vm((FlatPtr)params.addrlen, &addrlen, sizeof(addrlen));
  664. }
  665. return rc < 0 ? -errno : rc;
  666. }
  667. int Emulator::virt$getgroups(ssize_t count, FlatPtr groups)
  668. {
  669. if (!count)
  670. return syscall(SC_getgroups, 0, nullptr);
  671. auto buffer_result = ByteBuffer::create_uninitialized(count * sizeof(gid_t));
  672. if (!buffer_result.has_value())
  673. return -ENOMEM;
  674. auto& buffer = buffer_result.value();
  675. int rc = syscall(SC_getgroups, count, buffer.data());
  676. if (rc < 0)
  677. return rc;
  678. mmu().copy_to_vm(groups, buffer.data(), buffer.size());
  679. return 0;
  680. }
  681. int Emulator::virt$setgroups(ssize_t count, FlatPtr groups)
  682. {
  683. if (!count)
  684. return syscall(SC_setgroups, 0, nullptr);
  685. auto buffer = mmu().copy_buffer_from_vm(groups, count * sizeof(gid_t));
  686. return syscall(SC_setgroups, count, buffer.data());
  687. }
  688. u32 Emulator::virt$fcntl(int fd, int cmd, u32 arg)
  689. {
  690. switch (cmd) {
  691. case F_DUPFD:
  692. case F_GETFD:
  693. case F_SETFD:
  694. case F_GETFL:
  695. case F_SETFL:
  696. case F_ISTTY:
  697. break;
  698. default:
  699. dbgln("Invalid fcntl cmd: {}", cmd);
  700. }
  701. return syscall(SC_fcntl, fd, cmd, arg);
  702. }
  703. u32 Emulator::virt$open(u32 params_addr)
  704. {
  705. Syscall::SC_open_params params;
  706. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  707. auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
  708. Syscall::SC_open_params host_params {};
  709. host_params.dirfd = params.dirfd;
  710. host_params.mode = params.mode;
  711. host_params.options = params.options;
  712. host_params.path.characters = (const char*)path.data();
  713. host_params.path.length = path.size();
  714. return syscall(SC_open, &host_params);
  715. }
  716. int Emulator::virt$pipe(FlatPtr vm_pipefd, int flags)
  717. {
  718. int pipefd[2];
  719. int rc = syscall(SC_pipe, pipefd, flags);
  720. if (rc < 0)
  721. return rc;
  722. mmu().copy_to_vm(vm_pipefd, pipefd, sizeof(pipefd));
  723. return rc;
  724. }
  725. static void round_to_page_size(FlatPtr& address, size_t& size)
  726. {
  727. auto new_end = round_up_to_power_of_two(address + size, PAGE_SIZE);
  728. address &= ~(PAGE_SIZE - 1);
  729. size = new_end - address;
  730. }
  731. u32 Emulator::virt$munmap(FlatPtr address, size_t size)
  732. {
  733. if (is_profiling())
  734. emit_profile_event(profile_stream(), "munmap", String::formatted("\"ptr\": {}, \"size\": {}", address, size));
  735. round_to_page_size(address, size);
  736. Vector<Region*, 4> marked_for_deletion;
  737. bool has_non_mmap_region = false;
  738. mmu().for_regions_in({ 0x23, address }, size, [&](Region* region) {
  739. if (region) {
  740. if (!is<MmapRegion>(*region)) {
  741. has_non_mmap_region = true;
  742. return IterationDecision::Break;
  743. }
  744. marked_for_deletion.append(region);
  745. }
  746. return IterationDecision::Continue;
  747. });
  748. if (has_non_mmap_region)
  749. return -EINVAL;
  750. for (Region* region : marked_for_deletion) {
  751. m_range_allocator.deallocate(region->range());
  752. mmu().remove_region(*region);
  753. }
  754. return 0;
  755. }
  756. u32 Emulator::virt$mmap(u32 params_addr)
  757. {
  758. Syscall::SC_mmap_params params;
  759. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  760. u32 requested_size = round_up_to_power_of_two(params.size, PAGE_SIZE);
  761. FlatPtr final_address;
  762. Optional<Range> result;
  763. if (params.flags & MAP_RANDOMIZED) {
  764. result = m_range_allocator.allocate_randomized(requested_size, params.alignment);
  765. } else if (params.flags & MAP_FIXED) {
  766. if (params.addr)
  767. result = m_range_allocator.allocate_specific(VirtualAddress { params.addr }, requested_size);
  768. else {
  769. // mmap(nullptr, …, MAP_FIXED) is technically okay, but tends to be a bug.
  770. // Therefore, refuse to be helpful.
  771. reportln("\n=={}== \033[31;1mTried to mmap at nullptr with MAP_FIXED.\033[0m, {:#x} bytes.", getpid(), params.size);
  772. dump_backtrace();
  773. }
  774. } else {
  775. result = m_range_allocator.allocate_anywhere(requested_size, params.alignment);
  776. }
  777. if (!result.has_value())
  778. return -ENOMEM;
  779. final_address = result.value().base().get();
  780. auto final_size = result.value().size();
  781. String name_str;
  782. if (params.name.characters) {
  783. auto buffer_result = ByteBuffer::create_uninitialized(params.name.length);
  784. if (!buffer_result.has_value())
  785. return -ENOMEM;
  786. auto& name = buffer_result.value();
  787. mmu().copy_from_vm(name.data(), (FlatPtr)params.name.characters, params.name.length);
  788. name_str = { name.data(), name.size() };
  789. }
  790. if (is_profiling())
  791. emit_profile_event(profile_stream(), "mmap", String::formatted(R"("ptr": {}, "size": {}, "name": "{}")", final_address, final_size, name_str));
  792. if (params.flags & MAP_ANONYMOUS) {
  793. mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot, move(name_str)));
  794. } else {
  795. auto region = MmapRegion::create_file_backed(final_address, final_size, params.prot, params.flags, params.fd, params.offset, move(name_str));
  796. if (region->name() == "libsystem.so: .text" && !m_libsystem_start) {
  797. m_libsystem_start = final_address;
  798. m_libsystem_end = final_address + final_size;
  799. }
  800. mmu().add_region(move(region));
  801. }
  802. return final_address;
  803. }
  804. FlatPtr Emulator::virt$mremap(FlatPtr params_addr)
  805. {
  806. Syscall::SC_mremap_params params;
  807. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  808. // FIXME: Support regions that have been split in the past (e.g. due to mprotect or munmap).
  809. if (auto* region = mmu().find_region({ m_cpu.ds(), params.old_address })) {
  810. if (!is<MmapRegion>(*region))
  811. return -EINVAL;
  812. VERIFY(region->size() == params.old_size);
  813. auto& mmap_region = *(MmapRegion*)region;
  814. auto* ptr = mremap(mmap_region.data(), mmap_region.size(), mmap_region.size(), params.flags);
  815. if (ptr == MAP_FAILED)
  816. return -errno;
  817. return (FlatPtr)ptr;
  818. }
  819. return -EINVAL;
  820. }
  821. u32 Emulator::virt$mount(u32 params_addr)
  822. {
  823. Syscall::SC_mount_params params;
  824. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  825. auto target = mmu().copy_buffer_from_vm((FlatPtr)params.target.characters, params.target.length);
  826. auto fs_path = mmu().copy_buffer_from_vm((FlatPtr)params.fs_type.characters, params.fs_type.length);
  827. params.fs_type.characters = (char*)fs_path.data();
  828. params.fs_type.length = fs_path.size();
  829. params.target.characters = (char*)target.data();
  830. params.target.length = target.size();
  831. return syscall(SC_mount, &params);
  832. }
  833. u32 Emulator::virt$gettid()
  834. {
  835. return gettid();
  836. }
  837. u32 Emulator::virt$getpid()
  838. {
  839. return getpid();
  840. }
  841. u32 Emulator::virt$pledge(u32)
  842. {
  843. return 0;
  844. }
  845. u32 Emulator::virt$unveil(u32)
  846. {
  847. return 0;
  848. }
  849. u32 Emulator::virt$mprotect(FlatPtr base, size_t size, int prot)
  850. {
  851. round_to_page_size(base, size);
  852. bool has_non_mmapped_region = false;
  853. mmu().for_regions_in({ 0x23, base }, size, [&](Region* region) {
  854. if (region) {
  855. if (!is<MmapRegion>(*region)) {
  856. has_non_mmapped_region = true;
  857. return IterationDecision::Break;
  858. }
  859. auto& mmap_region = *(MmapRegion*)region;
  860. mmap_region.set_prot(prot);
  861. }
  862. return IterationDecision::Continue;
  863. });
  864. if (has_non_mmapped_region)
  865. return -EINVAL;
  866. return 0;
  867. }
  868. u32 Emulator::virt$madvise(FlatPtr, size_t, int)
  869. {
  870. return 0;
  871. }
  872. uid_t Emulator::virt$getuid()
  873. {
  874. return getuid();
  875. }
  876. uid_t Emulator::virt$geteuid()
  877. {
  878. return geteuid();
  879. }
  880. gid_t Emulator::virt$getgid()
  881. {
  882. return getgid();
  883. }
  884. gid_t Emulator::virt$getegid()
  885. {
  886. return getegid();
  887. }
  888. int Emulator::virt$setuid(uid_t uid)
  889. {
  890. return syscall(SC_setuid, uid);
  891. }
  892. int Emulator::virt$setgid(gid_t gid)
  893. {
  894. return syscall(SC_setgid, gid);
  895. }
  896. u32 Emulator::virt$write(int fd, FlatPtr data, ssize_t size)
  897. {
  898. if (size < 0)
  899. return -EINVAL;
  900. auto buffer = mmu().copy_buffer_from_vm(data, size);
  901. return syscall(SC_write, fd, buffer.data(), buffer.size());
  902. }
  903. u32 Emulator::virt$read(int fd, FlatPtr buffer, ssize_t size)
  904. {
  905. if (size < 0)
  906. return -EINVAL;
  907. auto buffer_result = ByteBuffer::create_uninitialized(size);
  908. if (!buffer_result.has_value())
  909. return -ENOMEM;
  910. auto& local_buffer = buffer_result.value();
  911. int nread = syscall(SC_read, fd, local_buffer.data(), local_buffer.size());
  912. if (nread < 0) {
  913. if (nread == -EPERM) {
  914. dump_backtrace();
  915. TODO();
  916. }
  917. return nread;
  918. }
  919. mmu().copy_to_vm(buffer, local_buffer.data(), local_buffer.size());
  920. return nread;
  921. }
  922. void Emulator::virt$sync()
  923. {
  924. syscall(SC_sync);
  925. }
  926. void Emulator::virt$exit(int status)
  927. {
  928. reportln("\n=={}== \033[33;1mSyscall: exit({})\033[0m, shutting down!", getpid(), status);
  929. m_exit_status = status;
  930. m_shutdown = true;
  931. }
  932. ssize_t Emulator::virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned int flags)
  933. {
  934. auto buffer_result = ByteBuffer::create_uninitialized(buffer_size);
  935. if (!buffer_result.has_value())
  936. return -ENOMEM;
  937. auto& host_buffer = buffer_result.value();
  938. int rc = syscall(SC_getrandom, host_buffer.data(), host_buffer.size(), flags);
  939. if (rc < 0)
  940. return rc;
  941. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  942. return rc;
  943. }
  944. int Emulator::virt$get_dir_entries(int fd, FlatPtr buffer, ssize_t size)
  945. {
  946. auto buffer_result = ByteBuffer::create_uninitialized(size);
  947. if (!buffer_result.has_value())
  948. return -ENOMEM;
  949. auto& host_buffer = buffer_result.value();
  950. int rc = syscall(SC_get_dir_entries, fd, host_buffer.data(), host_buffer.size());
  951. if (rc < 0)
  952. return rc;
  953. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  954. return rc;
  955. }
  956. int Emulator::virt$ioctl([[maybe_unused]] int fd, unsigned request, [[maybe_unused]] FlatPtr arg)
  957. {
  958. if (request == TIOCGWINSZ) {
  959. struct winsize ws;
  960. int rc = syscall(SC_ioctl, fd, TIOCGWINSZ, &ws);
  961. if (rc < 0)
  962. return rc;
  963. mmu().copy_to_vm(arg, &ws, sizeof(winsize));
  964. return 0;
  965. }
  966. if (request == TIOCSPGRP) {
  967. return syscall(SC_ioctl, fd, request, arg);
  968. }
  969. if (request == TCGETS) {
  970. struct termios termios;
  971. int rc = syscall(SC_ioctl, fd, request, &termios);
  972. if (rc < 0)
  973. return rc;
  974. mmu().copy_to_vm(arg, &termios, sizeof(termios));
  975. return rc;
  976. }
  977. if (request == TCSETS) {
  978. struct termios termios;
  979. mmu().copy_from_vm(&termios, arg, sizeof(termios));
  980. return syscall(SC_ioctl, fd, request, &termios);
  981. }
  982. if (request == TIOCNOTTY || request == TIOCSCTTY) {
  983. return syscall(SC_ioctl, fd, request, 0);
  984. }
  985. if (request == FB_IOCTL_GET_SIZE_IN_BYTES) {
  986. size_t size = 0;
  987. auto rc = syscall(SC_ioctl, fd, request, &size);
  988. mmu().copy_to_vm(arg, &size, sizeof(size));
  989. return rc;
  990. }
  991. if (request == FB_IOCTL_SET_RESOLUTION) {
  992. FBResolution user_resolution;
  993. mmu().copy_from_vm(&user_resolution, arg, sizeof(user_resolution));
  994. auto rc = syscall(SC_ioctl, fd, request, &user_resolution);
  995. mmu().copy_to_vm(arg, &user_resolution, sizeof(user_resolution));
  996. return rc;
  997. }
  998. if (request == FB_IOCTL_SET_BUFFER) {
  999. return syscall(SC_ioctl, fd, request, arg);
  1000. }
  1001. reportln("Unsupported ioctl: {}", request);
  1002. dump_backtrace();
  1003. TODO();
  1004. }
  1005. int Emulator::virt$emuctl(FlatPtr arg1, FlatPtr arg2, FlatPtr arg3)
  1006. {
  1007. auto* tracer = malloc_tracer();
  1008. if (arg1 <= 4 && !tracer)
  1009. return 0;
  1010. switch (arg1) {
  1011. case 1:
  1012. tracer->target_did_malloc({}, arg3, arg2);
  1013. return 0;
  1014. case 2:
  1015. tracer->target_did_free({}, arg2);
  1016. return 0;
  1017. case 3:
  1018. tracer->target_did_realloc({}, arg3, arg2);
  1019. return 0;
  1020. case 4:
  1021. tracer->target_did_change_chunk_size({}, arg3, arg2);
  1022. return 0;
  1023. case 5: // mark ROI start
  1024. if (is_in_region_of_interest())
  1025. return -EINVAL;
  1026. m_is_in_region_of_interest = true;
  1027. return 0;
  1028. case 6: // mark ROI end
  1029. m_is_in_region_of_interest = false;
  1030. return 0;
  1031. case 7:
  1032. m_is_memory_auditing_suppressed = true;
  1033. return 0;
  1034. case 8:
  1035. m_is_memory_auditing_suppressed = false;
  1036. return 0;
  1037. default:
  1038. return -EINVAL;
  1039. }
  1040. }
  1041. int Emulator::virt$fork()
  1042. {
  1043. int rc = fork();
  1044. if (rc < 0)
  1045. return -errno;
  1046. return rc;
  1047. }
  1048. int Emulator::virt$execve(FlatPtr params_addr)
  1049. {
  1050. Syscall::SC_execve_params params;
  1051. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1052. auto path = String::copy(mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length));
  1053. Vector<String> arguments;
  1054. Vector<String> environment;
  1055. auto copy_string_list = [this](auto& output_vector, auto& string_list) {
  1056. for (size_t i = 0; i < string_list.length; ++i) {
  1057. Syscall::StringArgument string;
  1058. mmu().copy_from_vm(&string, (FlatPtr)&string_list.strings[i], sizeof(string));
  1059. output_vector.append(String::copy(mmu().copy_buffer_from_vm((FlatPtr)string.characters, string.length)));
  1060. }
  1061. };
  1062. copy_string_list(arguments, params.arguments);
  1063. copy_string_list(environment, params.environment);
  1064. reportln("\n=={}== \033[33;1mSyscall:\033[0m execve", getpid());
  1065. reportln("=={}== @ {}", getpid(), path);
  1066. for (auto& argument : arguments)
  1067. reportln("=={}== - {}", getpid(), argument);
  1068. Vector<char*> argv;
  1069. Vector<char*> envp;
  1070. argv.append(const_cast<char*>("/bin/UserspaceEmulator"));
  1071. argv.append(const_cast<char*>(path.characters()));
  1072. if (g_report_to_debug)
  1073. argv.append(const_cast<char*>("--report-to-debug"));
  1074. argv.append(const_cast<char*>("--"));
  1075. auto create_string_vector = [](auto& output_vector, auto& input_vector) {
  1076. for (auto& string : input_vector)
  1077. output_vector.append(const_cast<char*>(string.characters()));
  1078. output_vector.append(nullptr);
  1079. };
  1080. create_string_vector(argv, arguments);
  1081. create_string_vector(envp, environment);
  1082. // Yoink duplicated program name.
  1083. argv.remove(3 + (g_report_to_debug ? 1 : 0));
  1084. return execve(argv[0], (char* const*)argv.data(), (char* const*)envp.data());
  1085. }
  1086. int Emulator::virt$stat(FlatPtr params_addr)
  1087. {
  1088. Syscall::SC_stat_params params;
  1089. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1090. auto path = String::copy(mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length));
  1091. struct stat host_statbuf;
  1092. int rc;
  1093. if (params.follow_symlinks)
  1094. rc = stat(path.characters(), &host_statbuf);
  1095. else
  1096. rc = lstat(path.characters(), &host_statbuf);
  1097. if (rc < 0)
  1098. return -errno;
  1099. mmu().copy_to_vm((FlatPtr)params.statbuf, &host_statbuf, sizeof(host_statbuf));
  1100. return rc;
  1101. }
  1102. int Emulator::virt$realpath(FlatPtr params_addr)
  1103. {
  1104. Syscall::SC_realpath_params params;
  1105. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1106. auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
  1107. auto buffer_result = ByteBuffer::create_zeroed(params.buffer.size);
  1108. if (!buffer_result.has_value())
  1109. return -ENOMEM;
  1110. auto& host_buffer = buffer_result.value();
  1111. Syscall::SC_realpath_params host_params;
  1112. host_params.path = { (const char*)path.data(), path.size() };
  1113. host_params.buffer = { (char*)host_buffer.data(), host_buffer.size() };
  1114. int rc = syscall(SC_realpath, &host_params);
  1115. if (rc < 0)
  1116. return rc;
  1117. mmu().copy_to_vm((FlatPtr)params.buffer.data, host_buffer.data(), host_buffer.size());
  1118. return rc;
  1119. }
  1120. int Emulator::virt$gethostname(FlatPtr buffer, ssize_t buffer_size)
  1121. {
  1122. if (buffer_size < 0)
  1123. return -EINVAL;
  1124. auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
  1125. if (!buffer_result.has_value())
  1126. return -ENOMEM;
  1127. auto& host_buffer = buffer_result.value();
  1128. int rc = syscall(SC_gethostname, host_buffer.data(), host_buffer.size());
  1129. if (rc < 0)
  1130. return rc;
  1131. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  1132. return rc;
  1133. }
  1134. int Emulator::virt$sigaction(int signum, FlatPtr act, FlatPtr oldact)
  1135. {
  1136. if (signum == SIGKILL) {
  1137. reportln("Attempted to sigaction() with SIGKILL");
  1138. return -EINVAL;
  1139. }
  1140. if (signum <= 0 || signum >= NSIG)
  1141. return -EINVAL;
  1142. struct sigaction host_act;
  1143. mmu().copy_from_vm(&host_act, act, sizeof(host_act));
  1144. auto& handler = m_signal_handler[signum];
  1145. handler.handler = (FlatPtr)host_act.sa_handler;
  1146. handler.mask = host_act.sa_mask;
  1147. handler.flags = host_act.sa_flags;
  1148. if (oldact) {
  1149. struct sigaction host_oldact;
  1150. auto& old_handler = m_signal_handler[signum];
  1151. host_oldact.sa_handler = (void (*)(int))(old_handler.handler);
  1152. host_oldact.sa_mask = old_handler.mask;
  1153. host_oldact.sa_flags = old_handler.flags;
  1154. mmu().copy_to_vm(oldact, &host_oldact, sizeof(host_oldact));
  1155. }
  1156. return 0;
  1157. }
  1158. int Emulator::virt$sigreturn()
  1159. {
  1160. u32 stack_ptr = m_cpu.esp().value();
  1161. auto local_pop = [&]() -> ValueWithShadow<u32> {
  1162. auto value = m_cpu.read_memory32({ m_cpu.ss(), stack_ptr });
  1163. stack_ptr += sizeof(u32);
  1164. return value;
  1165. };
  1166. auto smuggled_eax = local_pop();
  1167. stack_ptr += 4 * sizeof(u32);
  1168. m_signal_mask = local_pop().value();
  1169. m_cpu.set_edi(local_pop());
  1170. m_cpu.set_esi(local_pop());
  1171. m_cpu.set_ebp(local_pop());
  1172. m_cpu.set_esp(local_pop());
  1173. m_cpu.set_ebx(local_pop());
  1174. m_cpu.set_edx(local_pop());
  1175. m_cpu.set_ecx(local_pop());
  1176. m_cpu.set_eax(local_pop());
  1177. m_cpu.set_eip(local_pop().value());
  1178. m_cpu.set_eflags(local_pop());
  1179. // FIXME: We're losing shadow bits here.
  1180. return smuggled_eax.value();
  1181. }
  1182. int Emulator::virt$getpgrp()
  1183. {
  1184. return syscall(SC_getpgrp);
  1185. }
  1186. int Emulator::virt$getpgid(pid_t pid)
  1187. {
  1188. return syscall(SC_getpgid, pid);
  1189. }
  1190. int Emulator::virt$setpgid(pid_t pid, pid_t pgid)
  1191. {
  1192. return syscall(SC_setpgid, pid, pgid);
  1193. }
  1194. int Emulator::virt$ttyname(int fd, FlatPtr buffer, size_t buffer_size)
  1195. {
  1196. auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
  1197. if (!buffer_result.has_value())
  1198. return -ENOMEM;
  1199. auto& host_buffer = buffer_result.value();
  1200. int rc = syscall(SC_ttyname, fd, host_buffer.data(), host_buffer.size());
  1201. if (rc < 0)
  1202. return rc;
  1203. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  1204. return rc;
  1205. }
  1206. int Emulator::virt$getcwd(FlatPtr buffer, size_t buffer_size)
  1207. {
  1208. auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
  1209. if (!buffer_result.has_value())
  1210. return -ENOMEM;
  1211. auto& host_buffer = buffer_result.value();
  1212. int rc = syscall(SC_getcwd, host_buffer.data(), host_buffer.size());
  1213. if (rc < 0)
  1214. return rc;
  1215. mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
  1216. return rc;
  1217. }
  1218. int Emulator::virt$getsid(pid_t pid)
  1219. {
  1220. return syscall(SC_getsid, pid);
  1221. }
  1222. int Emulator::virt$access(FlatPtr path, size_t path_length, int type)
  1223. {
  1224. auto host_path = mmu().copy_buffer_from_vm(path, path_length);
  1225. return syscall(SC_access, host_path.data(), host_path.size(), type);
  1226. }
  1227. int Emulator::virt$waitid(FlatPtr params_addr)
  1228. {
  1229. Syscall::SC_waitid_params params;
  1230. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1231. Syscall::SC_waitid_params host_params = params;
  1232. siginfo info {};
  1233. host_params.infop = &info;
  1234. int rc = syscall(SC_waitid, &host_params);
  1235. if (rc < 0)
  1236. return rc;
  1237. if (info.si_addr) {
  1238. // FIXME: Translate this somehow once we actually start setting it in the kernel.
  1239. dbgln("si_addr is set to {:p}, I did not expect this!", info.si_addr);
  1240. TODO();
  1241. }
  1242. if (params.infop)
  1243. mmu().copy_to_vm((FlatPtr)params.infop, &info, sizeof(info));
  1244. return rc;
  1245. }
  1246. int Emulator::virt$chdir(FlatPtr path, size_t path_length)
  1247. {
  1248. auto host_path = mmu().copy_buffer_from_vm(path, path_length);
  1249. return syscall(SC_chdir, host_path.data(), host_path.size());
  1250. }
  1251. int Emulator::virt$dup2(int old_fd, int new_fd)
  1252. {
  1253. return syscall(SC_dup2, old_fd, new_fd);
  1254. }
  1255. int Emulator::virt$sched_getparam(pid_t pid, FlatPtr user_addr)
  1256. {
  1257. sched_param user_param;
  1258. mmu().copy_from_vm(&user_param, user_addr, sizeof(user_param));
  1259. auto rc = syscall(SC_sched_getparam, pid, &user_param);
  1260. mmu().copy_to_vm(user_addr, &user_param, sizeof(user_param));
  1261. return rc;
  1262. }
  1263. int Emulator::virt$sched_setparam(int pid, FlatPtr user_addr)
  1264. {
  1265. sched_param user_param;
  1266. mmu().copy_from_vm(&user_param, user_addr, sizeof(user_param));
  1267. return syscall(SC_sched_setparam, pid, &user_param);
  1268. }
  1269. int Emulator::virt$set_thread_name(pid_t pid, FlatPtr name_addr, size_t name_length)
  1270. {
  1271. auto user_name = mmu().copy_buffer_from_vm(name_addr, name_length);
  1272. auto name = String::formatted("(UE) {}", StringView { user_name.data(), user_name.size() });
  1273. return syscall(SC_set_thread_name, pid, name.characters(), name.length());
  1274. }
  1275. pid_t Emulator::virt$setsid()
  1276. {
  1277. return syscall(SC_setsid);
  1278. }
  1279. int Emulator::virt$create_inode_watcher(unsigned flags)
  1280. {
  1281. return syscall(SC_create_inode_watcher, flags);
  1282. }
  1283. int Emulator::virt$inode_watcher_add_watch(FlatPtr params_addr)
  1284. {
  1285. Syscall::SC_inode_watcher_add_watch_params params;
  1286. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1287. return syscall(SC_inode_watcher_add_watch, &params);
  1288. }
  1289. int Emulator::virt$inode_watcher_remove_watch(int fd, int wd)
  1290. {
  1291. return syscall(SC_inode_watcher_add_watch, fd, wd);
  1292. }
  1293. int Emulator::virt$clock_nanosleep(FlatPtr params_addr)
  1294. {
  1295. Syscall::SC_clock_nanosleep_params params;
  1296. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1297. timespec requested_sleep;
  1298. mmu().copy_from_vm(&requested_sleep, (FlatPtr)params.requested_sleep, sizeof(timespec));
  1299. params.requested_sleep = &requested_sleep;
  1300. auto remaining_vm_addr = params.remaining_sleep;
  1301. timespec remaining { 0, 0 };
  1302. params.remaining_sleep = &remaining;
  1303. int rc = syscall(SC_clock_nanosleep, &params);
  1304. if (remaining_vm_addr)
  1305. mmu().copy_to_vm((FlatPtr)remaining_vm_addr, &remaining, sizeof(timespec));
  1306. return rc;
  1307. }
  1308. int Emulator::virt$readlink(FlatPtr params_addr)
  1309. {
  1310. Syscall::SC_readlink_params params;
  1311. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1312. auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
  1313. auto buffer_result = ByteBuffer::create_zeroed(params.buffer.size);
  1314. if (!buffer_result.has_value())
  1315. return -ENOMEM;
  1316. auto& host_buffer = buffer_result.value();
  1317. Syscall::SC_readlink_params host_params;
  1318. host_params.path = { (const char*)path.data(), path.size() };
  1319. host_params.buffer = { (char*)host_buffer.data(), host_buffer.size() };
  1320. int rc = syscall(SC_readlink, &host_params);
  1321. if (rc < 0)
  1322. return rc;
  1323. mmu().copy_to_vm((FlatPtr)params.buffer.data, host_buffer.data(), host_buffer.size());
  1324. return rc;
  1325. }
  1326. u32 Emulator::virt$allocate_tls(FlatPtr initial_data, size_t size)
  1327. {
  1328. // TODO: This matches what Thread::make_thread_specific_region does. The kernel
  1329. // ends up allocating one more page. Figure out if this is intentional.
  1330. auto region_size = align_up_to(size, PAGE_SIZE) + PAGE_SIZE;
  1331. auto tcb_region = make<SimpleRegion>(0x20000000, region_size);
  1332. size_t offset = 0;
  1333. while (size - offset > 0) {
  1334. u8 buffer[512];
  1335. size_t read_bytes = min(sizeof(buffer), size - offset);
  1336. mmu().copy_from_vm(buffer, initial_data + offset, read_bytes);
  1337. memcpy(tcb_region->data() + offset, buffer, read_bytes);
  1338. offset += read_bytes;
  1339. }
  1340. memset(tcb_region->shadow_data(), 0x01, size);
  1341. auto tls_region = make<SimpleRegion>(0, 4);
  1342. tls_region->write32(0, shadow_wrap_as_initialized(tcb_region->base() + (u32)size));
  1343. memset(tls_region->shadow_data(), 0x01, 4);
  1344. u32 tls_base = tcb_region->base();
  1345. mmu().add_region(move(tcb_region));
  1346. mmu().set_tls_region(move(tls_region));
  1347. return tls_base;
  1348. }
  1349. int Emulator::virt$ptsname(int fd, FlatPtr buffer, size_t buffer_size)
  1350. {
  1351. auto pts = mmu().copy_buffer_from_vm(buffer, buffer_size);
  1352. return syscall(SC_ptsname, fd, pts.data(), pts.size());
  1353. }
  1354. int Emulator::virt$beep()
  1355. {
  1356. return syscall(SC_beep);
  1357. }
  1358. int Emulator::virt$msyscall(FlatPtr)
  1359. {
  1360. // FIXME: Implement this.
  1361. return 0;
  1362. }
  1363. int Emulator::virt$futex(FlatPtr params_addr)
  1364. {
  1365. Syscall::SC_futex_params params;
  1366. mmu().copy_from_vm(&params, params_addr, sizeof(params));
  1367. // FIXME: Implement this.
  1368. return 0;
  1369. }
  1370. }