mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
fix(libkernel_sys): check the linkat source before resolving the target
This commit is contained in:
1 parent
d44d5685eb
commit
2d32e8bd85
2 files changed
+21
-7
No files matched your search
@@ -436,17 +436,21 @@ static int FollowLinkPath(const std::filesystem::path& source, std::filesystem::
|
||||
}
|
||||
#endif
|
||||
|
||||
static int LinkNative(const std::filesystem::path& source, const std::filesystem::path& destination) {
|
||||
static int LinkSourceError(const std::filesystem::path& source) {
|
||||
std::error_code error;
|
||||
const auto status = std::filesystem::status(source, error);
|
||||
if (!std::filesystem::exists(status)) {
|
||||
#ifdef _WIN32
|
||||
std::filesystem::path target;
|
||||
if (const int followError = FollowLinkPath(source, target)) return static_cast<int>(Fail(followError));
|
||||
if (const int followError = FollowLinkPath(source, target)) return followError;
|
||||
#endif
|
||||
return static_cast<int>(Fail(HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent));
|
||||
return HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent;
|
||||
}
|
||||
if (std::filesystem::is_directory(status)) return static_cast<int>(Fail(GuestEperm));
|
||||
return std::filesystem::is_directory(status) ? GuestEperm : 0;
|
||||
}
|
||||
|
||||
static int LinkNative(const std::filesystem::path& source, const std::filesystem::path& destination) {
|
||||
std::error_code error;
|
||||
if (std::filesystem::exists(std::filesystem::symlink_status(destination, error))) return static_cast<int>(Fail(GuestEexist));
|
||||
if (!std::filesystem::is_directory(destination.parent_path(), error)) return static_cast<int>(Fail(HasNonDirectoryPrefix(destination) ? GuestEnotdir : GuestEnoent));
|
||||
#ifdef _WIN32
|
||||
@@ -469,6 +473,7 @@ int APS5_VABI link_nid_postfix(const char* existing, const char* created) {
|
||||
std::filesystem::path source, destination;
|
||||
if (const int error = ResolvePathError_nid_no_patch(existing, source)) return static_cast<int>(Fail(error));
|
||||
if (const int error = ResolvePathError_nid_no_patch(created, destination)) return static_cast<int>(Fail(error));
|
||||
if (const int error = LinkSourceError(source)) return static_cast<int>(Fail(error));
|
||||
return LinkNative(source, destination);
|
||||
}
|
||||
|
||||
@@ -484,12 +489,15 @@ static int ResolveAtPath(int fd, const char* path, std::filesystem::path& native
|
||||
|
||||
int APS5_VABI linkat_nid_postfix(int fd1, const char* path1, int fd2, const char* path2, int flag) {
|
||||
if (flag & ~GuestAtSymlinkFollow) return static_cast<int>(Fail(GuestEinval));
|
||||
if (path1 == nullptr || path2 == nullptr) return static_cast<int>(Fail(GuestEfault));
|
||||
if (*path1 == '\0' || *path2 == '\0') return static_cast<int>(Fail(GuestEnoent));
|
||||
if (path1 == nullptr) return static_cast<int>(Fail(GuestEfault));
|
||||
if (*path1 == '\0') return static_cast<int>(Fail(GuestEnoent));
|
||||
std::filesystem::path source, destination;
|
||||
if (const int error = ResolveAtPath(fd1, path1, source)) return static_cast<int>(Fail(error));
|
||||
if (const int error = ResolveAtPath(fd2, path2, destination)) return static_cast<int>(Fail(error));
|
||||
if (flag == 0 && IsSymbolicLink(source)) NotImplemented_nid_no_patch("linkat: a hard link to a symbolic link itself");
|
||||
if (const int error = LinkSourceError(source)) return static_cast<int>(Fail(error));
|
||||
if (path2 == nullptr) return static_cast<int>(Fail(GuestEfault));
|
||||
if (*path2 == '\0') return static_cast<int>(Fail(GuestEnoent));
|
||||
if (const int error = ResolveAtPath(fd2, path2, destination)) return static_cast<int>(Fail(error));
|
||||
return LinkNative(source, destination);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,12 @@ void OwnershipAndLinkTests(const std::filesystem::path& root) {
|
||||
Require(linkat_nid_postfix(directory, "missing.txt", directory, "absent.txt", 0) == -1 && Error() == 2);
|
||||
Require(linkat_nid_postfix(4321, "owned.txt", directory, "absent.txt", 0) == -1 && Error() == 9);
|
||||
Require(linkat_nid_postfix(directory, "owned.txt", 4321, "absent.txt", 0) == -1 && Error() == 9);
|
||||
Require(linkat_nid_postfix(directory, "missing.txt", 4321, "absent.txt", 0) == -1 && Error() == 2);
|
||||
Require(linkat_nid_postfix(directory, "missing.txt", -100, nullptr, 0) == -1 && Error() == 2);
|
||||
Require(linkat_nid_postfix(-100, root.string().c_str(), 4321, "absent.txt", 0) == -1 && Error() == 1);
|
||||
Require(linkat_nid_postfix(-100, root.string().c_str(), -100, "", 0) == -1 && Error() == 1);
|
||||
Require(linkat_nid_postfix(directory, "owned.txt", -100, nullptr, 0) == -1 && Error() == 14);
|
||||
Require(linkat_nid_postfix(directory, "owned.txt", -100, "", 0) == -1 && Error() == 2);
|
||||
const int plain = sceKernelOpen(file.c_str(), SCE_KERNEL_O_RDONLY, 0);
|
||||
Require(plain >= 0);
|
||||
Require(linkat_nid_postfix(plain, "owned.txt", directory, "absent.txt", 0) == -1 && Error() == 20);
|
||||
|
||||
Reference in new issue
Block a user