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
35extern "C" {
36struct timeval;
37struct timespec;
38struct sockaddr;
39struct siginfo;
40typedef u32 socklen_t;
41}
42
43namespace Kernel {
44
45#define ENUMERATE_SYSCALLS \
46 __ENUMERATE_SYSCALL(sleep) \
47 __ENUMERATE_SYSCALL(yield) \
48 __ENUMERATE_SYSCALL(open) \
49 __ENUMERATE_SYSCALL(close) \
50 __ENUMERATE_SYSCALL(read) \
51 __ENUMERATE_SYSCALL(lseek) \
52 __ENUMERATE_SYSCALL(kill) \
53 __ENUMERATE_SYSCALL(getuid) \
54 __ENUMERATE_SYSCALL(exit) \
55 __ENUMERATE_SYSCALL(getgid) \
56 __ENUMERATE_SYSCALL(getpid) \
57 __ENUMERATE_SYSCALL(waitid) \
58 __ENUMERATE_SYSCALL(mmap) \
59 __ENUMERATE_SYSCALL(munmap) \
60 __ENUMERATE_SYSCALL(get_dir_entries) \
61 __ENUMERATE_SYSCALL(getcwd) \
62 __ENUMERATE_SYSCALL(gettimeofday) \
63 __ENUMERATE_SYSCALL(gethostname) \
64 __ENUMERATE_SYSCALL(chdir) \
65 __ENUMERATE_SYSCALL(uname) \
66 __ENUMERATE_SYSCALL(set_mmap_name) \
67 __ENUMERATE_SYSCALL(readlink) \
68 __ENUMERATE_SYSCALL(write) \
69 __ENUMERATE_SYSCALL(ttyname_r) \
70 __ENUMERATE_SYSCALL(stat) \
71 __ENUMERATE_SYSCALL(getsid) \
72 __ENUMERATE_SYSCALL(setsid) \
73 __ENUMERATE_SYSCALL(getpgid) \
74 __ENUMERATE_SYSCALL(setpgid) \
75 __ENUMERATE_SYSCALL(getpgrp) \
76 __ENUMERATE_SYSCALL(fork) \
77 __ENUMERATE_SYSCALL(execve) \
78 __ENUMERATE_SYSCALL(geteuid) \
79 __ENUMERATE_SYSCALL(getegid) \
80 __ENUMERATE_SYSCALL(getdtablesize) \
81 __ENUMERATE_SYSCALL(dup) \
82 __ENUMERATE_SYSCALL(dup2) \
83 __ENUMERATE_SYSCALL(sigaction) \
84 __ENUMERATE_SYSCALL(getppid) \
85 __ENUMERATE_SYSCALL(umask) \
86 __ENUMERATE_SYSCALL(getgroups) \
87 __ENUMERATE_SYSCALL(setgroups) \
88 __ENUMERATE_SYSCALL(sigreturn) \
89 __ENUMERATE_SYSCALL(sigprocmask) \
90 __ENUMERATE_SYSCALL(sigpending) \
91 __ENUMERATE_SYSCALL(pipe) \
92 __ENUMERATE_SYSCALL(killpg) \
93 __ENUMERATE_SYSCALL(setuid) \
94 __ENUMERATE_SYSCALL(setgid) \
95 __ENUMERATE_SYSCALL(alarm) \
96 __ENUMERATE_SYSCALL(fstat) \
97 __ENUMERATE_SYSCALL(access) \
98 __ENUMERATE_SYSCALL(fcntl) \
99 __ENUMERATE_SYSCALL(ioctl) \
100 __ENUMERATE_SYSCALL(mkdir) \
101 __ENUMERATE_SYSCALL(times) \
102 __ENUMERATE_SYSCALL(utime) \
103 __ENUMERATE_SYSCALL(sync) \
104 __ENUMERATE_SYSCALL(ptsname_r) \
105 __ENUMERATE_SYSCALL(select) \
106 __ENUMERATE_SYSCALL(unlink) \
107 __ENUMERATE_SYSCALL(poll) \
108 __ENUMERATE_SYSCALL(rmdir) \
109 __ENUMERATE_SYSCALL(chmod) \
110 __ENUMERATE_SYSCALL(usleep) \
111 __ENUMERATE_SYSCALL(socket) \
112 __ENUMERATE_SYSCALL(bind) \
113 __ENUMERATE_SYSCALL(accept) \
114 __ENUMERATE_SYSCALL(listen) \
115 __ENUMERATE_SYSCALL(connect) \
116 __ENUMERATE_SYSCALL(create_shared_buffer) \
117 __ENUMERATE_SYSCALL(share_buffer_with) \
118 __ENUMERATE_SYSCALL(get_shared_buffer) \
119 __ENUMERATE_SYSCALL(release_shared_buffer) \
120 __ENUMERATE_SYSCALL(link) \
121 __ENUMERATE_SYSCALL(chown) \
122 __ENUMERATE_SYSCALL(fchmod) \
123 __ENUMERATE_SYSCALL(symlink) \
124 __ENUMERATE_SYSCALL(get_shared_buffer_size) \
125 __ENUMERATE_SYSCALL(seal_shared_buffer) \
126 __ENUMERATE_SYSCALL(sendto) \
127 __ENUMERATE_SYSCALL(recvfrom) \
128 __ENUMERATE_SYSCALL(getsockopt) \
129 __ENUMERATE_SYSCALL(setsockopt) \
130 __ENUMERATE_SYSCALL(create_thread) \
131 __ENUMERATE_SYSCALL(gettid) \
132 __ENUMERATE_SYSCALL(donate) \
133 __ENUMERATE_SYSCALL(rename) \
134 __ENUMERATE_SYSCALL(ftruncate) \
135 __ENUMERATE_SYSCALL(systrace) \
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(share_buffer_globally) \
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_nanosleep) \
163 __ENUMERATE_SYSCALL(join_thread) \
164 __ENUMERATE_SYSCALL(module_load) \
165 __ENUMERATE_SYSCALL(module_unload) \
166 __ENUMERATE_SYSCALL(detach_thread) \
167 __ENUMERATE_SYSCALL(set_thread_name) \
168 __ENUMERATE_SYSCALL(get_thread_name) \
169 __ENUMERATE_SYSCALL(madvise) \
170 __ENUMERATE_SYSCALL(purge) \
171 __ENUMERATE_SYSCALL(set_shared_buffer_volatile) \
172 __ENUMERATE_SYSCALL(profiling_enable) \
173 __ENUMERATE_SYSCALL(profiling_disable) \
174 __ENUMERATE_SYSCALL(get_kernel_info_page) \
175 __ENUMERATE_SYSCALL(futex) \
176 __ENUMERATE_SYSCALL(set_thread_boost) \
177 __ENUMERATE_SYSCALL(set_process_boost) \
178 __ENUMERATE_SYSCALL(chroot) \
179 __ENUMERATE_SYSCALL(pledge) \
180 __ENUMERATE_SYSCALL(unveil) \
181 __ENUMERATE_SYSCALL(perf_event) \
182 __ENUMERATE_SYSCALL(shutdown)
183
184namespace Syscall {
185
186enum Function {
187#undef __ENUMERATE_SYSCALL
188#undef __ENUMERATE_REMOVED_SYSCALL
189#define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x,
190#define __ENUMERATE_SYSCALL(x) SC_##x,
191 ENUMERATE_SYSCALLS
192#undef __ENUMERATE_SYSCALL
193#undef __ENUMERATE_REMOVED_SYSCALL
194 __Count
195};
196
197inline constexpr const char* to_string(Function function)
198{
199 switch (function) {
200#undef __ENUMERATE_SYSCALL
201#undef __ENUMERATE_REMOVED_SYSCALL
202#define __ENUMERATE_REMOVED_SYSCALL(x) \
203 case SC_##x: \
204 return #x " (removed)";
205#define __ENUMERATE_SYSCALL(x) \
206 case SC_##x: \
207 return #x;
208 ENUMERATE_SYSCALLS
209#undef __ENUMERATE_SYSCALL
210#undef __ENUMERATE_REMOVED_SYSCALL
211 default:
212 break;
213 }
214 return "Unknown";
215}
216
217#ifdef __serenity__
218struct StringArgument {
219 const char* characters { nullptr };
220 size_t length { 0 };
221};
222
223template<typename DataType, typename SizeType>
224struct MutableBufferArgument {
225 DataType* data { nullptr };
226 SizeType size { 0 };
227};
228
229template<typename DataType, typename SizeType>
230struct ImmutableBufferArgument {
231 const DataType* data { nullptr };
232 SizeType size { 0 };
233};
234
235struct StringListArgument {
236 StringArgument* strings { nullptr };
237 size_t length { 0 };
238};
239
240struct SC_mmap_params {
241 uint32_t addr;
242 uint32_t size;
243 uint32_t alignment;
244 int32_t prot;
245 int32_t flags;
246 int32_t fd;
247 int32_t offset; // FIXME: 64-bit off_t?
248 StringArgument name;
249};
250
251struct SC_open_params {
252 int dirfd;
253 StringArgument path;
254 int options;
255 u16 mode;
256};
257
258struct SC_select_params {
259 int nfds;
260 fd_set* readfds;
261 fd_set* writefds;
262 fd_set* exceptfds;
263 struct timeval* timeout;
264};
265
266struct SC_clock_nanosleep_params {
267 int clock_id;
268 int flags;
269 const struct timespec* requested_sleep;
270 struct timespec* remaining_sleep;
271};
272
273struct SC_sendto_params {
274 int sockfd;
275 ImmutableBufferArgument<void, size_t> data;
276 int flags;
277 const sockaddr* addr;
278 socklen_t addr_length;
279};
280
281struct SC_recvfrom_params {
282 int sockfd;
283 MutableBufferArgument<void, size_t> buffer;
284 int flags;
285 sockaddr* addr;
286 socklen_t* addr_length;
287};
288
289struct SC_getsockopt_params {
290 int sockfd;
291 int level;
292 int option;
293 void* value;
294 socklen_t* value_size;
295};
296
297struct SC_setsockopt_params {
298 int sockfd;
299 int level;
300 int option;
301 const void* value;
302 socklen_t value_size;
303};
304
305struct SC_getsockname_params {
306 int sockfd;
307 sockaddr* addr;
308 socklen_t* addrlen;
309};
310
311struct SC_getpeername_params {
312 int sockfd;
313 sockaddr* addr;
314 socklen_t* addrlen;
315};
316
317struct SC_futex_params {
318 i32* userspace_address;
319 int futex_op;
320 i32 val;
321 const timespec* timeout;
322};
323
324struct SC_setkeymap_params {
325 const char* map;
326 const char* shift_map;
327 const char* alt_map;
328 const char* altgr_map;
329};
330
331struct SC_create_thread_params {
332 unsigned int m_detach_state = 0; // JOINABLE or DETACHED
333 int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL
334 // FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
335 // "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
336 // a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
337 // parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
338 // ... ok, if you say so posix. Guess we get to lie to people about guard page size
339 unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
340 unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
341 unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
342 void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
343};
344
345struct SC_realpath_params {
346 StringArgument path;
347 MutableBufferArgument<char, size_t> buffer;
348};
349
350struct SC_set_mmap_name_params {
351 void* addr;
352 size_t size;
353 StringArgument name;
354};
355
356struct SC_execve_params {
357 StringArgument path;
358 StringListArgument arguments;
359 StringListArgument environment;
360};
361
362struct SC_readlink_params {
363 StringArgument path;
364 MutableBufferArgument<char, size_t> buffer;
365};
366
367struct SC_link_params {
368 StringArgument old_path;
369 StringArgument new_path;
370};
371
372struct SC_chown_params {
373 StringArgument path;
374 u32 uid;
375 u32 gid;
376};
377
378struct SC_mknod_params {
379 StringArgument path;
380 u16 mode;
381 u32 dev;
382};
383
384struct SC_symlink_params {
385 StringArgument target;
386 StringArgument linkpath;
387};
388
389struct SC_rename_params {
390 StringArgument old_path;
391 StringArgument new_path;
392};
393
394struct SC_mount_params {
395 StringArgument source;
396 StringArgument target;
397 StringArgument fs_type;
398 int flags;
399};
400
401struct SC_pledge_params {
402 StringArgument promises;
403 StringArgument execpromises;
404};
405
406struct SC_unveil_params {
407 StringArgument path;
408 StringArgument permissions;
409};
410
411struct SC_waitid_params {
412 int idtype;
413 int id;
414 struct siginfo* infop;
415 int options;
416};
417
418struct SC_stat_params {
419 StringArgument path;
420 struct stat* statbuf;
421 bool follow_symlinks;
422};
423
424void initialize();
425int sync();
426
427inline u32 invoke(Function function)
428{
429 u32 result;
430 asm volatile("int $0x82"
431 : "=a"(result)
432 : "a"(function)
433 : "memory");
434 return result;
435}
436
437template<typename T1>
438inline u32 invoke(Function function, T1 arg1)
439{
440 u32 result;
441 asm volatile("int $0x82"
442 : "=a"(result)
443 : "a"(function), "d"((u32)arg1)
444 : "memory");
445 return result;
446}
447
448template<typename T1, typename T2>
449inline u32 invoke(Function function, T1 arg1, T2 arg2)
450{
451 u32 result;
452 asm volatile("int $0x82"
453 : "=a"(result)
454 : "a"(function), "d"((u32)arg1), "c"((u32)arg2)
455 : "memory");
456 return result;
457}
458
459template<typename T1, typename T2, typename T3>
460inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
461{
462 u32 result;
463 asm volatile("int $0x82"
464 : "=a"(result)
465 : "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3)
466 : "memory");
467 return result;
468}
469#endif
470
471}
472
473#undef __ENUMERATE_SYSCALL
474#define __ENUMERATE_SYSCALL(x) using Syscall::SC_##x;
475#define __ENUMERATE_REMOVED_SYSCALL(x)
476ENUMERATE_SYSCALLS
477#undef __ENUMERATE_SYSCALL
478#undef __ENUMERATE_REMOVED_SYSCALL
479#define syscall Syscall::invoke
480
481}
482
483using namespace Kernel;