8.1 KiB
8.1 KiB
libkernel_sys technical debt
Functional
- fchdir (libkernel_sys) changes the guest working directory to the descriptor's directory: on Windows through the path recorded when the descriptor was opened, on Linux through the
/proc/self/fdlink target. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. FreeBSDchange_dir's search-permission check (EACCES) is not modelled, and a directory renamed after it was opened is still reached through the recorded path. Console behaviour is unverified - openat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths toopen. Any other relative path is joined to the descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. As withopen,O_NOFOLLOWandO_NONBLOCKare ignored. PPSA99003 opens directory entries this way. Console behaviour is unverified - fchmodat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths tochmod; any other relative path is joined to the descriptor's host directory the same way as foropenat, so guest path aliases and case-insensitive name matching do not apply to it and a..component is not kept inside the guest root. A flag other than0orAT_SYMLINK_NOFOLLOW(0x200) returnsEINVAL; the mode is masked to07777. WithAT_SYMLINK_NOFOLLOWa symbolic link throws, since the host cannot change a link's own mode, while a regular file is changed either way. The mode maps to the host file mode, which on Windows is only the CRT's read-only bit. PPSA99621 calls it throughstd::filesystem::permissions. Console behaviour is unverified - pathconf (libkernel_sys) looks the path up as FreeBSD 11's
kern_pathconfdoes (links followed,ENAMETOOLONGfor a path of 1024 bytes or more or a component over 255) and returns the constants of FreeBSD 11's UFSufs_pathconffor files and directories alike:_PC_LINK_MAX32767,_PC_NAME_MAX255,_PC_PATH_MAXand_PC_SYMLINK_MAX1024,_PC_PIPE_BUF512,_PC_CHOWN_RESTRICTEDand_PC_NO_TRUNC1,_PC_FILESIZEBITS64,_PC_REC_MAX_XFER_SIZE-1,_PC_PRIO_IOand_PC_SYNC_IO0. Whether the console's filesystems report the same is not verified. It throws for the names whose UFS value depends on the mount (_PC_ALLOC_SIZE_MIN,_PC_REC_INCR_XFER_SIZE,_PC_REC_MIN_XFER_SIZE,_PC_MIN_HOLE_SIZE), the kernel options (_PC_ACL_EXTENDED,_PC_ACL_PATH_MAX,_PC_ACL_NFS4,_PC_MAC_PRESENT) or the page size (_PC_REC_XFER_ALIGN), and on which UFS andvop_stdpathconfdisagree (_PC_MAX_CANON,_PC_MAX_INPUT,_PC_VDISABLE,_PC_ASYNC_IO); other names fail withEINVAL - mkdirat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths tomkdir. Any other relative path is joined to the descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. On Windows,modeis ignored. Console behaviour is unverified - readlink (libkernel_sys) on Windows reads a symbolic link's target from its reparse data and returns it with
/separators, only when the target is relative, assymlinkcreates them. A symbolic link with an absolute target and a junction throw, as a host path has no guest form. Any other reparse point throws too, where FreeBSD reportsEINVALfor a file that is not a link - readlinkat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths toreadlink. Any other relative path is joined to the descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. Console behaviour is unverified - unlinkat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths tormdir(withAT_REMOVEDIR, 0x800) orunlink. Any other relative path is joined to the descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. Removing a directory withoutAT_REMOVEDIRfails withEPERM, removing.or..withAT_REMOVEDIRfails withEINVAL, and flags other thanAT_REMOVEDIRfail withEINVAL. Console behaviour is unverified - renameat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths torename. Any other relative path is joined to its descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to relative descriptors, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. Console behaviour is unverified - fork (libkernel_sys) throws: creating a child process is not supported. PPSA19111 imports it and fails to load without it. Its engine calls
forkinPosix_Daemonize, only with-daemonize, and inPlatform_ShellExecutebeforeexecvp("xdg-open"), which the main menu's Previews button reaches, so pressing Previews ends in this throw. setsid fails withEPERM, as FreeBSD's does for a process group leader, since the guest is taken to lead its own process group (seekill). umask keeps the guest's mask (initially 022, masked to 07777) and returns the previous one, Linux named shared-memory creation applies it, but ordinary files are still created with the host process's mask - chroot (libkernel_sys) follows FreeBSD 11.4's
sys_chrootandpwd_chrootfor a root caller:EFAULTfor a null path,ENOENTfor an empty or missing one,ENAMETOOLONGfor a path of 1024 bytes or more or a component over 255, andENOTDIRfor a path that is not a directory or passes through a file. A directory that is the guest root (/,/.., or.afterfchdirto a descriptor of/) succeeds and changes nothing, as the root stays the same directory; the guest is taken never to have changed its root, so open directory descriptors do not make it fail withEPERM(kern.chroot_allow_open_directories1). Any other directory throws, naming the path: the guest path resolver has a fixed root and mount aliases (/app0,/savedata0) that do not move with it. On the console a title starts in a sandbox root, wherepwd_chrootrefuses withEPERMwhile a directory is open; whether that holds for titles, and whether a title holdsPRIV_VFS_CHROOT, are unverified. Porpoise (PPSA99764) weak-imports it and calls it only asfchdirto its saved descriptor of/thenchroot("."), to put its sandbox root back after a jailbreak daemon replaced it (put_root_back)