summary refs log tree commit diff
path: root/ripple/website
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2021-12-27 20:41:43 +0000
committeredef <edef@unfathomable.blue>2021-12-27 20:41:43 +0000
commit977730017ce27275b71d29dfa88e98ca4db21dcd (patch)
treed55ba103b2730eadee7792a74084029a7a55794d /ripple/website
parent97a37b1baa49fcfe683c466c7ae711c46f0fc121 (diff)
ripple/website/pages/syscalls: document the syscalls we need to support for our MVP
Change-Id: I651816d004ee5c5049569ddcf157d492cbcc0b2a
Diffstat (limited to 'ripple/website')
-rw-r--r--ripple/website/pages/syscalls.adoc174
1 files changed, 174 insertions, 0 deletions
diff --git a/ripple/website/pages/syscalls.adoc b/ripple/website/pages/syscalls.adoc
new file mode 100644
index 0000000..5b1cf69
--- /dev/null
+++ b/ripple/website/pages/syscalls.adoc
@@ -0,0 +1,174 @@
+= TODO
+
+These have various sub-cases that vary significantly in complexity.
+
+== mmap
+
+== mprotect
+
+== munmap
+
+= Trivial
+
+== arch_prctl(ARCH_SET_FS, ptr)
+
+This is just `SETFS`.
+Safe to pass through, but also trivial to implement.
+
+== ioctl(fd, TCGETS, …)
+
+gcc likes doing these on various fds, but `return -ENOTTY;` is enough of an implementation.
+
+== close(fd)
+
+Close a file descriptor.
+
+== getrusage(RUSAGE_SELF, ptr)
+
+gcc is rather eager to know how long it's taking.
+We can probably stub this out safely.
+
+== sysinfo(ptr)
+
+I'm honestly not sure why gcc reads this, but we can probably stub it out.
+
+== umask(mask)
+
+Thread-unsafe, but we should probably bail if this gets invoked while multithreaded.
+We just `mode &= ~mask` any filesystem call, and that's the only place this matters.
+
+== prlimit(0, resource, NULL, ptr)
+
+Retrieve a resource limit.
+We can stub all of these out.
+
+=== prlimit64(0, RLIMIT_STACK, NULL, ptr)
+
+Retrieve the maximum stack size, presumably specifically of the main thread.
+
+=== prlimit64(0, RLIMIT_AS, NULL, ptr)
+
+Retrieve the maximum virtual memory size.
+
+=== prlimit64(0, RLIMIT_RSS, NULL, ptr)
+
+The maximum amount of resident memory.
+
+=== prlimit64(0, RLIMIT_NOFILE, NULL, ptr)
+
+The maximum amount of file descriptors.
+
+= Easy
+
+== brk
+
+Should be fairly trivial.
+`validate_prctl_map_addr` documents the requirements on address space layout.
+
+== exit_group(status)
+
+Kill the process, aka thread group.
+Straightforward enough, although we do need to emit `SIGCHLD` appropriately.
+
+== fcntl(fd, F_GETFD)
+
+Grab the current flags for an fd.
+Used only immediately preceding `fcntl(fd, F_SETFD, FD_CLOEXEC)`.
+
+== fcntl(fd, F_SETFD, FD_CLOEXEC)
+
+Set the `CLOEXEC` flag.
+
+= This is where they start to trick you
+
+== set_robust_list
+
+The code for this itself isn't complex (we just store a pointer), but we have to actually do futex signalling on process death and execve.
+Technically trivial if `futex` is never called.
+
+== set_tid_address
+The code for this itself isn't complex (we just store a pointer), but we have to actually do futex signalling on thread termination.
+Technically trivial if `futex` is never called.
+
+== getcwd(buf, len)
+
+Read the current working directory path into a buffer.
+Equivalent to `readlink("/proc/self/cwd", buf, len)`.
+Probably bail if anything funny happens.
+
+== readlink(path, buf, len)
+
+Read the target of a symlink.
+
+== unlink(path)
+
+Remove a directory entry that is itself not a directory.
+Equivalent to `unlinkat(AT_FDCWD, path, 0)`.
+
+== chmod(path, mode)
+
+Change the mode of an inode.
+
+== pipe2(fds_out, flags)
+
+Technically easy, but almost certainly being invoked for imminent IPC.
+
+== read(fd, ptr, len)
+
+Read bytes from a file descriptor.
+Hard if it's IPC, easier if it's filesystem I/O.
+
+== lseek(fd, offset, SEEK_SET)
+
+Reposition the file offset, relative to the start of the file.
+
+== lseek(fd, offset, SEEK_CUR)
+
+Reposition the file offset, relative to the current offset.
+
+== pread64(fd, buf, len, offset)
+
+Equivalent to atomic `lseek(fd, offset, SEEK_SET); read(fd, buf, len)`, but without the side effects on the file descriptor offset.
+
+== write(fd, ptr, len)
+
+Write bytes to a file descriptor.
+Hard if it's IPC, easier if it's filesystem I/O.
+
+== execve(pathname, argv, envp)
+
+Replace the current process image with another, loaded from a file.
+Technically easy, modulo `O_CLOEXEC` handling, but almost certainly spells imminent IPC.
+
+== access(path, mode)
+
+Equivalent to atomic `int fd = open(path, mode); if (fd >= 0) close(fd);`, except if `eugid != ugid`.
+Build systems are rarely setuid, so this distinction seems ok to bail on.
+
+== openat(AT_FDCWD, path, flags, mode)
+
+Filesystem I/O.
+
+= This one's hard
+
+== newfstatat(dirfd, name, stat_out, flag)
+
+Filesystem I/O, primarily complicated by mtime and inode numbers.
+
+== vfork()
+
+Strictly less troubling than fork, but this spells imminent IPC.
+
+== wait4(wstatus, 0, NULL)
+
+Pure IPC.
+This probably isn't much trouble if nothing unusual happens, however.
+
+== rt_sigaction
+
+Signals are complicated, underspecified, *and* IPC.
+This is going to hurt.
+
+== rt_sigprocmask
+
+Signal mask manipulation is a doozy, but unblocking signals can deliver queued signals…