-
Notifications
You must be signed in to change notification settings - Fork 21
Translation of system calls
imlk edited this page Aug 23, 2021
·
1 revision
System call translation is the most important and complex part of proot-rs. This is because it can easily introduce bugs or behave inconsistently with the kernel.
We use unit tests and test_with_proot()
to test if these system calls work correctly.
The following table describes the current state of translation of system calls. These system calls are organized by SyscallGroup
, and system calls in the same SyscallGroup
usually imply similar processing.
SyscallGroup | Syscall | Status | UnitTest Covered | Remarks |
---|---|---|---|---|
Execve | execve | ✅ | ✅ | |
Ptrace | ptrace | ❌ | ❌ | |
Wait | wait4 | ❌ | ❌ | |
Brk | brk | ❌ | ❌ | |
GetCwd | getcwd | ✅ | ✅ | |
Chdir | fchdir, chdir | ✅ | ✅ | |
BindConnect | bind, connect | ❌ | ❌ | |
Accept | accept, accept4 | ❌ | ❌ | |
GetSockOrPeerName | getsockname, getpeername | ❌ | ❌ | |
StandardSyscall | access, acct, chmod, chown, chroot, getxattr, listxattr, mknod, creat, removexattr, setxattr, stat, swapoff, swapon, truncate, umount2, uselib, utime, utimes | ✅ | ✅ | int syscall(const char *pathname, ...) follow symlink |
Open | open | ✅ | ✅ | int syscall(const char *pathname, int flags, ...) |
StatAt | fchownat, newfstatat, utimensat, name_to_handle_at, statx | ✅ | ✅ | int syscall(int dirfd, const char *pathname, ... , int flags, ...) |
ChmodAccessMkNodAt | fchmodat, faccessat, futimesat, mknodat | ✅ | ✅ | int syscall(int dirfd, const char *pathname, ...) follow symlink |
InotifyAddWatch | inotify_add_watch | ❌ | ❌ | |
DirLinkAttr | lchown, lgetxattr, llistxattr, lremovexattr, lsetxattr, lstat, unlink, rmdir, mkdir | ✅ | ✅ | int syscall(const char *pathname, ...) not follow symlink |
PivotRoot | pivot_root | ❌ | ❌ | |
LinkAt | linkat | ✅ | ✅ | |
Mount | mount | ❌ | ❌ | |
OpenAt | openat | ✅ | ✅ | |
ReadLink | readlink | ✅ | ✅ | |
ReadLinkAt | readlinkat | ✅ | ✅ | |
UnlinkMkdirAt | unlinkat, mkdirat | ✅ | ✅ | int syscall(int dirfd, const char *pathname, ...) not follow symlink |
Link | link | ✅ | ✅ | |
Rename | rename | ✅ | ✅ | |
RenameAt | renameat | ✅ | ✅ | |
SymLink | symlink | ✅ | ✅ | |
SymLinkAt | symlinkat | ✅ | ✅ | |
Uname | uname | ❌ | ❌ |
One complication in path translation is whether we need to dereference/follow it if the last component of the path is a symbolic link.
In solving this problem, we found something worthy of reference in the kernel source code: https://elixir.bootlin.com/linux/latest/source/fs/namei.c#L97
/* [Feb-Apr 2000 AV] Complete rewrite. Rules for symlinks:
* inside the path - always follow.
* in the last component in creation/removal/renaming - never follow.
* if LOOKUP_FOLLOW passed - follow.
* if the pathname has trailing slashes - follow.
* otherwise - don't follow.
* (applied in that order).
*/