fix(libkernel_sys): check fchdir search permission on Linux

This commit is contained in:
Dani committed 2026-10-11 13:18:30 +02:00
1 parent 0f863c1022
commit 0e4d94ce39
2 files changed
+26

No files matched your search

+8
View File
@@ -8,6 +8,11 @@
#include <stdexcept>
#include <string>
#include <system_error>
#ifdef __linux__
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#endif
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libkernel/File/include/DirectoryDescriptor.hpp"
@@ -98,6 +103,9 @@ int APS5_VABI fchdir_nid_postfix(int fd) {
int error = 0;
const char* path = GetDirectoryDescriptorPath_nid_no_patch(fd, &error);
if (path == nullptr) return static_cast<int>(Fail(error));
#ifdef __linux__
if (::faccessat(fd, ".", X_OK, AT_EACCESS) != 0) return static_cast<int>(Fail(errno));
#endif
error = SetWorkingDirectory_nid_no_patch(path);
if (error != 0) return static_cast<int>(Fail(error));
return 0;
+18
View File
@@ -9,6 +9,10 @@
#include <fstream>
#include <source_location>
#include <string>
#ifdef __linux__
#include <cerrno>
#include <unistd.h>
#endif
extern "C" {
int APS5_VABI fstatfs_nid_postfix(int, void*);
@@ -104,6 +108,20 @@ int main() {
char directoryPath[1024];
Require(getcwd_nid_postfix(directoryPath, sizeof(directoryPath)) == directoryPath);
Require(std::strcmp(directoryPath, ("/" + root.filename().string()).c_str()) == 0);
#ifdef __linux__
Require(chdir_nid_postfix("/") == 0);
const auto originalPermissions = std::filesystem::status(root).permissions();
std::filesystem::permissions(root, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write);
const bool searchDenied = ::access(root.c_str(), X_OK) == -1 && errno == EACCES;
const int deniedResult = searchDenied ? fchdir_nid_postfix(directory) : 0;
const int deniedError = Error();
const bool cwdUnchanged = getcwd_nid_postfix(directoryPath, sizeof(directoryPath)) == directoryPath && std::strcmp(directoryPath, "/") == 0;
std::filesystem::permissions(root, std::filesystem::perms::owner_exec);
const int searchOnlyResult = fchdir_nid_postfix(directory);
std::filesystem::permissions(root, originalPermissions);
if (searchDenied) Require(deniedResult == -1 && deniedError == EACCES && cwdUnchanged);
Require(searchOnlyResult == 0);
#endif
Require(sceKernelClose(fileDescriptor) == 0);
Require(sceKernelClose(directory) == 0);
Require(fchdir_nid_postfix(directory) == -1 && Error() == 9);