mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 16:43:05 -05:00
Porpoise (PPSA99764) stops on its weak chroot import (#3632, #4497).
Run 5 on main c2565f014, and again on a copy of that runtime:
FAIL: unresolved ELF import AKknh8Cx-V8 from libkernel_sys.prx
Its only call is in put_root_back (src/porpoise_jailbreak.cpp,
elripalda/Porpoise-Dolphin-Emulator-for-PS5 2ed1ab5a06995aa1): after a
jailbreak daemon has made the console's root its root and /app0 is
gone, it calls fchdir on the descriptor of "/" it opened at start, then
chroot("."), and checks the result. So it only ever puts back the root
it started in, and it does not use paths under any other root.
On top of the lookup errors of the previous commit, chroot now follows
FreeBSD 11.4 sys_chroot and pwd_chroot (8c639945, vfs_syscalls.c and
kern_descrip.c) for that case: a directory that is the guest root
("/", "/..", "." after fchdir to "/") succeeds without a change, since
fd_rdir would be set to the vnode it already is. The guest is taken
never to have changed its root, so with chroot_allow_open_directories 1
an open directory does not give EPERM. ENAMETOOLONG is added as in
pathconf, and a ".." through a file reports ENOTDIR instead of
escaping as a filesystem_error. Any other directory still throws: the
resolver's root and mount aliases are fixed, and no title is known that
needs a real new root.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
15 lines
7.3 KiB
Markdown
15 lines
7.3 KiB
Markdown
# libkernel_sys technical debt
|
|
|
|
### Functional
|
|
|
|
- [fchdir](../../../core/libs/prx/libkernel_sys/Export.cpp) (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/fd` link target. It returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. FreeBSD `change_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](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `open`. Any other relative path is joined to the descriptor's host directory, found the same way as for `fchdir`, 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 returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. As with `open`, `O_NOFOLLOW` and `O_NONBLOCK` are ignored. PPSA99003 opens directory entries this way. Console behaviour is unverified
|
|
- [pathconf](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) looks the path up as FreeBSD 11's `kern_pathconf` does (links followed, `ENAMETOOLONG` for a path of 1024 bytes or more or a component over 255) and returns the constants of FreeBSD 11's UFS `ufs_pathconf` for files and directories alike: `_PC_LINK_MAX` 32767, `_PC_NAME_MAX` 255, `_PC_PATH_MAX` and `_PC_SYMLINK_MAX` 1024, `_PC_PIPE_BUF` 512, `_PC_CHOWN_RESTRICTED` and `_PC_NO_TRUNC` 1, `_PC_FILESIZEBITS` 64, `_PC_REC_MAX_XFER_SIZE` -1, `_PC_PRIO_IO` and `_PC_SYNC_IO` 0. 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 and `vop_stdpathconf` disagree (`_PC_MAX_CANON`, `_PC_MAX_INPUT`, `_PC_VDISABLE`, `_PC_ASYNC_IO`); other names fail with `EINVAL`
|
|
- [mkdirat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `mkdir`. Any other relative path is joined to the descriptor's host directory, found the same way as for `fchdir`, 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 returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. On Windows, `mode` is ignored. Console behaviour is unverified
|
|
- [readlink](../../../core/libs/prx/libkernel_sys/Export.cpp) (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, as `symlink` creates 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 reports `EINVAL` for a file that is not a link
|
|
- [readlinkat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `readlink`. Any other relative path is joined to the descriptor's host directory, found the same way as for `fchdir`, 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 returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. Console behaviour is unverified
|
|
- [unlinkat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `rmdir` (with `AT_REMOVEDIR`, 0x800) or `unlink`. Any other relative path is joined to the descriptor's host directory, found the same way as for `fchdir`, 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 returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. Removing a directory without `AT_REMOVEDIR` fails with `EPERM`, removing `.` or `..` with `AT_REMOVEDIR` fails with `EINVAL`, and flags other than `AT_REMOVEDIR` fail with `EINVAL`. Console behaviour is unverified
|
|
- [renameat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `rename`. Any other relative path is joined to its descriptor's host directory, found the same way as for `fchdir`, 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 returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. Console behaviour is unverified
|
|
- [fork](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) throws: creating a child process is not supported. PPSA19111 imports it and fails to load without it. Its engine calls `fork` in `Posix_Daemonize`, only with `-daemonize`, and in `Platform_ShellExecute` before `execvp("xdg-open")`, which the main menu's Previews button reaches, so pressing Previews ends in this throw. [setsid](../../../core/libs/prx/libkernel_sys/Export.cpp) fails with `EPERM`, as FreeBSD's does for a process group leader, since the guest is taken to lead its own process group (see `kill`). [umask](../../../core/libs/prx/libkernel_sys/Export.cpp) 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](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) follows FreeBSD 11.4's [`sys_chroot`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/vfs_syscalls.c#L776-L807) and [`pwd_chroot`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_descrip.c#L3059-L3085) for a root caller: `EFAULT` for a null path, `ENOENT` for an empty or missing one, `ENAMETOOLONG` for a path of 1024 bytes or more or a component over 255, and `ENOTDIR` for a path that is not a directory or passes through a file. A directory that is the guest root (`/`, `/..`, or `.` after `fchdir` to 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 with `EPERM` (`kern.chroot_allow_open_directories` 1). 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, where `pwd_chroot` refuses with `EPERM` while a directory is open; whether that holds for titles, and whether a title holds `PRIV_VFS_CHROOT`, are unverified. Porpoise (PPSA99764) weak-imports it and calls it only as `fchdir` to its saved descriptor of `/` then `chroot(".")`, to put its sandbox root back after a jailbreak daemon replaced it ([`put_root_back`](https://github.com/elripalda/Porpoise-Dolphin-Emulator-for-PS5/blob/2ed1ab5a06995aa198f7bccd4da0f90c3fc29d39/src/porpoise_jailbreak.cpp#L303-L331))
|