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