Serenity Operating System
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;