Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/libs/prx/libc/include/FilesystemError.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ inline bool HasNonDirectoryPrefix_nid_no_patch(const std::filesystem::path& nati
return false;
}

inline bool NamesNonDirectoryWithSlash_nid_no_patch(const std::filesystem::path& native) {
if (native.has_filename()) return false;
auto named = native;
while (!named.has_filename() && named.has_relative_path()) named = named.parent_path();
std::error_code error;
const auto status = std::filesystem::status(named, error);
return std::filesystem::exists(status) && !std::filesystem::is_directory(status);
}

inline int NotFoundError_nid_no_patch(const std::filesystem::path& native) {
return HasNonDirectoryPrefix_nid_no_patch(native) ? 20 : 2;
}
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libc/src/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ extern "C" int APS5_VABI remove_nid_postfix(const char* path) {
errno = 22;
return -1;
}
if (NamesNonDirectoryWithSlash_nid_no_patch(resolved)) { errno = 20; return -1; }
std::error_code error;
#ifdef _WIN32
const DWORD attributes = GetFileAttributesW(resolved.c_str());
Expand Down
2 changes: 0 additions & 2 deletions core/libs/prx/libc/src/General.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,11 @@ std::optional<std::filesystem::path> ResolveAlias(const std::string& guestPath,
const auto result = std::filesystem::path(host).make_preferred();
return module ? PathOrRelinkedModule(result) : result;
}
#ifndef _WIN32
if (guestPath.back() == '/') {
auto result = ResolveHostPath(host, SplitNames(std::string_view(relative).substr(prefix.size() + 1)));
result /= "";
return module ? PathOrRelinkedModule(result) : result;
}
#endif
return ResolveHostPath(host, SplitNames(std::string_view(relative).substr(prefix.size() + 1)), module).make_preferred();
}
return std::nullopt;
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libc/src/Rename.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extern "C" int RenameGuestPath_nid_no_patch(const char* from, const char* to) {
return -1;
}
const auto destination = ResolvePath_nid_no_patch(to);
if (NamesNonDirectoryWithSlash_nid_no_patch(source) || (std::filesystem::exists(source) && NamesNonDirectoryWithSlash_nid_no_patch(destination))) { errno = 20; return -1; }
int error = RenamePath_nid_no_patch(source, destination);
if (error == 2) {
std::error_code status;
Expand Down
2 changes: 2 additions & 0 deletions core/libs/prx/libkernel/File/src/Open.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) {
APS5_LOG_ERR("open failed path=%s resolveError=%d result=0x%08X", path != nullptr ? path : "<null>", error, static_cast<unsigned>(result));
return result;
}
if (NamesNonDirectoryWithSlash_nid_no_patch(native)) return SceErrorFromErrno(ENOTDIR);
const int result = OpenNative(native, flags, mode);
if (result < 0) {
const auto resolved = native.u8string();
Expand Down Expand Up @@ -416,6 +417,7 @@ int APS5_VABI sceKernelUnlink(const char* path) {
std::filesystem::path native;
if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error);
constexpr int GuestEperm = 1;
if (NamesNonDirectoryWithSlash_nid_no_patch(native)) return SceErrorFromErrno(20);
std::error_code error;
if (std::filesystem::is_directory(std::filesystem::symlink_status(native, error))) return SceErrorFromErrno(GuestEperm);
if (NativeUnlink(native) != 0) {
Expand Down
6 changes: 4 additions & 2 deletions core/libs/tests/GuestFilesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,21 @@ static void TestParentTraversal() {
checkInvalid("/parent-test-mount/present.txt/..", 20);
FileStat status{};
Require(sceKernelStat("/parent-test-mount/existing/../present.txt", &status) == 0 && status.st_size == 9);
#ifndef _WIN32
for (const char* name : {"slash-unlink", "slash-remove", "slash-rename", "slash-open", "slash-kernel"}) std::ofstream(root / name) << "kept";
Require(unlink_nid_postfix("/parent-test-mount/slash-unlink/") == -1 && *__error_nid_postfix() == 20);
Require(remove_nid_postfix("/parent-test-mount/slash-remove/") == -1 && *__error_nid_postfix() == 20);
Require(rename_nid_postfix("/parent-test-mount/slash-rename/", "/parent-test-mount/slash-renamed") == -1 && *__error_nid_postfix() == 20);
Require(open_nid_postfix("/parent-test-mount/slash-open/", 0, 0) == -1 && *__error_nid_postfix() == 20);
Require(sceKernelUnlink("/parent-test-mount/slash-kernel/") == static_cast<int>(0x80020014u));
Require(unlink_nid_postfix("/parent-test-mount/slash-unlink/child/") == -1 && *__error_nid_postfix() == 20);
Require(remove_nid_postfix("/parent-test-mount/slash-remove/child/") == -1 && *__error_nid_postfix() == 20);
Require(open_nid_postfix("/parent-test-mount/slash-open/child/", 0, 0) == -1 && *__error_nid_postfix() == 20);
Require(sceKernelUnlink("/parent-test-mount/slash-kernel/child/") == static_cast<int>(0x80020014u));
for (const char* name : {"slash-unlink", "slash-remove", "slash-rename", "slash-open", "slash-kernel"}) Require(std::filesystem::is_regular_file(root / name));
Require(!std::filesystem::exists(root / "slash-renamed"));
Require(sceKernelStat("/parent-test-mount/Existing/", &status) == 0 && (status.st_mode & 0170000) == 0040000);
Require(mkdir_nid_postfix("/parent-test-mount/slash-directory/", 0755) == 0 && std::filesystem::is_directory(root / "slash-directory"));
Require(rmdir_nid_postfix("/parent-test-mount/slash-directory/") == 0 && !std::filesystem::exists(root / "slash-directory"));
#endif
RemovePathAlias_nid_no_patch("parent-test-mount");
std::error_code linkError;
std::filesystem::create_directory_symlink("Existing", root / "directory-link", linkError);
Expand Down
Loading