Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/Types.h>
30
31#ifdef __serenity__
32# include <LibC/fd_set.h>
33#endif
34
35constexpr int syscall_vector = 0x82;
36
37extern "C" {
38struct timeval;
39struct timespec;
40struct sockaddr;
41struct siginfo;
42typedef u32 socklen_t;
43}
44
45namespace Kernel {
46
47#define ENUMERATE_SYSCALLS \
48 __ENUMERATE_SYSCALL(sleep) \
49 __ENUMERATE_SYSCALL(yield) \
50 __ENUMERATE_SYSCALL(open) \
51 __ENUMERATE_SYSCALL(close) \
52 __ENUMERATE_SYSCALL(read) \
53 __ENUMERATE_SYSCALL(lseek) \
54 __ENUMERATE_SYSCALL(kill) \
55 __ENUMERATE_SYSCALL(getuid) \
56 __ENUMERATE_SYSCALL(exit) \
57 __ENUMERATE_SYSCALL(getgid) \
58 __ENUMERATE_SYSCALL(getpid) \
59 __ENUMERATE_SYSCALL(waitid) \
60 __ENUMERATE_SYSCALL(mmap) \
61 __ENUMERATE_SYSCALL(munmap) \
62 __ENUMERATE_SYSCALL(get_dir_entries) \
63 __ENUMERATE_SYSCALL(getcwd) \
64 __ENUMERATE_SYSCALL(gettimeofday) \
65 __ENUMERATE_SYSCALL(gethostname) \
66 __ENUMERATE_SYSCALL(chdir) \
67 __ENUMERATE_SYSCALL(uname) \
68 __ENUMERATE_SYSCALL(set_mmap_name) \
69 __ENUMERATE_SYSCALL(readlink) \
70 __ENUMERATE_SYSCALL(write) \
71 __ENUMERATE_SYSCALL(ttyname_r) \
72 __ENUMERATE_SYSCALL(stat) \
73 __ENUMERATE_SYSCALL(getsid) \
74 __ENUMERATE_SYSCALL(setsid) \
75 __ENUMERATE_SYSCALL(getpgid) \
76 __ENUMERATE_SYSCALL(setpgid) \
77 __ENUMERATE_SYSCALL(getpgrp) \
78 __ENUMERATE_SYSCALL(fork) \
79 __ENUMERATE_SYSCALL(execve) \
80 __ENUMERATE_SYSCALL(geteuid) \
81 __ENUMERATE_SYSCALL(getegid) \
82 __ENUMERATE_SYSCALL(getdtablesize) \
83 __ENUMERATE_SYSCALL(dup) \
84 __ENUMERATE_SYSCALL(dup2) \
85 __ENUMERATE_SYSCALL(sigaction) \
86 __ENUMERATE_SYSCALL(getppid) \
87 __ENUMERATE_SYSCALL(umask) \
88 __ENUMERATE_SYSCALL(getgroups) \
89 __ENUMERATE_SYSCALL(setgroups) \
90 __ENUMERATE_SYSCALL(sigreturn) \
91 __ENUMERATE_SYSCALL(sigprocmask) \
92 __ENUMERATE_SYSCALL(sigpending) \
93 __ENUMERATE_SYSCALL(pipe) \
94 __ENUMERATE_SYSCALL(killpg) \
95 __ENUMERATE_SYSCALL(setuid) \
96 __ENUMERATE_SYSCALL(setgid) \
97 __ENUMERATE_SYSCALL(alarm) \
98 __ENUMERATE_SYSCALL(fstat) \
99 __ENUMERATE_SYSCALL(access) \
100 __ENUMERATE_SYSCALL(fcntl) \
101 __ENUMERATE_SYSCALL(ioctl) \
102 __ENUMERATE_SYSCALL(mkdir) \
103 __ENUMERATE_SYSCALL(times) \
104 __ENUMERATE_SYSCALL(utime) \
105 __ENUMERATE_SYSCALL(sync) \
106 __ENUMERATE_SYSCALL(ptsname_r) \
107 __ENUMERATE_SYSCALL(select) \
108 __ENUMERATE_SYSCALL(unlink) \
109 __ENUMERATE_SYSCALL(poll) \
110 __ENUMERATE_SYSCALL(rmdir) \
111 __ENUMERATE_SYSCALL(chmod) \
112 __ENUMERATE_SYSCALL(usleep) \
113 __ENUMERATE_SYSCALL(socket) \
114 __ENUMERATE_SYSCALL(bind) \
115 __ENUMERATE_SYSCALL(accept) \
116 __ENUMERATE_SYSCALL(listen) \
117 __ENUMERATE_SYSCALL(connect) \
118 __ENUMERATE_SYSCALL(shbuf_create) \
119 __ENUMERATE_SYSCALL(shbuf_allow_pid) \
120 __ENUMERATE_SYSCALL(shbuf_get) \
121 __ENUMERATE_SYSCALL(shbuf_release) \
122 __ENUMERATE_SYSCALL(link) \
123 __ENUMERATE_SYSCALL(chown) \
124 __ENUMERATE_SYSCALL(fchmod) \
125 __ENUMERATE_SYSCALL(symlink) \
126 __ENUMERATE_SYSCALL(shbuf_seal) \
127 __ENUMERATE_SYSCALL(sendto) \
128 __ENUMERATE_SYSCALL(recvfrom) \
129 __ENUMERATE_SYSCALL(getsockopt) \
130 __ENUMERATE_SYSCALL(setsockopt) \
131 __ENUMERATE_SYSCALL(create_thread) \
132 __ENUMERATE_SYSCALL(gettid) \
133 __ENUMERATE_SYSCALL(donate) \
134 __ENUMERATE_SYSCALL(rename) \
135 __ENUMERATE_SYSCALL(ftruncate) \
136 __ENUMERATE_SYSCALL(exit_thread) \
137 __ENUMERATE_SYSCALL(mknod) \
138 __ENUMERATE_SYSCALL(writev) \
139 __ENUMERATE_SYSCALL(beep) \
140 __ENUMERATE_SYSCALL(getsockname) \
141 __ENUMERATE_SYSCALL(getpeername) \
142 __ENUMERATE_SYSCALL(sched_setparam) \
143 __ENUMERATE_SYSCALL(sched_getparam) \
144 __ENUMERATE_SYSCALL(fchown) \
145 __ENUMERATE_SYSCALL(halt) \
146 __ENUMERATE_SYSCALL(reboot) \
147 __ENUMERATE_SYSCALL(mount) \
148 __ENUMERATE_SYSCALL(umount) \
149 __ENUMERATE_SYSCALL(dump_backtrace) \
150 __ENUMERATE_SYSCALL(dbgputch) \
151 __ENUMERATE_SYSCALL(dbgputstr) \
152 __ENUMERATE_SYSCALL(watch_file) \
153 __ENUMERATE_SYSCALL(shbuf_allow_all) \
154 __ENUMERATE_SYSCALL(set_process_icon) \
155 __ENUMERATE_SYSCALL(mprotect) \
156 __ENUMERATE_SYSCALL(realpath) \
157 __ENUMERATE_SYSCALL(get_process_name) \
158 __ENUMERATE_SYSCALL(fchdir) \
159 __ENUMERATE_SYSCALL(getrandom) \
160 __ENUMERATE_SYSCALL(setkeymap) \
161 __ENUMERATE_SYSCALL(clock_gettime) \
162 __ENUMERATE_SYSCALL(clock_settime) \
163 __ENUMERATE_SYSCALL(clock_nanosleep) \
164 __ENUMERATE_SYSCALL(join_thread) \
165 __ENUMERATE_SYSCALL(module_load) \
166 __ENUMERATE_SYSCALL(module_unload) \
167 __ENUMERATE_SYSCALL(detach_thread) \
168 __ENUMERATE_SYSCALL(set_thread_name) \
169 __ENUMERATE_SYSCALL(get_thread_name) \
170 __ENUMERATE_SYSCALL(madvise) \
171 __ENUMERATE_SYSCALL(purge) \
172 __ENUMERATE_SYSCALL(shbuf_set_volatile) \
173 __ENUMERATE_SYSCALL(profiling_enable) \
174 __ENUMERATE_SYSCALL(profiling_disable) \
175 __ENUMERATE_SYSCALL(get_kernel_info_page) \
176 __ENUMERATE_SYSCALL(futex) \
177 __ENUMERATE_SYSCALL(set_thread_boost) \
178 __ENUMERATE_SYSCALL(set_process_boost) \
179 __ENUMERATE_SYSCALL(chroot) \
180 __ENUMERATE_SYSCALL(pledge) \
181 __ENUMERATE_SYSCALL(unveil) \
182 __ENUMERATE_SYSCALL(perf_event) \
183 __ENUMERATE_SYSCALL(shutdown) \
184 __ENUMERATE_SYSCALL(get_stack_bounds) \
185 __ENUMERATE_SYSCALL(ptrace)
186
187namespace Syscall {
188
189enum Function {
190#undef __ENUMERATE_SYSCALL
191#undef __ENUMERATE_REMOVED_SYSCALL
192#define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x,
193#define __ENUMERATE_SYSCALL(x) SC_##x,
194 ENUMERATE_SYSCALLS
195#undef __ENUMERATE_SYSCALL
196#undef __ENUMERATE_REMOVED_SYSCALL
197 __Count
198};
199
200inline constexpr const char* to_string(Function function)
201{
202 switch (function) {
203#undef __ENUMERATE_SYSCALL
204#undef __ENUMERATE_REMOVED_SYSCALL
205#define __ENUMERATE_REMOVED_SYSCALL(x) \
206 case SC_##x: \
207 return #x " (removed)";
208#define __ENUMERATE_SYSCALL(x) \
209 case SC_##x: \
210 return #x;
211 ENUMERATE_SYSCALLS
212#undef __ENUMERATE_SYSCALL
213#undef __ENUMERATE_REMOVED_SYSCALL
214 default:
215 break;
216 }
217 return "Unknown";
218}
219
220#ifdef __serenity__
221struct StringArgument {
222 const char* characters { nullptr };
223 size_t length { 0 };
224};
225
226template<typename DataType, typename SizeType>
227struct MutableBufferArgument {
228 DataType* data { nullptr };
229 SizeType size { 0 };
230};
231
232template<typename DataType, typename SizeType>
233struct ImmutableBufferArgument {
234 const DataType* data { nullptr };
235 SizeType size { 0 };
236};
237
238struct StringListArgument {
239 StringArgument* strings { nullptr };
240 size_t length { 0 };
241};
242
243struct SC_mmap_params {
244 uint32_t addr;
245 uint32_t size;
246 uint32_t alignment;
247 int32_t prot;
248 int32_t flags;
249 int32_t fd;
250 int32_t offset; // FIXME: 64-bit off_t?
251 StringArgument name;
252};
253
254struct SC_open_params {
255 int dirfd;
256 StringArgument path;
257 int options;
258 u16 mode;
259};
260
261struct SC_select_params {
262 int nfds;
263 fd_set* readfds;
264 fd_set* writefds;
265 fd_set* exceptfds;
266 struct timeval* timeout;
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_sendto_params {
277 int sockfd;
278 ImmutableBufferArgument<void, size_t> data;
279 int flags;
280 const sockaddr* addr;
281 socklen_t addr_length;
282};
283
284struct SC_recvfrom_params {
285 int sockfd;
286 MutableBufferArgument<void, size_t> buffer;
287 int flags;
288 sockaddr* addr;
289 socklen_t* addr_length;
290};
291
292struct SC_getsockopt_params {
293 int sockfd;
294 int level;
295 int option;
296 void* value;
297 socklen_t* value_size;
298};
299
300struct SC_setsockopt_params {
301 int sockfd;
302 int level;
303 int option;
304 const void* value;
305 socklen_t value_size;
306};
307
308struct SC_getsockname_params {
309 int sockfd;
310 sockaddr* addr;
311 socklen_t* addrlen;
312};
313
314struct SC_getpeername_params {
315 int sockfd;
316 sockaddr* addr;
317 socklen_t* addrlen;
318};
319
320struct SC_futex_params {
321 i32* userspace_address;
322 int futex_op;
323 i32 val;
324 const timespec* timeout;
325};
326
327struct SC_setkeymap_params {
328 const char* map;
329 const char* shift_map;
330 const char* alt_map;
331 const char* altgr_map;
332};
333
334struct SC_create_thread_params {
335 unsigned int m_detach_state = 0; // JOINABLE or DETACHED
336 int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL
337 // FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
338 // "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
339 // a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
340 // parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
341 // ... ok, if you say so posix. Guess we get to lie to people about guard page size
342 unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
343 unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
344 unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
345 void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
346};
347
348struct SC_realpath_params {
349 StringArgument path;
350 MutableBufferArgument<char, size_t> buffer;
351};
352
353struct SC_set_mmap_name_params {
354 void* addr;
355 size_t size;
356 StringArgument name;
357};
358
359struct SC_execve_params {
360 StringArgument path;
361 StringListArgument arguments;
362 StringListArgument environment;
363};
364
365struct SC_readlink_params {
366 StringArgument path;
367 MutableBufferArgument<char, size_t> buffer;
368};
369
370struct SC_link_params {
371 StringArgument old_path;
372 StringArgument new_path;
373};
374
375struct SC_chown_params {
376 StringArgument path;
377 u32 uid;
378 u32 gid;
379};
380
381struct SC_mknod_params {
382 StringArgument path;
383 u16 mode;
384 u32 dev;
385};
386
387struct SC_symlink_params {
388 StringArgument target;
389 StringArgument linkpath;
390};
391
392struct SC_rename_params {
393 StringArgument old_path;
394 StringArgument new_path;
395};
396
397struct SC_mount_params {
398 int source_fd;
399 StringArgument target;
400 StringArgument fs_type;
401 int flags;
402};
403
404struct SC_pledge_params {
405 StringArgument promises;
406 StringArgument execpromises;
407};
408
409struct SC_unveil_params {
410 StringArgument path;
411 StringArgument permissions;
412};
413
414struct SC_waitid_params {
415 int idtype;
416 int id;
417 struct siginfo* infop;
418 int options;
419};
420
421struct SC_stat_params {
422 StringArgument path;
423 struct stat* statbuf;
424 bool follow_symlinks;
425};
426
427struct SC_ptrace_params {
428 int request;
429 pid_t pid;
430 u8* addr;
431 int data;
432};
433
434void initialize();
435int sync();
436
437inline u32 invoke(Function function)
438{
439 u32 result;
440 asm volatile("int $0x82"
441 : "=a"(result)
442 : "a"(function)
443 : "memory");
444 return result;
445}
446
447template<typename T1>
448inline u32 invoke(Function function, T1 arg1)
449{
450 u32 result;
451 asm volatile("int $0x82"
452 : "=a"(result)
453 : "a"(function), "d"((u32)arg1)
454 : "memory");
455 return result;
456}
457
458template<typename T1, typename T2>
459inline u32 invoke(Function function, T1 arg1, T2 arg2)
460{
461 u32 result;
462 asm volatile("int $0x82"
463 : "=a"(result)
464 : "a"(function), "d"((u32)arg1), "c"((u32)arg2)
465 : "memory");
466 return result;
467}
468
469template<typename T1, typename T2, typename T3>
470inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
471{
472 u32 result;
473 asm volatile("int $0x82"
474 : "=a"(result)
475 : "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3)
476 : "memory");
477 return result;
478}
479#endif
480
481}
482
483#undef __ENUMERATE_SYSCALL
484#define __ENUMERATE_SYSCALL(x) using Syscall::SC_##x;
485#define __ENUMERATE_REMOVED_SYSCALL(x)
486ENUMERATE_SYSCALLS
487#undef __ENUMERATE_SYSCALL
488#undef __ENUMERATE_REMOVED_SYSCALL
489#define syscall Syscall::invoke
490
491}
492
493using namespace Kernel;