Serenity Operating System
at master 937 lines 28 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <AK/Format.h> 9#include <AK/HashTable.h> 10#include <AK/IPv4Address.h> 11#include <AK/StdLibExtras.h> 12#include <AK/Types.h> 13#include <Kernel/API/SyscallString.h> 14#include <LibCore/ArgsParser.h> 15#include <LibCore/File.h> 16#include <LibCore/System.h> 17#include <LibMain/Main.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <netinet/in.h> 21#include <signal.h> 22#include <stdio.h> 23#include <string.h> 24#include <sys/arch/regs.h> 25#include <sys/ioctl.h> 26#include <sys/mman.h> 27#include <sys/ptrace.h> 28#include <sys/socket.h> 29#include <sys/time.h> 30#include <sys/wait.h> 31#include <syscall.h> 32#include <unistd.h> 33 34#define HANDLE(VALUE) \ 35 case VALUE: \ 36 return #VALUE##sv; 37#define VALUES_TO_NAMES(FUNC_NAME) \ 38 static DeprecatedString FUNC_NAME(int value) \ 39 { \ 40 switch (value) { 41#define END_VALUES_TO_NAMES() \ 42 } \ 43 return DeprecatedString::formatted("{}", value); \ 44 } 45 46VALUES_TO_NAMES(errno_name) 47HANDLE(EPERM) 48HANDLE(ENOENT) 49HANDLE(ESRCH) 50HANDLE(EINTR) 51HANDLE(EIO) 52HANDLE(ENXIO) 53HANDLE(E2BIG) 54HANDLE(ENOEXEC) 55HANDLE(EBADF) 56HANDLE(ECHILD) 57HANDLE(EAGAIN) 58HANDLE(ENOMEM) 59HANDLE(EACCES) 60HANDLE(EFAULT) 61HANDLE(ENOTBLK) 62HANDLE(EBUSY) 63HANDLE(EEXIST) 64HANDLE(EXDEV) 65HANDLE(ENODEV) 66HANDLE(ENOTDIR) 67HANDLE(EISDIR) 68HANDLE(EINVAL) 69HANDLE(ENFILE) 70HANDLE(EMFILE) 71HANDLE(ENOTTY) 72HANDLE(ETXTBSY) 73HANDLE(EFBIG) 74HANDLE(ENOSPC) 75HANDLE(ESPIPE) 76HANDLE(EROFS) 77HANDLE(EMLINK) 78HANDLE(EPIPE) 79HANDLE(ERANGE) 80HANDLE(ENAMETOOLONG) 81HANDLE(ELOOP) 82HANDLE(EOVERFLOW) 83HANDLE(EOPNOTSUPP) 84HANDLE(ENOSYS) 85HANDLE(ENOTIMPL) 86HANDLE(EAFNOSUPPORT) 87HANDLE(ENOTSOCK) 88HANDLE(EADDRINUSE) 89HANDLE(ENOTEMPTY) 90HANDLE(EDOM) 91HANDLE(ECONNREFUSED) 92HANDLE(EHOSTDOWN) 93HANDLE(EADDRNOTAVAIL) 94HANDLE(EISCONN) 95HANDLE(ECONNABORTED) 96HANDLE(EALREADY) 97HANDLE(ECONNRESET) 98HANDLE(EDESTADDRREQ) 99HANDLE(EHOSTUNREACH) 100HANDLE(EILSEQ) 101HANDLE(EMSGSIZE) 102HANDLE(ENETDOWN) 103HANDLE(ENETUNREACH) 104HANDLE(ENETRESET) 105HANDLE(ENOBUFS) 106HANDLE(ENOLCK) 107HANDLE(ENOMSG) 108HANDLE(ENOPROTOOPT) 109HANDLE(ENOTCONN) 110HANDLE(ESHUTDOWN) 111HANDLE(ETOOMANYREFS) 112HANDLE(EPROTONOSUPPORT) 113HANDLE(ESOCKTNOSUPPORT) 114HANDLE(EDEADLK) 115HANDLE(ETIMEDOUT) 116HANDLE(EPROTOTYPE) 117HANDLE(EINPROGRESS) 118HANDLE(ENOTHREAD) 119HANDLE(EPROTO) 120HANDLE(ENOTSUP) 121HANDLE(EPFNOSUPPORT) 122HANDLE(EDIRINTOSELF) 123HANDLE(EDQUOT) 124HANDLE(EMAXERRNO) 125END_VALUES_TO_NAMES() 126 127VALUES_TO_NAMES(whence_name) 128HANDLE(SEEK_SET) 129HANDLE(SEEK_CUR) 130HANDLE(SEEK_END) 131END_VALUES_TO_NAMES() 132 133VALUES_TO_NAMES(ioctl_request_name) 134HANDLE(TIOCGPGRP) 135HANDLE(TIOCSPGRP) 136HANDLE(TCGETS) 137HANDLE(TCSETS) 138HANDLE(TCSETSW) 139HANDLE(TCSETSF) 140HANDLE(TCFLSH) 141HANDLE(TIOCGWINSZ) 142HANDLE(TIOCSCTTY) 143HANDLE(TIOCSTI) 144HANDLE(TIOCNOTTY) 145HANDLE(TIOCSWINSZ) 146HANDLE(GRAPHICS_IOCTL_GET_PROPERTIES) 147HANDLE(GRAPHICS_IOCTL_SET_HEAD_MODE_SETTING) 148HANDLE(GRAPHICS_IOCTL_GET_HEAD_MODE_SETTING) 149HANDLE(GRAPHICS_IOCTL_SET_HEAD_VERTICAL_OFFSET_BUFFER) 150HANDLE(GRAPHICS_IOCTL_GET_HEAD_VERTICAL_OFFSET_BUFFER) 151HANDLE(GRAPHICS_IOCTL_FLUSH_HEAD_BUFFERS) 152HANDLE(GRAPHICS_IOCTL_FLUSH_HEAD) 153HANDLE(KEYBOARD_IOCTL_GET_NUM_LOCK) 154HANDLE(KEYBOARD_IOCTL_SET_NUM_LOCK) 155HANDLE(KEYBOARD_IOCTL_GET_CAPS_LOCK) 156HANDLE(KEYBOARD_IOCTL_SET_CAPS_LOCK) 157HANDLE(SIOCSIFADDR) 158HANDLE(SIOCGIFADDR) 159HANDLE(SIOCGIFHWADDR) 160HANDLE(SIOCGIFNETMASK) 161HANDLE(SIOCSIFNETMASK) 162HANDLE(SIOCGIFBRDADDR) 163HANDLE(SIOCGIFMTU) 164HANDLE(SIOCGIFFLAGS) 165HANDLE(SIOCGIFCONF) 166HANDLE(SIOCADDRT) 167HANDLE(SIOCDELRT) 168HANDLE(SIOCSARP) 169HANDLE(SIOCDARP) 170HANDLE(FIBMAP) 171HANDLE(FIONBIO) 172HANDLE(FIONREAD) 173HANDLE(KCOV_SETBUFSIZE) 174HANDLE(KCOV_ENABLE) 175HANDLE(KCOV_DISABLE) 176HANDLE(SOUNDCARD_IOCTL_SET_SAMPLE_RATE) 177HANDLE(SOUNDCARD_IOCTL_GET_SAMPLE_RATE) 178HANDLE(STORAGE_DEVICE_GET_SIZE) 179HANDLE(STORAGE_DEVICE_GET_BLOCK_SIZE) 180END_VALUES_TO_NAMES() 181 182VALUES_TO_NAMES(domain_name) 183HANDLE(AF_UNSPEC) 184HANDLE(AF_UNIX) 185HANDLE(AF_INET) 186HANDLE(AF_INET6) 187END_VALUES_TO_NAMES() 188 189VALUES_TO_NAMES(socket_type_name) 190HANDLE(SOCK_STREAM) 191HANDLE(SOCK_DGRAM) 192HANDLE(SOCK_RAW) 193HANDLE(SOCK_RDM) 194HANDLE(SOCK_SEQPACKET) 195END_VALUES_TO_NAMES() 196 197VALUES_TO_NAMES(protocol_name) 198HANDLE(PF_UNSPEC) 199HANDLE(PF_UNIX) 200HANDLE(PF_INET) 201HANDLE(PF_INET6) 202END_VALUES_TO_NAMES() 203 204VALUES_TO_NAMES(clockid_name) 205HANDLE(CLOCK_REALTIME) 206HANDLE(CLOCK_MONOTONIC) 207HANDLE(CLOCK_REALTIME_COARSE) 208HANDLE(CLOCK_MONOTONIC_COARSE) 209END_VALUES_TO_NAMES() 210 211static int g_pid = -1; 212 213using syscall_arg_t = u64; 214 215static void handle_sigint(int) 216{ 217 if (g_pid == -1) 218 return; 219 220 if (ptrace(PT_DETACH, g_pid, 0, 0) == -1) { 221 perror("detach"); 222 } 223} 224 225static ErrorOr<void> copy_from_process(void const* source, Bytes target) 226{ 227 return Core::System::ptrace_peekbuf(g_pid, const_cast<void*>(source), target); 228} 229 230static ErrorOr<ByteBuffer> copy_from_process(void const* source, size_t length) 231{ 232 auto buffer = TRY(ByteBuffer::create_uninitialized(length)); 233 TRY(copy_from_process(source, buffer.bytes())); 234 return buffer; 235} 236 237template<typename T> 238static ErrorOr<T> copy_from_process(T const* source) 239{ 240 T value {}; 241 TRY(copy_from_process(source, Bytes { &value, sizeof(T) })); 242 return value; 243} 244 245struct BitflagOption { 246 int value; 247 StringView name; 248}; 249 250#define BITFLAG(NAME) \ 251 BitflagOption \ 252 { \ 253 NAME, #NAME##sv \ 254 } 255 256struct BitflagBase { 257 int flagset; 258 // Derivatives must define 'options', like so: 259 // static constexpr auto options = { BITFLAG(O_CREAT), BITFLAG(O_DIRECTORY) }; 260}; 261 262namespace AK { 263template<typename BitflagDerivative> 264requires(IsBaseOf<BitflagBase, BitflagDerivative>) && requires { BitflagDerivative::options; } 265struct Formatter<BitflagDerivative> : StandardFormatter { 266 Formatter() = default; 267 explicit Formatter(StandardFormatter formatter) 268 : StandardFormatter(formatter) 269 { 270 } 271 272 ErrorOr<void> format(FormatBuilder& format_builder, BitflagDerivative const& value) 273 { 274 bool had_any_output = false; 275 int remaining = value.flagset; 276 277 for (BitflagOption const& option : BitflagDerivative::options) { 278 if ((remaining & option.value) != option.value) 279 continue; 280 remaining &= ~option.value; 281 if (had_any_output) 282 TRY(format_builder.put_literal(" | "sv)); 283 TRY(format_builder.put_literal(option.name)); 284 had_any_output = true; 285 } 286 287 if (remaining != 0) { 288 // No more BitflagOptions are available. Any remaining flags are unrecognized. 289 if (had_any_output) 290 TRY(format_builder.put_literal(" | "sv)); 291 format_builder.builder().appendff("0x{:x} (?)", static_cast<unsigned>(remaining)); 292 had_any_output = true; 293 } 294 295 if (!had_any_output) { 296 if constexpr (requires { BitflagDerivative::default_; }) 297 TRY(format_builder.put_literal(BitflagDerivative::default_)); 298 else 299 TRY(format_builder.put_literal("0"sv)); 300 } 301 302 return {}; 303 } 304}; 305} 306 307struct PointerArgument { 308 void const* value; 309}; 310 311namespace AK { 312template<> 313struct Formatter<PointerArgument> : StandardFormatter { 314 Formatter() = default; 315 explicit Formatter(StandardFormatter formatter) 316 : StandardFormatter(formatter) 317 { 318 } 319 320 ErrorOr<void> format(FormatBuilder& format_builder, PointerArgument const& value) 321 { 322 auto& builder = format_builder.builder(); 323 if (value.value == nullptr) 324 builder.append("null"sv); 325 else 326 builder.appendff("{}", value.value); 327 return {}; 328 } 329}; 330} 331 332struct StringArgument { 333 Syscall::StringArgument argument; 334 StringView trim_by {}; 335}; 336 337namespace AK { 338template<> 339struct Formatter<StringArgument> : StandardFormatter { 340 Formatter() = default; 341 explicit Formatter(StandardFormatter formatter) 342 : StandardFormatter(formatter) 343 { 344 } 345 346 ErrorOr<void> format(FormatBuilder& format_builder, StringArgument const& string_argument) 347 { 348 auto& builder = format_builder.builder(); 349 if (string_argument.argument.characters == nullptr) { 350 builder.append("null"sv); 351 return {}; 352 } 353 354 // TODO: Avoid trying to copy excessively long strings. 355 auto string_buffer = copy_from_process(string_argument.argument.characters, string_argument.argument.length); 356 if (string_buffer.is_error()) { 357 builder.appendff("{}{{{:p}, {}b}}", string_buffer.error(), (void const*)string_argument.argument.characters, string_argument.argument.length); 358 } else { 359 auto view = StringView(string_buffer.value()); 360 if (!string_argument.trim_by.is_empty()) 361 view = view.trim(string_argument.trim_by); 362 builder.appendff("\"{}\"", view); 363 } 364 365 return {}; 366 } 367}; 368} 369 370class FormattedSyscallBuilder { 371public: 372 FormattedSyscallBuilder(StringView syscall_name) 373 { 374 m_builder.append(syscall_name); 375 m_builder.append('('); 376 } 377 378 template<typename T> 379 void add_argument(CheckedFormatString<T> format, T&& arg) 380 { 381 add_argument_separator(); 382 m_builder.appendff(format.view(), forward<T>(arg)); 383 } 384 385 template<typename T> 386 void add_argument(T&& arg) 387 { 388 add_argument("{}", forward<T>(arg)); 389 } 390 391 template<typename... Ts> 392 void add_arguments(Ts&&... args) 393 { 394 (add_argument(forward<Ts>(args)), ...); 395 } 396 397 template<typename T> 398 void format_result_no_error(T res) 399 { 400 m_builder.appendff(") = {}\n", res); 401 } 402 403 void format_result(Integral auto res) 404 { 405 m_builder.append(") = "sv); 406 if (res < 0) 407 m_builder.appendff("{} {}", res, errno_name(-(int)res)); 408 else 409 m_builder.appendff("{}", res); 410 m_builder.append('\n'); 411 } 412 413 void format_result(void* res) 414 { 415 if (res == MAP_FAILED) 416 m_builder.append(") = MAP_FAILED\n"sv); 417 else if (FlatPtr(res) > FlatPtr(-EMAXERRNO)) 418 m_builder.appendff(") = {} {}\n", res, errno_name(-static_cast<int>(FlatPtr(res)))); 419 else 420 m_builder.appendff(") = {}\n", res); 421 } 422 423 void format_result() 424 { 425 m_builder.append(")\n"sv); 426 } 427 428 StringView string_view() 429 { 430 return m_builder.string_view(); 431 } 432 433private: 434 void add_argument_separator() 435 { 436 if (!m_first_arg) { 437 m_builder.append(", "sv); 438 } 439 m_first_arg = false; 440 } 441 442 StringBuilder m_builder; 443 bool m_first_arg { true }; 444}; 445 446static void format_getrandom(FormattedSyscallBuilder& builder, void* buffer, size_t size, unsigned flags) 447{ 448 builder.add_arguments(buffer, size, flags); 449} 450 451static ErrorOr<void> format_realpath(FormattedSyscallBuilder& builder, Syscall::SC_realpath_params* params_p, size_t length) 452{ 453 auto params = TRY(copy_from_process(params_p)); 454 builder.add_arguments(StringArgument { params.path }, StringArgument { { params.buffer.data, min(params.buffer.size, length) } }); 455 return {}; 456} 457 458static void format_exit(FormattedSyscallBuilder& builder, int status) 459{ 460 builder.add_argument(status); 461} 462 463struct OpenOptions : BitflagBase { 464 static constexpr auto options = { 465 BITFLAG(O_RDWR), BITFLAG(O_RDONLY), BITFLAG(O_WRONLY), 466 BITFLAG(O_EXEC), BITFLAG(O_CREAT), BITFLAG(O_EXCL), BITFLAG(O_NOCTTY), 467 BITFLAG(O_TRUNC), BITFLAG(O_APPEND), BITFLAG(O_NONBLOCK), BITFLAG(O_DIRECTORY), 468 BITFLAG(O_NOFOLLOW), BITFLAG(O_CLOEXEC), BITFLAG(O_DIRECT) 469 }; 470}; 471 472static ErrorOr<void> format_open(FormattedSyscallBuilder& builder, Syscall::SC_open_params* params_p) 473{ 474 auto params = TRY(copy_from_process(params_p)); 475 476 if (params.dirfd == AT_FDCWD) 477 builder.add_argument("AT_FDCWD"); 478 else 479 builder.add_argument(params.dirfd); 480 481 builder.add_arguments(StringArgument { params.path }, OpenOptions { params.options }); 482 483 if (params.options & O_CREAT) 484 builder.add_argument("{:04o}", params.mode); 485 return {}; 486} 487 488static void format_ioctl(FormattedSyscallBuilder& builder, int fd, unsigned request, void* arg) 489{ 490 builder.add_arguments(fd, ioctl_request_name(request)); 491 if (request == FIONBIO) { 492 auto value = copy_from_process(reinterpret_cast<int*>(arg)); 493 builder.add_argument(value.release_value_but_fixme_should_propagate_errors()); 494 } else 495 builder.add_argument(PointerArgument { arg }); 496} 497 498namespace AK { 499template<> 500struct Formatter<struct timespec> : StandardFormatter { 501 ErrorOr<void> format(FormatBuilder& format_builder, struct timespec value) 502 { 503 auto& builder = format_builder.builder(); 504 builder.appendff("{{tv_sec={}, tv_nsec={}}}", value.tv_sec, value.tv_nsec); 505 return {}; 506 } 507}; 508 509template<> 510struct Formatter<struct timeval> : StandardFormatter { 511 ErrorOr<void> format(FormatBuilder& format_builder, struct timeval value) 512 { 513 auto& builder = format_builder.builder(); 514 builder.appendff("{{tv_sec={}, tv_usec={}}}", value.tv_sec, value.tv_usec); 515 return {}; 516 } 517}; 518 519template<> 520struct Formatter<struct stat> : StandardFormatter { 521 ErrorOr<void> format(FormatBuilder& format_builder, struct stat value) 522 { 523 auto& builder = format_builder.builder(); 524 builder.appendff( 525 "{{st_dev={}, st_ino={}, st_mode={}, st_nlink={}, st_uid={}, st_gid={}, st_rdev={}, " 526 "st_size={}, st_blksize={}, st_blocks={}, st_atim={}, st_mtim={}, st_ctim={}}}", 527 value.st_dev, value.st_ino, value.st_mode, value.st_nlink, value.st_uid, value.st_gid, value.st_rdev, 528 value.st_size, value.st_blksize, value.st_blocks, value.st_atim, value.st_mtim, value.st_ctim); 529 return {}; 530 } 531}; 532} 533 534static void format_chdir(FormattedSyscallBuilder& builder, char const* path_p, size_t length) 535{ 536 auto buf = copy_from_process(path_p, length); 537 if (buf.is_error()) 538 builder.add_arguments(buf.error()); 539 else 540 builder.add_arguments(StringView { buf.value().data(), buf.value().size() }); 541} 542 543static void format_fstat(FormattedSyscallBuilder& builder, int fd, struct stat* buf_p) 544{ 545 auto buf = copy_from_process(buf_p); 546 builder.add_arguments(fd, buf.release_value_but_fixme_should_propagate_errors()); 547} 548 549static ErrorOr<void> format_stat(FormattedSyscallBuilder& builder, Syscall::SC_stat_params* params_p) 550{ 551 auto params = TRY(copy_from_process(params_p)); 552 if (params.dirfd == AT_FDCWD) 553 builder.add_argument("AT_FDCWD"); 554 else 555 builder.add_argument(params.dirfd); 556 builder.add_arguments(StringArgument { params.path }, TRY(copy_from_process(params.statbuf)), params.follow_symlinks); 557 return {}; 558} 559 560static void format_lseek(FormattedSyscallBuilder& builder, int fd, off_t offset, int whence) 561{ 562 builder.add_arguments(fd, offset, whence_name(whence)); 563} 564 565static void format_read(FormattedSyscallBuilder& builder, int fd, void* buf, size_t nbyte) 566{ 567 builder.add_arguments(fd, buf, nbyte); 568} 569 570static void format_write(FormattedSyscallBuilder& builder, int fd, void* buf, size_t nbyte) 571{ 572 builder.add_arguments(fd, buf, nbyte); 573} 574 575static void format_close(FormattedSyscallBuilder& builder, int fd) 576{ 577 builder.add_arguments(fd); 578} 579 580static ErrorOr<void> format_poll(FormattedSyscallBuilder& builder, Syscall::SC_poll_params* params_p) 581{ 582 // TODO: format fds and sigmask properly 583 auto params = TRY(copy_from_process(params_p)); 584 builder.add_arguments( 585 params.nfds, 586 PointerArgument { params.fds }, 587 TRY(copy_from_process(params.timeout)), 588 PointerArgument { params.sigmask }); 589 return {}; 590} 591 592namespace AK { 593template<> 594struct Formatter<struct sockaddr> : StandardFormatter { 595 ErrorOr<void> format(FormatBuilder& format_builder, struct sockaddr address) 596 { 597 auto& builder = format_builder.builder(); 598 builder.append("{sa_family="sv); 599 builder.append(domain_name(address.sa_family)); 600 if (address.sa_family == AF_INET) { 601 auto* address_in = (const struct sockaddr_in*)&address; 602 builder.appendff( 603 ", sin_port={}, sin_addr={}", 604 address_in->sin_port, 605 IPv4Address(address_in->sin_addr.s_addr).to_deprecated_string()); 606 } else if (address.sa_family == AF_UNIX) { 607 auto* address_un = (const struct sockaddr_un*)&address; 608 builder.appendff( 609 ", sun_path={}", 610 address_un->sun_path); 611 } 612 builder.append('}'); 613 return {}; 614 } 615}; 616} 617 618static void format_socket(FormattedSyscallBuilder& builder, int domain, int type, int protocol) 619{ 620 // TODO: show additional options in type 621 builder.add_arguments(domain_name(domain), socket_type_name(type & SOCK_TYPE_MASK), protocol_name(protocol)); 622} 623 624static void format_connect(FormattedSyscallBuilder& builder, int socket, const struct sockaddr* address_p, socklen_t address_len) 625{ 626 builder.add_arguments(socket, copy_from_process(address_p).release_value_but_fixme_should_propagate_errors(), address_len); 627} 628 629struct MsgOptions : BitflagBase { 630 static constexpr auto options = { 631 BITFLAG(MSG_TRUNC), BITFLAG(MSG_CTRUNC), BITFLAG(MSG_PEEK), 632 BITFLAG(MSG_OOB), BITFLAG(MSG_DONTROUTE), BITFLAG(MSG_WAITALL), 633 BITFLAG(MSG_DONTWAIT) 634 }; 635}; 636 637static void format_recvmsg(FormattedSyscallBuilder& builder, int socket, struct msghdr* message, int flags) 638{ 639 // TODO: format message 640 builder.add_arguments(socket, message, MsgOptions { flags }); 641} 642 643struct MmapFlags : BitflagBase { 644 static constexpr auto options = { 645 BITFLAG(MAP_SHARED), BITFLAG(MAP_PRIVATE), BITFLAG(MAP_FIXED), BITFLAG(MAP_ANONYMOUS), 646 BITFLAG(MAP_RANDOMIZED), BITFLAG(MAP_STACK), BITFLAG(MAP_NORESERVE), BITFLAG(MAP_PURGEABLE), 647 BITFLAG(MAP_FIXED_NOREPLACE) 648 }; 649 static constexpr StringView default_ = "MAP_FILE"sv; 650}; 651 652struct MemoryProtectionFlags : BitflagBase { 653 static constexpr auto options = { 654 BITFLAG(PROT_READ), BITFLAG(PROT_WRITE), BITFLAG(PROT_EXEC) 655 }; 656 static constexpr StringView default_ = "PROT_NONE"sv; 657}; 658 659static ErrorOr<void> format_mmap(FormattedSyscallBuilder& builder, Syscall::SC_mmap_params* params_p) 660{ 661 auto params = TRY(copy_from_process(params_p)); 662 builder.add_arguments(params.addr, params.size, MemoryProtectionFlags { params.prot }, MmapFlags { params.flags }, params.fd, params.offset, params.alignment, StringArgument { params.name }); 663 return {}; 664} 665 666static void format_munmap(FormattedSyscallBuilder& builder, void* addr, size_t size) 667{ 668 builder.add_arguments(addr, size); 669} 670 671static void format_mprotect(FormattedSyscallBuilder& builder, void* addr, size_t size, int prot) 672{ 673 builder.add_arguments(addr, size, MemoryProtectionFlags { prot }); 674} 675 676static ErrorOr<void> format_set_mmap_name(FormattedSyscallBuilder& builder, Syscall::SC_set_mmap_name_params* params_p) 677{ 678 auto params = TRY(copy_from_process(params_p)); 679 builder.add_arguments(params.addr, params.size, StringArgument { params.name }); 680 return {}; 681} 682 683static void format_clock_gettime(FormattedSyscallBuilder& builder, clockid_t clockid, struct timespec* time) 684{ 685 builder.add_arguments(clockid_name(clockid), copy_from_process(time).release_value_but_fixme_should_propagate_errors()); 686} 687 688static void format_dbgputstr(FormattedSyscallBuilder& builder, char* characters, size_t size) 689{ 690 builder.add_argument(StringArgument { { characters, size }, "\0\n"sv }); 691} 692 693static void format_get_process_name(FormattedSyscallBuilder& builder, char* buffer, size_t buffer_size) 694{ 695 builder.add_argument(StringArgument { { buffer, buffer_size }, "\0"sv }); 696} 697 698static ErrorOr<void> format_syscall(FormattedSyscallBuilder& builder, Syscall::Function syscall_function, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, syscall_arg_t res) 699{ 700 enum ResultType { 701 Int, 702 Ssize, 703 VoidP, 704 Void 705 }; 706 707 ResultType result_type { Int }; 708 switch (syscall_function) { 709 case SC_clock_gettime: 710 format_clock_gettime(builder, (clockid_t)arg1, (struct timespec*)arg2); 711 break; 712 case SC_close: 713 format_close(builder, (int)arg1); 714 break; 715 case SC_connect: 716 format_connect(builder, (int)arg1, (const struct sockaddr*)arg2, (socklen_t)arg3); 717 break; 718 case SC_dbgputstr: 719 format_dbgputstr(builder, (char*)arg1, (size_t)arg2); 720 break; 721 case SC_exit: 722 format_exit(builder, (int)arg1); 723 result_type = Void; 724 break; 725 case SC_fstat: 726 format_fstat(builder, (int)arg1, (struct stat*)arg2); 727 result_type = Ssize; 728 break; 729 case SC_chdir: 730 format_chdir(builder, (char const*)arg1, (size_t)arg2); 731 result_type = Int; 732 break; 733 case SC_get_process_name: 734 format_get_process_name(builder, (char*)arg1, (size_t)arg2); 735 break; 736 case SC_getrandom: 737 format_getrandom(builder, (void*)arg1, (size_t)arg2, (unsigned)arg3); 738 break; 739 case SC_ioctl: 740 format_ioctl(builder, (int)arg1, (unsigned)arg2, (void*)arg3); 741 break; 742 case SC_lseek: 743 format_lseek(builder, (int)arg1, (off_t)arg2, (int)arg3); 744 break; 745 case SC_mmap: 746 TRY(format_mmap(builder, (Syscall::SC_mmap_params*)arg1)); 747 result_type = VoidP; 748 break; 749 case SC_mprotect: 750 format_mprotect(builder, (void*)arg1, (size_t)arg2, (int)arg3); 751 break; 752 case SC_munmap: 753 format_munmap(builder, (void*)arg1, (size_t)arg2); 754 break; 755 case SC_open: 756 TRY(format_open(builder, (Syscall::SC_open_params*)arg1)); 757 break; 758 case SC_poll: 759 TRY(format_poll(builder, (Syscall::SC_poll_params*)arg1)); 760 break; 761 case SC_read: 762 format_read(builder, (int)arg1, (void*)arg2, (size_t)arg3); 763 result_type = Ssize; 764 break; 765 case SC_realpath: 766 TRY(format_realpath(builder, (Syscall::SC_realpath_params*)arg1, (size_t)res)); 767 break; 768 case SC_recvmsg: 769 format_recvmsg(builder, (int)arg1, (struct msghdr*)arg2, (int)arg3); 770 result_type = Ssize; 771 break; 772 case SC_set_mmap_name: 773 TRY(format_set_mmap_name(builder, (Syscall::SC_set_mmap_name_params*)arg1)); 774 break; 775 case SC_socket: 776 format_socket(builder, (int)arg1, (int)arg2, (int)arg3); 777 break; 778 case SC_stat: 779 TRY(format_stat(builder, (Syscall::SC_stat_params*)arg1)); 780 break; 781 case SC_write: 782 format_write(builder, (int)arg1, (void*)arg2, (size_t)arg3); 783 result_type = Ssize; 784 break; 785 case SC_getuid: 786 case SC_geteuid: 787 case SC_getgid: 788 case SC_getegid: 789 case SC_getpid: 790 case SC_getppid: 791 case SC_gettid: 792 break; 793 default: 794 builder.add_arguments((void*)arg1, (void*)arg2, (void*)arg3); 795 result_type = VoidP; 796 } 797 798 switch (result_type) { 799 case Int: 800 builder.format_result((int)res); 801 break; 802 case Ssize: 803 builder.format_result((ssize_t)res); 804 break; 805 case VoidP: 806 builder.format_result((void*)res); 807 break; 808 case Void: 809 builder.format_result(); 810 break; 811 } 812 return {}; 813} 814 815ErrorOr<int> serenity_main(Main::Arguments arguments) 816{ 817 TRY(Core::System::pledge("stdio rpath wpath cpath proc exec ptrace sigaction")); 818 819 Vector<StringView> child_argv; 820 821 StringView output_filename; 822 StringView exclude_syscalls_option; 823 StringView include_syscalls_option; 824 HashTable<StringView> exclude_syscalls; 825 HashTable<StringView> include_syscalls; 826 827 Core::ArgsParser parser; 828 parser.set_stop_on_first_non_option(true); 829 parser.set_general_help( 830 "Trace all syscalls and their result."); 831 parser.add_option(g_pid, "Trace the given PID", "pid", 'p', "pid"); 832 parser.add_option(output_filename, "Filename to write output to", "output", 'o', "output"); 833 parser.add_option(exclude_syscalls_option, "Comma-delimited syscalls to exclude", "exclude", 'e', "exclude"); 834 parser.add_option(include_syscalls_option, "Comma-delimited syscalls to include", "include", 'i', "include"); 835 parser.add_positional_argument(child_argv, "Arguments to exec", "argument", Core::ArgsParser::Required::No); 836 837 parser.parse(arguments); 838 839 auto trace_file = output_filename.is_empty() 840 ? TRY(Core::File::standard_error()) 841 : TRY(Core::File::open(output_filename, Core::File::OpenMode::Write)); 842 843 auto parse_syscalls = [](StringView option, auto& hash_table) { 844 if (!option.is_empty()) { 845 for (auto syscall : option.split_view(',')) 846 hash_table.set(syscall); 847 } 848 }; 849 parse_syscalls(exclude_syscalls_option, exclude_syscalls); 850 parse_syscalls(include_syscalls_option, include_syscalls); 851 852 TRY(Core::System::pledge("stdio rpath proc exec ptrace sigaction")); 853 854 int status; 855 if (g_pid == -1) { 856 if (child_argv.is_empty()) 857 return Error::from_string_literal("Expected either a pid or some arguments"); 858 859 auto pid = TRY(Core::System::fork()); 860 861 if (!pid) { 862 TRY(Core::System::ptrace(PT_TRACE_ME, 0, 0, 0)); 863 TRY(Core::System::exec(child_argv.first(), child_argv, Core::System::SearchInPath::Yes)); 864 VERIFY_NOT_REACHED(); 865 } 866 867 g_pid = pid; 868 if (waitpid(pid, &status, WSTOPPED | WEXITED) != pid || !WIFSTOPPED(status)) { 869 perror("waitpid"); 870 return 1; 871 } 872 } 873 874 struct sigaction sa = {}; 875 sa.sa_handler = handle_sigint; 876 TRY(Core::System::sigaction(SIGINT, &sa, nullptr)); 877 878 TRY(Core::System::ptrace(PT_ATTACH, g_pid, 0, 0)); 879 if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) { 880 perror("waitpid"); 881 return 1; 882 } 883 884 for (;;) { 885 TRY(Core::System::ptrace(PT_SYSCALL, g_pid, 0, 0)); 886 887 if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) { 888 perror("wait_pid"); 889 return 1; 890 } 891 PtraceRegisters regs = {}; 892 TRY(Core::System::ptrace(PT_GETREGS, g_pid, &regs, 0)); 893#if ARCH(X86_64) 894 syscall_arg_t syscall_index = regs.rax; 895 syscall_arg_t arg1 = regs.rdx; 896 syscall_arg_t arg2 = regs.rcx; 897 syscall_arg_t arg3 = regs.rbx; 898#elif ARCH(AARCH64) 899 syscall_arg_t syscall_index = 0; // FIXME 900 syscall_arg_t arg1 = 0; // FIXME 901 syscall_arg_t arg2 = 0; // FIXME 902 syscall_arg_t arg3 = 0; // FIXME 903 TODO_AARCH64(); 904#else 905# error Unknown architecture 906#endif 907 908 TRY(Core::System::ptrace(PT_SYSCALL, g_pid, 0, 0)); 909 if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) { 910 perror("wait_pid"); 911 return 1; 912 } 913 914 TRY(Core::System::ptrace(PT_GETREGS, g_pid, &regs, 0)); 915 916#if ARCH(X86_64) 917 u64 res = regs.rax; 918#elif ARCH(AARCH64) 919 u64 res = 0; // FIXME 920 TODO_AARCH64(); 921#else 922# error Unknown architecture 923#endif 924 925 auto syscall_function = (Syscall::Function)syscall_index; 926 auto syscall_name = to_string(syscall_function); 927 if (exclude_syscalls.contains(syscall_name)) 928 continue; 929 if (!include_syscalls.is_empty() && !include_syscalls.contains(syscall_name)) 930 continue; 931 932 FormattedSyscallBuilder builder(syscall_name); 933 TRY(format_syscall(builder, syscall_function, arg1, arg2, arg3, res)); 934 935 TRY(trace_file->write_until_depleted(builder.string_view().bytes())); 936 } 937}