Serenity Operating System
at master 657 lines 21 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Types.h> 10#include <AK/Userspace.h> 11#include <Kernel/API/POSIX/sched.h> 12 13#ifdef KERNEL 14# include <AK/Error.h> 15# include <Kernel/Arch/RegisterState.h> 16#endif 17 18constexpr int syscall_vector = 0x82; 19 20extern "C" { 21struct pollfd; 22struct timeval; 23struct timespec; 24struct sockaddr; 25struct siginfo; 26struct stat; 27struct statvfs; 28typedef u32 socklen_t; 29} 30 31namespace Kernel { 32 33enum class NeedsBigProcessLock { 34 Yes, 35 No 36}; 37 38// Declare all syscalls and associated metadata. 39// 40// NOTE: When declaring a new syscall or modifying an existing, please 41// ensure that the proper assert is present at the top of the syscall 42// implementation to both verify and document to any readers if the 43// syscall acquires the big process lock or not. The asserts are: 44// - VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) 45// - VERIFY_NO_PROCESS_BIG_LOCK(this) 46// 47#define ENUMERATE_SYSCALLS(S) \ 48 S(accept4, NeedsBigProcessLock::No) \ 49 S(adjtime, NeedsBigProcessLock::No) \ 50 S(alarm, NeedsBigProcessLock::Yes) \ 51 S(allocate_tls, NeedsBigProcessLock::Yes) \ 52 S(anon_create, NeedsBigProcessLock::No) \ 53 S(annotate_mapping, NeedsBigProcessLock::No) \ 54 S(beep, NeedsBigProcessLock::No) \ 55 S(bind, NeedsBigProcessLock::No) \ 56 S(chdir, NeedsBigProcessLock::No) \ 57 S(chmod, NeedsBigProcessLock::No) \ 58 S(chown, NeedsBigProcessLock::No) \ 59 S(clock_gettime, NeedsBigProcessLock::No) \ 60 S(clock_nanosleep, NeedsBigProcessLock::No) \ 61 S(clock_getres, NeedsBigProcessLock::No) \ 62 S(clock_settime, NeedsBigProcessLock::No) \ 63 S(close, NeedsBigProcessLock::No) \ 64 S(connect, NeedsBigProcessLock::No) \ 65 S(create_inode_watcher, NeedsBigProcessLock::No) \ 66 S(create_thread, NeedsBigProcessLock::Yes) \ 67 S(dbgputstr, NeedsBigProcessLock::No) \ 68 S(detach_thread, NeedsBigProcessLock::Yes) \ 69 S(disown, NeedsBigProcessLock::Yes) \ 70 S(dump_backtrace, NeedsBigProcessLock::No) \ 71 S(dup2, NeedsBigProcessLock::No) \ 72 S(emuctl, NeedsBigProcessLock::No) \ 73 S(execve, NeedsBigProcessLock::Yes) \ 74 S(exit, NeedsBigProcessLock::Yes) \ 75 S(exit_thread, NeedsBigProcessLock::Yes) \ 76 S(faccessat, NeedsBigProcessLock::Yes) \ 77 S(fchdir, NeedsBigProcessLock::No) \ 78 S(fchmod, NeedsBigProcessLock::No) \ 79 S(fchown, NeedsBigProcessLock::No) \ 80 S(fcntl, NeedsBigProcessLock::Yes) \ 81 S(fork, NeedsBigProcessLock::Yes) \ 82 S(fstat, NeedsBigProcessLock::No) \ 83 S(fstatvfs, NeedsBigProcessLock::No) \ 84 S(fsync, NeedsBigProcessLock::No) \ 85 S(ftruncate, NeedsBigProcessLock::No) \ 86 S(futex, NeedsBigProcessLock::Yes) \ 87 S(get_dir_entries, NeedsBigProcessLock::Yes) \ 88 S(get_process_name, NeedsBigProcessLock::No) \ 89 S(get_root_session_id, NeedsBigProcessLock::No) \ 90 S(get_stack_bounds, NeedsBigProcessLock::No) \ 91 S(get_thread_name, NeedsBigProcessLock::No) \ 92 S(getcwd, NeedsBigProcessLock::No) \ 93 S(getegid, NeedsBigProcessLock::No) \ 94 S(geteuid, NeedsBigProcessLock::No) \ 95 S(getgid, NeedsBigProcessLock::No) \ 96 S(getgroups, NeedsBigProcessLock::No) \ 97 S(gethostname, NeedsBigProcessLock::No) \ 98 S(getkeymap, NeedsBigProcessLock::No) \ 99 S(getpeername, NeedsBigProcessLock::Yes) \ 100 S(getpgid, NeedsBigProcessLock::Yes) \ 101 S(getpgrp, NeedsBigProcessLock::Yes) \ 102 S(getpid, NeedsBigProcessLock::No) \ 103 S(getppid, NeedsBigProcessLock::No) \ 104 S(getrandom, NeedsBigProcessLock::No) \ 105 S(getresgid, NeedsBigProcessLock::No) \ 106 S(getresuid, NeedsBigProcessLock::No) \ 107 S(getrusage, NeedsBigProcessLock::Yes) \ 108 S(getsid, NeedsBigProcessLock::Yes) \ 109 S(getsockname, NeedsBigProcessLock::Yes) \ 110 S(getsockopt, NeedsBigProcessLock::No) \ 111 S(gettid, NeedsBigProcessLock::No) \ 112 S(getuid, NeedsBigProcessLock::No) \ 113 S(inode_watcher_add_watch, NeedsBigProcessLock::Yes) \ 114 S(inode_watcher_remove_watch, NeedsBigProcessLock::Yes) \ 115 S(ioctl, NeedsBigProcessLock::Yes) \ 116 S(join_thread, NeedsBigProcessLock::Yes) \ 117 S(jail_create, NeedsBigProcessLock::No) \ 118 S(jail_attach, NeedsBigProcessLock::No) \ 119 S(kill, NeedsBigProcessLock::Yes) \ 120 S(kill_thread, NeedsBigProcessLock::Yes) \ 121 S(killpg, NeedsBigProcessLock::Yes) \ 122 S(link, NeedsBigProcessLock::No) \ 123 S(listen, NeedsBigProcessLock::No) \ 124 S(lseek, NeedsBigProcessLock::No) \ 125 S(madvise, NeedsBigProcessLock::Yes) \ 126 S(map_time_page, NeedsBigProcessLock::Yes) \ 127 S(mkdir, NeedsBigProcessLock::No) \ 128 S(mknod, NeedsBigProcessLock::No) \ 129 S(mmap, NeedsBigProcessLock::Yes) \ 130 S(mount, NeedsBigProcessLock::Yes) \ 131 S(mprotect, NeedsBigProcessLock::Yes) \ 132 S(mremap, NeedsBigProcessLock::Yes) \ 133 S(msync, NeedsBigProcessLock::Yes) \ 134 S(munmap, NeedsBigProcessLock::Yes) \ 135 S(open, NeedsBigProcessLock::Yes) \ 136 S(perf_event, NeedsBigProcessLock::Yes) \ 137 S(perf_register_string, NeedsBigProcessLock::Yes) \ 138 S(pipe, NeedsBigProcessLock::No) \ 139 S(pledge, NeedsBigProcessLock::No) \ 140 S(poll, NeedsBigProcessLock::Yes) \ 141 S(posix_fallocate, NeedsBigProcessLock::No) \ 142 S(prctl, NeedsBigProcessLock::No) \ 143 S(profiling_disable, NeedsBigProcessLock::Yes) \ 144 S(profiling_enable, NeedsBigProcessLock::Yes) \ 145 S(profiling_free_buffer, NeedsBigProcessLock::Yes) \ 146 S(ptrace, NeedsBigProcessLock::Yes) \ 147 S(purge, NeedsBigProcessLock::Yes) \ 148 S(read, NeedsBigProcessLock::Yes) \ 149 S(pread, NeedsBigProcessLock::Yes) \ 150 S(readlink, NeedsBigProcessLock::No) \ 151 S(readv, NeedsBigProcessLock::Yes) \ 152 S(realpath, NeedsBigProcessLock::No) \ 153 S(recvfd, NeedsBigProcessLock::No) \ 154 S(recvmsg, NeedsBigProcessLock::Yes) \ 155 S(rename, NeedsBigProcessLock::No) \ 156 S(rmdir, NeedsBigProcessLock::No) \ 157 S(scheduler_get_parameters, NeedsBigProcessLock::No) \ 158 S(scheduler_set_parameters, NeedsBigProcessLock::No) \ 159 S(sendfd, NeedsBigProcessLock::No) \ 160 S(sendmsg, NeedsBigProcessLock::Yes) \ 161 S(set_mmap_name, NeedsBigProcessLock::Yes) \ 162 S(set_process_name, NeedsBigProcessLock::No) \ 163 S(set_thread_name, NeedsBigProcessLock::No) \ 164 S(setegid, NeedsBigProcessLock::No) \ 165 S(seteuid, NeedsBigProcessLock::No) \ 166 S(setgid, NeedsBigProcessLock::No) \ 167 S(setgroups, NeedsBigProcessLock::No) \ 168 S(sethostname, NeedsBigProcessLock::No) \ 169 S(setkeymap, NeedsBigProcessLock::No) \ 170 S(setpgid, NeedsBigProcessLock::Yes) \ 171 S(setregid, NeedsBigProcessLock::No) \ 172 S(setresgid, NeedsBigProcessLock::No) \ 173 S(setresuid, NeedsBigProcessLock::No) \ 174 S(setreuid, NeedsBigProcessLock::No) \ 175 S(setsid, NeedsBigProcessLock::Yes) \ 176 S(setsockopt, NeedsBigProcessLock::No) \ 177 S(setuid, NeedsBigProcessLock::No) \ 178 S(shutdown, NeedsBigProcessLock::No) \ 179 S(sigaction, NeedsBigProcessLock::Yes) \ 180 S(sigaltstack, NeedsBigProcessLock::Yes) \ 181 S(sigpending, NeedsBigProcessLock::Yes) \ 182 S(sigprocmask, NeedsBigProcessLock::Yes) \ 183 S(sigreturn, NeedsBigProcessLock::Yes) \ 184 S(sigsuspend, NeedsBigProcessLock::Yes) \ 185 S(sigtimedwait, NeedsBigProcessLock::Yes) \ 186 S(socket, NeedsBigProcessLock::No) \ 187 S(socketpair, NeedsBigProcessLock::No) \ 188 S(stat, NeedsBigProcessLock::No) \ 189 S(statvfs, NeedsBigProcessLock::No) \ 190 S(symlink, NeedsBigProcessLock::No) \ 191 S(sync, NeedsBigProcessLock::No) \ 192 S(sysconf, NeedsBigProcessLock::No) \ 193 S(times, NeedsBigProcessLock::Yes) \ 194 S(umask, NeedsBigProcessLock::Yes) \ 195 S(umount, NeedsBigProcessLock::Yes) \ 196 S(uname, NeedsBigProcessLock::No) \ 197 S(unlink, NeedsBigProcessLock::No) \ 198 S(unveil, NeedsBigProcessLock::No) \ 199 S(utime, NeedsBigProcessLock::No) \ 200 S(utimensat, NeedsBigProcessLock::No) \ 201 S(waitid, NeedsBigProcessLock::Yes) \ 202 S(write, NeedsBigProcessLock::Yes) \ 203 S(pwritev, NeedsBigProcessLock::Yes) \ 204 S(yield, NeedsBigProcessLock::No) 205 206namespace Syscall { 207 208#ifdef KERNEL 209ErrorOr<FlatPtr> handle(RegisterState&, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3, FlatPtr arg4); 210#endif 211 212enum Function { 213#undef __ENUMERATE_SYSCALL 214#define __ENUMERATE_SYSCALL(sys_call, needs_lock) SC_##sys_call, 215 ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL) 216#undef __ENUMERATE_SYSCALL 217 __Count 218}; 219 220#ifdef AK_OS_SERENITY 221struct StringArgument { 222 char const* characters; 223 size_t length { 0 }; 224}; 225 226template<typename DataType, typename SizeType> 227struct MutableBufferArgument { 228 DataType* data { nullptr }; 229 SizeType size { 0 }; 230}; 231 232struct StringListArgument { 233 StringArgument* strings {}; 234 size_t length { 0 }; 235}; 236 237struct SC_mmap_params { 238 void* addr; 239 size_t size; 240 size_t alignment; 241 int32_t prot; 242 int32_t flags; 243 int32_t fd; 244 int64_t offset; 245 StringArgument name; 246}; 247 248struct SC_mremap_params { 249 void* old_address; 250 size_t old_size; 251 size_t new_size; 252 int32_t flags; 253}; 254 255struct SC_open_params { 256 int dirfd; 257 StringArgument path; 258 int options; 259 u16 mode; 260}; 261 262struct SC_poll_params { 263 struct pollfd* fds; 264 unsigned nfds; 265 const struct timespec* timeout; 266 u32 const* sigmask; 267}; 268 269struct SC_clock_nanosleep_params { 270 int clock_id; 271 int flags; 272 const struct timespec* requested_sleep; 273 struct timespec* remaining_sleep; 274}; 275 276struct SC_clock_getres_params { 277 int clock_id; 278 struct timespec* result; 279}; 280 281struct SC_accept4_params { 282 sockaddr* addr; 283 socklen_t* addrlen; 284 int sockfd; 285 int flags; 286}; 287 288struct SC_getsockopt_params { 289 int sockfd; 290 int level; 291 int option; 292 void* value; 293 socklen_t* value_size; 294}; 295 296struct SC_setsockopt_params { 297 void const* value; 298 int sockfd; 299 int level; 300 int option; 301 socklen_t value_size; 302}; 303 304struct SC_getsockname_params { 305 int sockfd; 306 sockaddr* addr; 307 socklen_t* addrlen; 308}; 309 310struct SC_getpeername_params { 311 int sockfd; 312 sockaddr* addr; 313 socklen_t* addrlen; 314}; 315 316struct SC_socketpair_params { 317 int domain; 318 int type; 319 int protocol; 320 int* sv; 321}; 322 323struct SC_futex_params { 324 u32* userspace_address; 325 int futex_op; 326 u32 val; 327 union { 328 timespec const* timeout; 329 uintptr_t val2; 330 }; 331 u32* userspace_address2; 332 u32 val3; 333}; 334 335struct SC_setkeymap_params { 336 u32 const* map; 337 u32 const* shift_map; 338 u32 const* alt_map; 339 u32 const* altgr_map; 340 u32 const* shift_altgr_map; 341 StringArgument map_name; 342}; 343 344struct SC_jail_create_params { 345 u64 index; 346 StringArgument name; 347}; 348 349struct SC_jail_attach_params { 350 u64 index; 351}; 352 353struct SC_getkeymap_params { 354 u32* map; 355 u32* shift_map; 356 u32* alt_map; 357 u32* altgr_map; 358 u32* shift_altgr_map; 359 MutableBufferArgument<char, size_t> map_name; 360}; 361 362struct SC_create_thread_params { 363 unsigned int detach_state = 0; // JOINABLE or DETACHED 364 int schedule_priority = 30; // THREAD_PRIORITY_NORMAL 365 // FIXME: Implement guard pages in create_thread (unreadable pages at "overflow" end of stack) 366 // "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE}, 367 // a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize 368 // parameter the guard size specified by the previous pthread_attr_setguardsize() function call" 369 // ... ok, if you say so posix. Guess we get to lie to people about guard page size 370 unsigned int guard_page_size = 0; // Rounded up to PAGE_SIZE 371 unsigned int reported_guard_page_size = 0; // The lie we tell callers 372 unsigned int stack_size = 1 * MiB; // Equal to Thread::default_userspace_stack_size 373 void* stack_location; // nullptr means any, o.w. process virtual address 374# if ARCH(X86_64) 375 FlatPtr rdi; 376 FlatPtr rsi; 377 FlatPtr rcx; 378 FlatPtr rdx; 379# endif 380}; 381 382struct SC_realpath_params { 383 StringArgument path; 384 MutableBufferArgument<char, size_t> buffer; 385}; 386 387struct SC_set_mmap_name_params { 388 void* addr; 389 size_t size; 390 StringArgument name; 391}; 392 393struct SC_execve_params { 394 StringArgument path; 395 StringListArgument arguments; 396 StringListArgument environment; 397}; 398 399struct SC_readlink_params { 400 StringArgument path; 401 MutableBufferArgument<char, size_t> buffer; 402 int dirfd; 403}; 404 405struct SC_link_params { 406 StringArgument old_path; 407 StringArgument new_path; 408}; 409 410struct SC_chown_params { 411 StringArgument path; 412 u32 uid; 413 u32 gid; 414 int dirfd; 415 int follow_symlinks; 416}; 417 418struct SC_mknod_params { 419 StringArgument path; 420 u16 mode; 421 u32 dev; 422}; 423 424struct SC_symlink_params { 425 StringArgument target; 426 StringArgument linkpath; 427 int dirfd; 428}; 429 430struct SC_rename_params { 431 int olddirfd; 432 StringArgument old_path; 433 int newdirfd; 434 StringArgument new_path; 435}; 436 437struct SC_mount_params { 438 StringArgument target; 439 StringArgument fs_type; 440 int source_fd; 441 int flags; 442}; 443 444struct SC_pledge_params { 445 StringArgument promises; 446 StringArgument execpromises; 447}; 448 449struct SC_unveil_params { 450 int flags; 451 StringArgument path; 452 StringArgument permissions; 453}; 454 455struct SC_utimensat_params { 456 int dirfd; 457 StringArgument path; 458 struct timespec const* times; 459 int flag; 460}; 461 462struct SC_waitid_params { 463 int idtype; 464 int id; 465 struct siginfo* infop; 466 int options; 467}; 468 469struct SC_stat_params { 470 StringArgument path; 471 struct stat* statbuf; 472 int dirfd; 473 int follow_symlinks; 474}; 475 476struct SC_ptrace_buf_params { 477 MutableBufferArgument<u8, size_t> buf; 478}; 479 480struct SC_ptrace_params { 481 int request; 482 pid_t tid; 483 void* addr; 484 FlatPtr data; 485}; 486 487struct SC_set_coredump_metadata_params { 488 StringArgument key; 489 StringArgument value; 490}; 491 492struct SC_inode_watcher_add_watch_params { 493 StringArgument user_path; 494 int fd; 495 u32 event_mask; 496}; 497 498struct SC_statvfs_params { 499 StringArgument path; 500 struct statvfs* buf; 501}; 502 503struct SC_chmod_params { 504 int dirfd; 505 StringArgument path; 506 u16 mode; 507 int follow_symlinks; 508}; 509 510enum class SchedulerParametersMode : bool { 511 Process, 512 Thread, 513}; 514 515struct SC_scheduler_parameters_params { 516 pid_t pid_or_tid; 517 SchedulerParametersMode mode; 518 struct sched_param parameters; 519}; 520 521struct SC_faccessat_params { 522 int dirfd; 523 StringArgument pathname; 524 int mode; 525 int flags; 526}; 527 528void initialize(); 529int sync(); 530 531# if ARCH(X86_64) || ARCH(AARCH64) 532inline uintptr_t invoke(Function function) 533{ 534 uintptr_t result; 535# if ARCH(X86_64) 536 asm volatile("syscall" 537 : "=a"(result) 538 : "a"(function) 539 : "rcx", "r11", "memory"); 540# elif ARCH(AARCH64) 541 register uintptr_t x0 asm("x0"); 542 register uintptr_t x8 asm("x8") = function; 543 asm volatile("svc #0" 544 : "=r"(x0) 545 : "r"(x8) 546 : "memory"); 547 result = x0; 548# endif 549 return result; 550} 551 552template<typename T1> 553inline uintptr_t invoke(Function function, T1 arg1) 554{ 555 uintptr_t result; 556# if ARCH(X86_64) 557 asm volatile("syscall" 558 : "=a"(result) 559 : "a"(function), "d"((uintptr_t)arg1) 560 : "rcx", "r11", "memory"); 561# elif ARCH(AARCH64) 562 register uintptr_t x0 asm("x0"); 563 register uintptr_t x1 asm("x1") = arg1; 564 register uintptr_t x8 asm("x8") = function; 565 asm volatile("svc #0" 566 : "=r"(x0) 567 : "r"(x1), "r"(x8) 568 : "memory"); 569 result = x0; 570# endif 571 return result; 572} 573 574template<typename T1, typename T2> 575inline uintptr_t invoke(Function function, T1 arg1, T2 arg2) 576{ 577 uintptr_t result; 578# if ARCH(X86_64) 579 asm volatile("syscall" 580 : "=a"(result) 581 : "a"(function), "d"((uintptr_t)arg1), "D"((uintptr_t)arg2) 582 : "rcx", "r11", "memory"); 583# elif ARCH(AARCH64) 584 register uintptr_t x0 asm("x0"); 585 register uintptr_t x1 asm("x1") = arg1; 586 register uintptr_t x2 asm("x2") = arg2; 587 register uintptr_t x8 asm("x8") = function; 588 asm volatile("svc #0" 589 : "=r"(x0) 590 : "r"(x1), "r"(x2), "r"(x8) 591 : "memory"); 592 result = x0; 593# endif 594 return result; 595} 596 597template<typename T1, typename T2, typename T3> 598inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3) 599{ 600 uintptr_t result; 601# if ARCH(X86_64) 602 asm volatile("syscall" 603 : "=a"(result) 604 : "a"(function), "d"((uintptr_t)arg1), "D"((uintptr_t)arg2), "b"((uintptr_t)arg3) 605 : "rcx", "r11", "memory"); 606# elif ARCH(AARCH64) 607 register uintptr_t x0 asm("x0"); 608 register uintptr_t x1 asm("x1") = arg1; 609 register uintptr_t x2 asm("x2") = arg2; 610 register uintptr_t x3 asm("x3") = arg3; 611 register uintptr_t x8 asm("x8") = function; 612 asm volatile("svc #0" 613 : "=r"(x0) 614 : "r"(x1), "r"(x2), "r"(x3), "r"(x8) 615 : "memory"); 616 result = x0; 617# endif 618 return result; 619} 620 621template<typename T1, typename T2, typename T3, typename T4> 622inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3, T4 arg4) 623{ 624 uintptr_t result; 625# if ARCH(X86_64) 626 asm volatile("syscall" 627 : "=a"(result) 628 : "a"(function), "d"((uintptr_t)arg1), "D"((uintptr_t)arg2), "b"((uintptr_t)arg3), "S"((uintptr_t)arg4) 629 : "memory"); 630# elif ARCH(AARCH64) 631 register uintptr_t x0 asm("x0"); 632 register uintptr_t x1 asm("x1") = arg1; 633 register uintptr_t x2 asm("x2") = arg2; 634 register uintptr_t x3 asm("x3") = arg3; 635 register uintptr_t x4 asm("x4") = arg4; 636 register uintptr_t x8 asm("x8") = function; 637 asm volatile("svc #0" 638 : "=r"(x0) 639 : "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x8) 640 : "memory"); 641 result = x0; 642# endif 643 return result; 644} 645# endif 646#endif 647 648} 649 650#undef __ENUMERATE_SYSCALL 651#define __ENUMERATE_SYSCALL(sys_call, needs_lock) using Syscall::SC_##sys_call; 652ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL) 653#undef __ENUMERATE_SYSCALL 654 655} 656 657using namespace Kernel;