feat(libkernel_sys): implement kldfind, kldfirstmod, kldnext and kldunload

This commit is contained in:
camezaro-intc committed 2026-10-25 23:58:13 -06:00
1 parent 14c99b52ac
commit d4200caffc
5 files changed
+42 -24

No files matched your search

@@ -114,26 +114,11 @@ int APS5_VABI kenv_nid_postfix(void) {
return 0;
}
int APS5_VABI kldfind_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI kldfirstmod_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI kldload_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI kldnext_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI kldstat_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
@@ -144,11 +129,6 @@ int APS5_VABI kldsym_nid_postfix(void) {
return 0;
}
int APS5_VABI kldunload_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI kmq_notify_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
+21
View File
@@ -560,6 +560,27 @@ int APS5_VABI chroot_nid_postfix(const char* path) {
throw std::runtime_error(std::string("chroot: changing the root directory to ") + path + " is not supported, the guest path resolver keeps a fixed root");
}
int APS5_VABI kldfind_nid_postfix(const char* file) {
std::string copy;
if (const int error = CopyPath(file, copy)) return static_cast<int>(Fail(error));
return static_cast<int>(Fail(GuestEnoent));
}
int APS5_VABI kldfirstmod_nid_postfix(int fileid) {
return static_cast<int>(Fail(GuestEnoent));
}
int APS5_VABI kldnext_nid_postfix(int fileid) {
if (fileid < 0) return static_cast<int>(Fail(GuestEnoent));
if (fileid == 0) return 0;
return static_cast<int>(Fail(GuestEnoent));
}
int APS5_VABI kldunload_nid_postfix(int fileid) {
(void)fileid;
return static_cast<int>(Fail(GuestEperm));
}
int APS5_VABI symlink_nid_postfix(const char* target, const char* created) {
std::string targetCopy, createdCopy;
if (const int error = CopyPath(target, targetCopy)) return static_cast<int>(Fail(error));
+4 -4
View File
@@ -99,13 +99,13 @@ int APS5_VABI getfsstat_nid_postfix(void);
int APS5_VABI ipmimgr_call_nid_postfix(void);
int APS5_VABI is_in_sandbox_nid_postfix(void);
int APS5_VABI kenv_nid_postfix(void);
int APS5_VABI kldfind_nid_postfix(void);
int APS5_VABI kldfirstmod_nid_postfix(void);
int APS5_VABI kldfind_nid_postfix(const char* file);
int APS5_VABI kldfirstmod_nid_postfix(int fileid);
int APS5_VABI kldload_nid_postfix(void);
int APS5_VABI kldnext_nid_postfix(void);
int APS5_VABI kldnext_nid_postfix(int fileid);
int APS5_VABI kldstat_nid_postfix(void);
int APS5_VABI kldsym_nid_postfix(void);
int APS5_VABI kldunload_nid_postfix(void);
int APS5_VABI kldunload_nid_postfix(int fileid);
int APS5_VABI kmq_notify_nid_postfix(void);
int APS5_VABI kmq_open_nid_postfix(void);
int APS5_VABI kmq_setattr_nid_postfix(void);
+16
View File
@@ -283,6 +283,7 @@ void CheckUnreadablePaths(const std::string& renameSource, int directory) {
Require(link_nid_postfix("missing", paths.Unreadable()) == -1 && Error() == 2);
posixFault([&] { return shm_open_nid_postfix(paths.Unreadable(), SCE_KERNEL_O_RDWR, 0600); });
posixFault([&] { return shm_unlink_nid_postfix(paths.Unreadable()); });
posixFault([&] { return kldfind_nid_postfix(paths.Unreadable()); });
Require(sceKernelOpen(paths.Unreadable(), SCE_KERNEL_O_RDONLY, 0) == KernelFault);
Require(sceKernelStat(paths.Unreadable(), &status) == KernelFault);
Require(sceKernelMkdir(paths.Unreadable(), 0755) == KernelFault);
@@ -794,6 +795,21 @@ int main() {
Require(chroot_nid_postfix((root / "file.txt" / "..").string().c_str()) == -1 && Error() == 20);
Require(chroot_nid_postfix((root / std::string(256, 'n')).string().c_str()) == -1 && Error() == 63);
Require(chroot_nid_postfix(("/" + std::string(1024, 'p')).c_str()) == -1 && Error() == 63);
Require(kldfind_nid_postfix(nullptr) == -1 && Error() == 14);
Require(kldfind_nid_postfix(reinterpret_cast<const char*>(0x10)) == -1 && Error() == 14);
Require(kldfind_nid_postfix(("/" + std::string(1024, 'p')).c_str()) == -1 && Error() == 63);
Require(kldfind_nid_postfix("") == -1 && Error() == 2);
Require(kldfind_nid_postfix("kernel") == -1 && Error() == 2);
Require(kldfind_nid_postfix("missing.ko") == -1 && Error() == 2);
Require(kldnext_nid_postfix(-1) == -1 && Error() == 2);
Require(kldnext_nid_postfix(0) == 0);
Require(kldnext_nid_postfix(1) == -1 && Error() == 2);
Require(kldfirstmod_nid_postfix(-1) == -1 && Error() == 2);
Require(kldfirstmod_nid_postfix(0) == -1 && Error() == 2);
Require(kldfirstmod_nid_postfix(1) == -1 && Error() == 2);
Require(kldunload_nid_postfix(-1) == -1 && Error() == 1);
Require(kldunload_nid_postfix(0) == -1 && Error() == 1);
Require(kldunload_nid_postfix(1) == -1 && Error() == 1);
const std::string throughFile = (root / "file.txt" / "child").string();
Require(pathconf_nid_postfix(throughFile.c_str(), 4) == -1 && Error() == 20);
Require(fchmodat_nid_postfix(-100, throughFile.c_str(), 0600, 0) == -1 && Error() == 20);
+1
View File
@@ -29,6 +29,7 @@
- [sceKernelGetModuleInfoInternal and sceKernelGetModuleListInternal](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) answer for every loaded module, system modules included. `sceKernelGetModuleInfoInternal` fills the 0x1A8-byte `SceKernelModuleInfoEx` of a module handle the way `sceKernelGetModuleInfoFromAddr` does for an address, with [shadPS4's checks](https://github.com/shadps4-emu/shadPS4/blob/a808e76/src/core/libraries/kernel/process.cpp#L243-L258) in their order: `EFAULT` for a null pointer, `EINVAL` when `st_size` is not 0x1A8, `ESRCH` for an unknown handle. `sceKernelGetModuleListInternal` returns the same list as `sceKernelGetModuleList`, as [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd4/kernel/ps4_libkernel.pas#L852-L858) does; fpPS4 marks that as a guess, and neither is checked on a PS5
- [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))
- [Console identity](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - `get_authinfo` errors and capability bits remain unverified on PS5; they follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/396c2a09a38d22eaa02aab32c1967263dceab95f/src/core/libraries/kernel/kernel.cpp), leaving the authority ID and other capability, attribute and credential words zero. The host models a retail unit (`IsCEX` 1, `IsDevKit` 0). The system OpenPSID reuses the ordinary ID; firmware 13.42 reads a separate `machdep.openpsid_for_sys`, whose value is unknown. Null returns positive 22 per the [module report](https://github.com/boykopovar/AnyPS5/pull/10524#issuecomment-6393566914).
- [kldfind, kldfirstmod, kldnext and kldunload](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) follow FreeBSD 11.4's linker calls ([sys/kern/kern_linker.c](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/kern_linker.c)): kldfind validates the module name with CopyPath (EFAULT on null or unreadable pointers, ENAMETOOLONG for paths of 1024 bytes or more) and returns ENOENT for any module name; on FreeBSD the kernel itself is linker file 1, and AnyPS5 models an empty file list, so kldnext(0) returns 0 and kldfind("kernel") fails; kldnext returns ENOENT for negative or positive fileids; kldfirstmod returns ENOENT for any fileid; and kldunload returns EPERM as sandboxed/jailed titles lack PRIV_KLD_UNLOAD. Dynamic kernel linker module lookup and management remain unverified on hardware
- [fchown](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - ownership is not modelled: the guest's own owner and group (0) and the unchanged value (-1) are accepted, a descriptor that is not open fails with `EBADF`, and any other owner or group throws, naming it. The check reads the descriptor with `fstat`, ignoring the CRT's invalid-parameter handler on Windows as `DescriptorControl` does. The console's ownership rules are unverified. Morrowind (`mshivam019/morrowind-ps5`) imports it
- [chown, lchown and fchownat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - ownership is not modelled, as for `fchown`: owner and group 0 and the unchanged value (-1) are accepted, and any other owner or group throws, naming it. The path is looked up first, as in FreeBSD 11's `kern_fchownat`, with `stat`, with `lstat` for `lchown`, and with `fstatat` for `fchownat`, so a lookup error is returned before the owner is checked and nothing is changed on the host. `fchownat` flags other than `AT_SYMLINK_NOFOLLOW` (0x200) return `EINVAL`, as in FreeBSD 11. The console's ownership rules are unverified
- [linkat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) resolves `AT_FDCWD` (-100) and absolute paths as `link` does, and flags other than `AT_SYMLINK_FOLLOW` (0x400) return `EINVAL`, as in FreeBSD 11. 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. A symbolic link as the source without `AT_SYMLINK_FOLLOW` throws, where FreeBSD links the symbolic link itself. Console behaviour is unverified