diff options
| author | 2023-11-04 11:14:08 -0400 | |
|---|---|---|
| committer | 2023-11-04 11:14:08 -0400 | |
| commit | f0cd02b9bda051c3d13e21d38771d4c115f812e6 (patch) | |
| tree | 50d4d7403039590505d26ec734b7cb552c87765d | |
| parent | Merge pull request #11885 from liamwhite/stop-nagging-me (diff) | |
| parent | sockets: use safe access helpers (diff) | |
| download | yuzu-f0cd02b9bda051c3d13e21d38771d4c115f812e6.tar.gz yuzu-f0cd02b9bda051c3d13e21d38771d4c115f812e6.tar.xz yuzu-f0cd02b9bda051c3d13e21d38771d4c115f812e6.zip | |
Merge pull request #11881 from liamwhite/sockets-safe-access
sockets: use safe access helpers
| -rw-r--r-- | src/core/hle/service/sockets/bsd.cpp | 77 | ||||
| -rw-r--r-- | src/core/hle/service/sockets/bsd.h | 2 |
2 files changed, 38 insertions, 41 deletions
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 85849d5f3..dd652ca42 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp | |||
| @@ -39,6 +39,18 @@ bool IsConnectionBased(Type type) { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | template <typename T> | ||
| 43 | T GetValue(std::span<const u8> buffer) { | ||
| 44 | T t{}; | ||
| 45 | std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size())); | ||
| 46 | return t; | ||
| 47 | } | ||
| 48 | |||
| 49 | template <typename T> | ||
| 50 | void PutValue(std::span<u8> buffer, const T& t) { | ||
| 51 | std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size())); | ||
| 52 | } | ||
| 53 | |||
| 42 | } // Anonymous namespace | 54 | } // Anonymous namespace |
| 43 | 55 | ||
| 44 | void BSD::PollWork::Execute(BSD* bsd) { | 56 | void BSD::PollWork::Execute(BSD* bsd) { |
| @@ -316,22 +328,12 @@ void BSD::SetSockOpt(HLERequestContext& ctx) { | |||
| 316 | const s32 fd = rp.Pop<s32>(); | 328 | const s32 fd = rp.Pop<s32>(); |
| 317 | const u32 level = rp.Pop<u32>(); | 329 | const u32 level = rp.Pop<u32>(); |
| 318 | const OptName optname = static_cast<OptName>(rp.Pop<u32>()); | 330 | const OptName optname = static_cast<OptName>(rp.Pop<u32>()); |
| 319 | 331 | const auto optval = ctx.ReadBuffer(); | |
| 320 | const auto buffer = ctx.ReadBuffer(); | ||
| 321 | const u8* optval = buffer.empty() ? nullptr : buffer.data(); | ||
| 322 | size_t optlen = buffer.size(); | ||
| 323 | |||
| 324 | std::array<u64, 2> values; | ||
| 325 | if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) { | ||
| 326 | std::memcpy(values.data(), buffer.data(), sizeof(values)); | ||
| 327 | optlen = sizeof(values); | ||
| 328 | optval = reinterpret_cast<const u8*>(values.data()); | ||
| 329 | } | ||
| 330 | 332 | ||
| 331 | LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level, | 333 | LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level, |
| 332 | static_cast<u32>(optname), optlen); | 334 | static_cast<u32>(optname), optval.size()); |
| 333 | 335 | ||
| 334 | BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval)); | 336 | BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval)); |
| 335 | } | 337 | } |
| 336 | 338 | ||
| 337 | void BSD::Shutdown(HLERequestContext& ctx) { | 339 | void BSD::Shutdown(HLERequestContext& ctx) { |
| @@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco | |||
| 521 | 523 | ||
| 522 | std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, | 524 | std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, |
| 523 | s32 nfds, s32 timeout) { | 525 | s32 nfds, s32 timeout) { |
| 524 | if (write_buffer.size() < nfds * sizeof(PollFD)) { | 526 | if (nfds <= 0) { |
| 525 | return {-1, Errno::INVAL}; | ||
| 526 | } | ||
| 527 | |||
| 528 | if (nfds == 0) { | ||
| 529 | // When no entries are provided, -1 is returned with errno zero | 527 | // When no entries are provided, -1 is returned with errno zero |
| 530 | return {-1, Errno::SUCCESS}; | 528 | return {-1, Errno::SUCCESS}; |
| 531 | } | 529 | } |
| 530 | if (read_buffer.size() < nfds * sizeof(PollFD)) { | ||
| 531 | return {-1, Errno::INVAL}; | ||
| 532 | } | ||
| 533 | if (write_buffer.size() < nfds * sizeof(PollFD)) { | ||
| 534 | return {-1, Errno::INVAL}; | ||
| 535 | } | ||
| 532 | 536 | ||
| 533 | const size_t length = std::min(read_buffer.size(), write_buffer.size()); | ||
| 534 | std::vector<PollFD> fds(nfds); | 537 | std::vector<PollFD> fds(nfds); |
| 535 | std::memcpy(fds.data(), read_buffer.data(), length); | 538 | std::memcpy(fds.data(), read_buffer.data(), nfds * sizeof(PollFD)); |
| 536 | 539 | ||
| 537 | if (timeout >= 0) { | 540 | if (timeout >= 0) { |
| 538 | const s64 seconds = timeout / 1000; | 541 | const s64 seconds = timeout / 1000; |
| @@ -580,7 +583,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con | |||
| 580 | for (size_t i = 0; i < num; ++i) { | 583 | for (size_t i = 0; i < num; ++i) { |
| 581 | fds[i].revents = Translate(host_pollfds[i].revents); | 584 | fds[i].revents = Translate(host_pollfds[i].revents); |
| 582 | } | 585 | } |
| 583 | std::memcpy(write_buffer.data(), fds.data(), length); | 586 | std::memcpy(write_buffer.data(), fds.data(), nfds * sizeof(PollFD)); |
| 584 | 587 | ||
| 585 | return Translate(result); | 588 | return Translate(result); |
| 586 | } | 589 | } |
| @@ -608,8 +611,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) { | |||
| 608 | new_descriptor.is_connection_based = descriptor.is_connection_based; | 611 | new_descriptor.is_connection_based = descriptor.is_connection_based; |
| 609 | 612 | ||
| 610 | const SockAddrIn guest_addr_in = Translate(result.sockaddr_in); | 613 | const SockAddrIn guest_addr_in = Translate(result.sockaddr_in); |
| 611 | const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size()); | 614 | PutValue(write_buffer, guest_addr_in); |
| 612 | std::memcpy(write_buffer.data(), &guest_addr_in, length); | ||
| 613 | 615 | ||
| 614 | return {new_fd, Errno::SUCCESS}; | 616 | return {new_fd, Errno::SUCCESS}; |
| 615 | } | 617 | } |
| @@ -619,8 +621,7 @@ Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) { | |||
| 619 | return Errno::BADF; | 621 | return Errno::BADF; |
| 620 | } | 622 | } |
| 621 | ASSERT(addr.size() == sizeof(SockAddrIn)); | 623 | ASSERT(addr.size() == sizeof(SockAddrIn)); |
| 622 | SockAddrIn addr_in; | 624 | auto addr_in = GetValue<SockAddrIn>(addr); |
| 623 | std::memcpy(&addr_in, addr.data(), sizeof(addr_in)); | ||
| 624 | 625 | ||
| 625 | return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); | 626 | return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); |
| 626 | } | 627 | } |
| @@ -631,8 +632,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) { | |||
| 631 | } | 632 | } |
| 632 | 633 | ||
| 633 | UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); | 634 | UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); |
| 634 | SockAddrIn addr_in; | 635 | auto addr_in = GetValue<SockAddrIn>(addr); |
| 635 | std::memcpy(&addr_in, addr.data(), sizeof(addr_in)); | ||
| 636 | 636 | ||
| 637 | return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); | 637 | return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); |
| 638 | } | 638 | } |
| @@ -650,7 +650,7 @@ Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) { | |||
| 650 | 650 | ||
| 651 | ASSERT(write_buffer.size() >= sizeof(guest_addrin)); | 651 | ASSERT(write_buffer.size() >= sizeof(guest_addrin)); |
| 652 | write_buffer.resize(sizeof(guest_addrin)); | 652 | write_buffer.resize(sizeof(guest_addrin)); |
| 653 | std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); | 653 | PutValue(write_buffer, guest_addrin); |
| 654 | return Translate(bsd_errno); | 654 | return Translate(bsd_errno); |
| 655 | } | 655 | } |
| 656 | 656 | ||
| @@ -667,7 +667,7 @@ Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) { | |||
| 667 | 667 | ||
| 668 | ASSERT(write_buffer.size() >= sizeof(guest_addrin)); | 668 | ASSERT(write_buffer.size() >= sizeof(guest_addrin)); |
| 669 | write_buffer.resize(sizeof(guest_addrin)); | 669 | write_buffer.resize(sizeof(guest_addrin)); |
| 670 | std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); | 670 | PutValue(write_buffer, guest_addrin); |
| 671 | return Translate(bsd_errno); | 671 | return Translate(bsd_errno); |
| 672 | } | 672 | } |
| 673 | 673 | ||
| @@ -725,7 +725,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o | |||
| 725 | optval.size() == sizeof(Errno), { return Errno::INVAL; }, | 725 | optval.size() == sizeof(Errno), { return Errno::INVAL; }, |
| 726 | "Incorrect getsockopt option size"); | 726 | "Incorrect getsockopt option size"); |
| 727 | optval.resize(sizeof(Errno)); | 727 | optval.resize(sizeof(Errno)); |
| 728 | memcpy(optval.data(), &translated_pending_err, sizeof(Errno)); | 728 | PutValue(optval, translated_pending_err); |
| 729 | } | 729 | } |
| 730 | return Translate(getsockopt_err); | 730 | return Translate(getsockopt_err); |
| 731 | } | 731 | } |
| @@ -735,7 +735,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o | |||
| 735 | } | 735 | } |
| 736 | } | 736 | } |
| 737 | 737 | ||
| 738 | Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) { | 738 | Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) { |
| 739 | if (!IsFileDescriptorValid(fd)) { | 739 | if (!IsFileDescriptorValid(fd)) { |
| 740 | return Errno::BADF; | 740 | return Errno::BADF; |
| 741 | } | 741 | } |
| @@ -748,17 +748,15 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con | |||
| 748 | Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); | 748 | Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); |
| 749 | 749 | ||
| 750 | if (optname == OptName::LINGER) { | 750 | if (optname == OptName::LINGER) { |
| 751 | ASSERT(optlen == sizeof(Linger)); | 751 | ASSERT(optval.size() == sizeof(Linger)); |
| 752 | Linger linger; | 752 | auto linger = GetValue<Linger>(optval); |
| 753 | std::memcpy(&linger, optval, sizeof(linger)); | ||
| 754 | ASSERT(linger.onoff == 0 || linger.onoff == 1); | 753 | ASSERT(linger.onoff == 0 || linger.onoff == 1); |
| 755 | 754 | ||
| 756 | return Translate(socket->SetLinger(linger.onoff != 0, linger.linger)); | 755 | return Translate(socket->SetLinger(linger.onoff != 0, linger.linger)); |
| 757 | } | 756 | } |
| 758 | 757 | ||
| 759 | ASSERT(optlen == sizeof(u32)); | 758 | ASSERT(optval.size() == sizeof(u32)); |
| 760 | u32 value; | 759 | auto value = GetValue<u32>(optval); |
| 761 | std::memcpy(&value, optval, sizeof(value)); | ||
| 762 | 760 | ||
| 763 | switch (optname) { | 761 | switch (optname) { |
| 764 | case OptName::REUSEADDR: | 762 | case OptName::REUSEADDR: |
| @@ -862,7 +860,7 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess | |||
| 862 | } else { | 860 | } else { |
| 863 | ASSERT(addr.size() == sizeof(SockAddrIn)); | 861 | ASSERT(addr.size() == sizeof(SockAddrIn)); |
| 864 | const SockAddrIn result = Translate(addr_in); | 862 | const SockAddrIn result = Translate(addr_in); |
| 865 | std::memcpy(addr.data(), &result, sizeof(result)); | 863 | PutValue(addr, result); |
| 866 | } | 864 | } |
| 867 | } | 865 | } |
| 868 | 866 | ||
| @@ -886,8 +884,7 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> mes | |||
| 886 | Network::SockAddrIn* p_addr_in = nullptr; | 884 | Network::SockAddrIn* p_addr_in = nullptr; |
| 887 | if (!addr.empty()) { | 885 | if (!addr.empty()) { |
| 888 | ASSERT(addr.size() == sizeof(SockAddrIn)); | 886 | ASSERT(addr.size() == sizeof(SockAddrIn)); |
| 889 | SockAddrIn guest_addr_in; | 887 | auto guest_addr_in = GetValue<SockAddrIn>(addr); |
| 890 | std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in)); | ||
| 891 | addr_in = Translate(guest_addr_in); | 888 | addr_in = Translate(guest_addr_in); |
| 892 | p_addr_in = &addr_in; | 889 | p_addr_in = &addr_in; |
| 893 | } | 890 | } |
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 161f22b9b..4f69d382c 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h | |||
| @@ -163,7 +163,7 @@ private: | |||
| 163 | Errno ListenImpl(s32 fd, s32 backlog); | 163 | Errno ListenImpl(s32 fd, s32 backlog); |
| 164 | std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); | 164 | std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); |
| 165 | Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval); | 165 | Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval); |
| 166 | Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval); | 166 | Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval); |
| 167 | Errno ShutdownImpl(s32 fd, s32 how); | 167 | Errno ShutdownImpl(s32 fd, s32 how); |
| 168 | std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); | 168 | std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); |
| 169 | std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, | 169 | std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, |