mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
Merge pull request #10958 from AZLisme/feat/posix-webkit-raw-addresses
feat(libScePosixForWebKit): resolve raw socket address hints
This commit is contained in:
4 files changed
+104
-5
No files matched your search
@@ -66,3 +66,16 @@ if(BUILD_TESTING)
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libScePosixForWebKit>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_raw_resolver_tests ${LIBS_INCLUDE_DIR}/tests/ResolverRaw.cpp)
|
||||
target_include_directories(guest_raw_resolver_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_raw_resolver_tests PRIVATE libScePosixForWebKit libc)
|
||||
configure_windows_unwind(guest_raw_resolver_tests)
|
||||
add_test(NAME guest_raw_resolver COMMAND guest_raw_resolver_tests)
|
||||
set_tests_properties(guest_raw_resolver PROPERTIES TIMEOUT 30)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_raw_resolver PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libScePosixForWebKit>")
|
||||
endif()
|
||||
endif()
|
||||
@@ -260,15 +260,17 @@ int APS5_VABI getaddrinfo_nid_postfix(const char* node, const char* service,
|
||||
const GuestResolver::AddressInfo* hints, GuestResolver::AddressInfo** output) {
|
||||
if (!output) return 4;
|
||||
*output = nullptr;
|
||||
if (!node && !service) return 8;
|
||||
addrinfo nativeHints{};
|
||||
const bool rawQuery = hints && hints->socketType == 3;
|
||||
if (hints) {
|
||||
if (hints->addressLength || hints->address || hints->canonicalName || hints->next) return 12;
|
||||
if ((hints->flags & ~0xd0f) != 0) return 3;
|
||||
if (hints->family != 0 && hints->family != 2 && hints->family != 28) return 5;
|
||||
if (hints->socketType != 0 && hints->socketType != 1 && hints->socketType != 2) return 10;
|
||||
if (hints->socketType != 0 && hints->socketType != 1 && hints->socketType != 2 && hints->socketType != 3) return 10;
|
||||
nativeHints.ai_family = hints->family == 28 ? AF_INET6 : hints->family == 2 ? AF_INET : AF_UNSPEC;
|
||||
nativeHints.ai_socktype = hints->socketType == 1 ? SOCK_STREAM : hints->socketType == 2 ? SOCK_DGRAM : 0;
|
||||
nativeHints.ai_protocol = hints->protocol;
|
||||
nativeHints.ai_socktype = hints->socketType == 1 ? SOCK_STREAM : (hints->socketType == 2 || rawQuery) ? SOCK_DGRAM : 0;
|
||||
nativeHints.ai_protocol = rawQuery ? IPPROTO_UDP : hints->protocol;
|
||||
if (hints->flags & 1) nativeHints.ai_flags |= AI_PASSIVE;
|
||||
if (hints->flags & 2) nativeHints.ai_flags |= AI_CANONNAME;
|
||||
if (hints->flags & 4) nativeHints.ai_flags |= AI_NUMERICHOST;
|
||||
@@ -277,6 +279,7 @@ int APS5_VABI getaddrinfo_nid_postfix(const char* node, const char* service,
|
||||
if (hints->flags & 0x400) nativeHints.ai_flags |= AI_ADDRCONFIG;
|
||||
if (hints->flags & 0x800) nativeHints.ai_flags |= AI_V4MAPPED;
|
||||
}
|
||||
if (rawQuery && service) return 9;
|
||||
if (!Ready()) return 4;
|
||||
addrinfo* native = nullptr;
|
||||
const auto error = ::getaddrinfo(node, service, &nativeHints, &native);
|
||||
@@ -292,8 +295,8 @@ int APS5_VABI getaddrinfo_nid_postfix(const char* node, const char* service,
|
||||
tail = &converted->next;
|
||||
converted->flags = hints ? hints->flags : 0;
|
||||
converted->family = item->ai_family == AF_INET ? 2 : 28;
|
||||
converted->socketType = item->ai_socktype == SOCK_STREAM ? 1 : item->ai_socktype == SOCK_DGRAM ? 2 : 0;
|
||||
converted->protocol = item->ai_protocol;
|
||||
converted->socketType = rawQuery ? 3 : item->ai_socktype == SOCK_STREAM ? 1 : item->ai_socktype == SOCK_DGRAM ? 2 : 0;
|
||||
converted->protocol = rawQuery ? hints->protocol : item->ai_protocol;
|
||||
converted->addressLength = item->ai_family == AF_INET ? 16 : 28;
|
||||
auto* bytes = static_cast<unsigned char*>(std::calloc(1, converted->addressLength));
|
||||
converted->address = bytes;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "prx/libScePosixForWebKit/libScePosixForWebKit.hpp"
|
||||
#include "prx/libScePosixForWebKit/GuestResolver.hpp"
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void Require(bool result, const char* message) {
|
||||
if (result) return;
|
||||
std::fprintf(stderr, "raw resolver: %s\n", message);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
void Address(const char* node, int family, int protocol, int flags) {
|
||||
GuestResolver::AddressInfo hints{};
|
||||
hints.flags = flags;
|
||||
hints.family = family;
|
||||
hints.socketType = 3;
|
||||
hints.protocol = protocol;
|
||||
GuestResolver::AddressInfo* result = nullptr;
|
||||
Require(getaddrinfo_nid_postfix(node, nullptr, &hints, &result) == 0 && result, "raw address resolution failed");
|
||||
unsigned count = 0;
|
||||
for (const auto* entry = result; entry; entry = entry->next) {
|
||||
++count;
|
||||
Require(entry->socketType == 3 && entry->protocol == protocol, "raw type or protocol changed");
|
||||
const auto* bytes = static_cast<const unsigned char*>(entry->address);
|
||||
Require(entry->family == (node[0] == ':' ? 28 : 2), "address family changed");
|
||||
Require(bytes[0] == entry->addressLength && bytes[1] == entry->family, "guest sockaddr prefix differs");
|
||||
Require(bytes[2] == 0 && bytes[3] == 0, "raw address has a transport port");
|
||||
if (entry->family == 2) {
|
||||
constexpr std::array<unsigned char, 4> expected{127, 0, 0, 1};
|
||||
Require(entry->addressLength == 16 && std::memcmp(bytes + 4, expected.data(), expected.size()) == 0, "IPv4 bytes differ");
|
||||
} else {
|
||||
constexpr std::array<unsigned char, 16> expected{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||
Require(entry->addressLength == 28 && std::memcmp(bytes + 8, expected.data(), expected.size()) == 0, "IPv6 bytes differ");
|
||||
}
|
||||
if (flags & 2) Require(entry->canonicalName && std::strcmp(entry->canonicalName, node) == 0, "numeric canonical name differs");
|
||||
}
|
||||
Require(count == 1, "raw numeric query returned duplicate socket variants");
|
||||
Require(hints.socketType == 3 && hints.protocol == protocol && hints.flags == flags && hints.family == family, "query mutated hints");
|
||||
freeaddrinfo_nid_postfix(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
for (int protocol : {0, 1, 6, 17, 58, 132, 255, 256, -1, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()}) {
|
||||
for (int flags : {4, 6, 12}) {
|
||||
Address("127.0.0.1", 0, protocol, flags);
|
||||
Address("127.0.0.1", 2, protocol, flags);
|
||||
Address("::1", 0, protocol, flags);
|
||||
Address("::1", 28, protocol, flags);
|
||||
}
|
||||
}
|
||||
GuestResolver::AddressInfo hints{};
|
||||
hints.flags = 4;
|
||||
hints.socketType = 3;
|
||||
for (const char* service : {"", "0", "123", "65535", "http", "not-a-service"}) {
|
||||
auto* result = reinterpret_cast<GuestResolver::AddressInfo*>(1);
|
||||
Require(getaddrinfo_nid_postfix("127.0.0.1", service, &hints, &result) == 9 && !result, "raw service did not fail with EAI_SERVICE and clear output");
|
||||
}
|
||||
GuestResolver::AddressInfo* result = nullptr;
|
||||
Require(getaddrinfo_nid_postfix(nullptr, nullptr, &hints, &result) == 8 && !result, "missing host and service was accepted");
|
||||
hints.family = 2;
|
||||
Require(getaddrinfo_nid_postfix("::1", nullptr, &hints, &result) != 0 && !result, "family mismatch was accepted");
|
||||
hints.family = 0;
|
||||
hints.flags = 0x200;
|
||||
Require(getaddrinfo_nid_postfix("127.0.0.1", nullptr, &hints, &result) == 3 && !result, "invalid raw flags were accepted");
|
||||
Require(getaddrinfo_nid_postfix(nullptr, nullptr, &hints, &result) == 8 && !result, "invalid flags overrode missing names");
|
||||
hints.flags = 4;
|
||||
hints.addressLength = 1;
|
||||
Require(getaddrinfo_nid_postfix("127.0.0.1", nullptr, &hints, &result) == 12 && !result, "invalid raw hint state was accepted");
|
||||
Require(getaddrinfo_nid_postfix(nullptr, nullptr, &hints, &result) == 8 && !result, "invalid hint state overrode missing names");
|
||||
return 0;
|
||||
}
|
||||
@@ -15,3 +15,5 @@
|
||||
- [fnmatch](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) follows FreeBSD 11 [fnmatch.c](https://github.com/freebsd/freebsd-src/blob/stable/11/lib/libc/gen/fnmatch.c) in the C locale: each byte is one character, `FNM_CASEFOLD` folds ASCII letters only, and bracket ranges compare byte values. `[:class:]` names are not character classes: as in FreeBSD 11 through 14, `[[:digit:]]` is the set of `[`, `:`, `d`, `i`, `g`, `t` followed by a literal `]` (classes were added to `fnmatch.c` after 14). Multibyte characters and locale collation are not modelled. A null pattern or string throws
|
||||
- [getservbyname](../../../core/libs/prx/libScePosixForWebKit/Resolver.cpp) (libScePosixForWebKit) searches a built-in copy of 37 lines of FreeBSD 11.4's [etc/services](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/etc/services) (ftp-data, ftp, ssh, telnet, smtp, domain, tftp, http, pop3, ntp, imap, https, rtsp, submission, imaps, pop3s with their aliases and protocols, in file order) the way [getservent.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/net/getservent.c) searches the file: case-sensitive name or alias, a null protocol takes the first match, the port in network byte order, the result in per-thread storage. The console's `/etc/services` is unknown, so any other service returns null without setting `errno`, as for a name the file lacks. `getaddrinfo` still resolves service names through the host's service database
|
||||
- [__wrap_access, __wrap_clock_gettime, __wrap_getcwd, __wrap_getenv, __wrap_lstat and __wrap_mmap](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) assume, from the export names alone, the GNU ld [`--wrap`](https://sourceware.org/binutils/docs/ld/Options.html) convention (a reference to `<name>` resolves to `__wrap_<name>`): each takes its target's POSIX signature and forwards to libc's (`access`, `getcwd`, `getenv`) or libkernel's (`clock_gettime`, `lstat`, `mmap`) implementation, which sets `errno`. No PS5 module or WebKit call site was read to confirm that WebKit imports `__wrap_<name>` in place of `<name>` or that the console wrappers only forward. Any sandbox or path handling the console module adds is not modelled, and how the wrappers relate to `getenv_np`, `setenv_np`, `mmap_np` and `clock_gettime_np` (such as a separate environment that `setenv_np` fills) is unknown
|
||||
|
||||
- [getaddrinfo raw-socket hints](../../../core/libs/prx/libScePosixForWebKit/Resolver.cpp) follow FreeBSD 11.4's [raw exploration entries and service rejection](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/net/getaddrinfo.c#L173-L196): an explicit raw type preserves any protocol number and forbids a non-null service. Address lookup uses the host's datagram resolver path with no service, then produces guest raw records with zero ports. PS5 execution is unverified; host DNS policy, address ordering, default-hint records and flag behavior can still differ from FreeBSD.
|
||||
Reference in new issue
Block a user