Socket: Fix a nullptr dereference when operations are pending

This commit is contained in:
Sepalani 2023-12-23 23:28:49 +04:00
parent 57327be7f3
commit e9fa335fbe
3 changed files with 24 additions and 16 deletions

View File

@ -573,7 +573,7 @@ void EmulationKernel::AddStaticDevices()
if (HasFeature(features, Feature::KD) || HasFeature(features, Feature::SO) || if (HasFeature(features, Feature::KD) || HasFeature(features, Feature::SO) ||
HasFeature(features, Feature::SSL)) HasFeature(features, Feature::SSL))
{ {
m_socket_manager = std::make_shared<IOS::HLE::WiiSockMan>(); m_socket_manager = std::make_shared<IOS::HLE::WiiSockMan>(*this);
} }
if (HasFeature(features, Feature::KD)) if (HasFeature(features, Feature::KD))
{ {

View File

@ -86,7 +86,9 @@ static s32 TranslateErrorCode(s32 native_error, bool is_rw)
} }
} }
WiiSockMan::WiiSockMan() = default; WiiSockMan::WiiSockMan(EmulationKernel& ios) : m_ios(ios)
{
}
WiiSockMan::~WiiSockMan() = default; WiiSockMan::~WiiSockMan() = default;
@ -176,19 +178,19 @@ s32 WiiSocket::Shutdown(u32 how)
{ {
case IOCTL_SO_ACCEPT: case IOCTL_SO_ACCEPT:
if (shut_write) if (shut_write)
op.Abort(-SO_EINVAL); Abort(&op, -SO_EINVAL);
break; break;
case IOCTL_SO_CONNECT: case IOCTL_SO_CONNECT:
if (shut_write && !nonBlock) if (shut_write && !nonBlock)
op.Abort(-SO_ENETUNREACH); Abort(&op, -SO_ENETUNREACH);
break; break;
case IOCTLV_SO_RECVFROM: case IOCTLV_SO_RECVFROM:
if (shut_read) if (shut_read)
op.Abort(-SO_ENOTCONN); Abort(&op, -SO_ENOTCONN);
break; break;
case IOCTLV_SO_SENDTO: case IOCTLV_SO_SENDTO:
if (shut_write) if (shut_write)
op.Abort(-SO_ENOTCONN); Abort(&op, -SO_ENOTCONN);
break; break;
default: default:
break; break;
@ -213,7 +215,7 @@ s32 WiiSocket::CloseFd()
for (auto it = pending_sockops.begin(); it != pending_sockops.end();) for (auto it = pending_sockops.begin(); it != pending_sockops.end();)
{ {
GetIOS()->EnqueueIPCReply(it->request, -SO_ENOTCONN); m_socket_manager.EnqueueIPCReply(it->request, -SO_ENOTCONN);
it = pending_sockops.erase(it); it = pending_sockops.erase(it);
} }
connecting_state = ConnectingState::None; connecting_state = ConnectingState::None;
@ -705,8 +707,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
wii_fd, it->is_ssl ? static_cast<int>(it->ssl_type) : static_cast<int>(it->net_type), wii_fd, it->is_ssl ? static_cast<int>(it->ssl_type) : static_cast<int>(it->net_type),
ReturnValue, nonBlock, forceNonBlock); ReturnValue, nonBlock, forceNonBlock);
// TODO: remove the dependency on a running IOS instance. m_socket_manager.EnqueueIPCReply(it->request, ReturnValue);
GetIOS()->EnqueueIPCReply(it->request, ReturnValue);
it = pending_sockops.erase(it); it = pending_sockops.erase(it);
} }
else else
@ -974,6 +975,11 @@ s32 WiiSockMan::DeleteSocket(s32 wii_fd)
return ReturnValue; return ReturnValue;
} }
void WiiSockMan::EnqueueIPCReply(const Request& request, s32 return_value) const
{
m_ios.EnqueueIPCReply(request, return_value);
}
void WiiSockMan::Update() void WiiSockMan::Update()
{ {
s32 nfds = 0; s32 nfds = 0;
@ -1099,7 +1105,7 @@ void WiiSockMan::UpdatePollCommands()
DEBUG_LOG_FMT(IOS_NET, "IOCTL_SO_POLL socket {} wevents {:08X} events {:08X} revents {:08X}", DEBUG_LOG_FMT(IOS_NET, "IOCTL_SO_POLL socket {} wevents {:08X} events {:08X} revents {:08X}",
i, revents, pfds[i].events, pfds[i].revents); i, revents, pfds[i].events, pfds[i].revents);
} }
GetIOS()->EnqueueIPCReply(request, ret); EnqueueIPCReply(request, ret);
return true; return true;
}); });
} }
@ -1195,10 +1201,10 @@ void WiiSockMan::UpdateWantDeterminism(bool want)
Clean(); Clean();
} }
void WiiSocket::sockop::Abort(s32 value) void WiiSocket::Abort(WiiSocket::sockop* op, s32 value) const
{ {
is_aborted = true; op->is_aborted = true;
GetIOS()->EnqueueIPCReply(request, value); m_socket_manager.EnqueueIPCReply(op->request, value);
} }
#undef ERRORCODE #undef ERRORCODE
#undef EITHER #undef EITHER

View File

@ -199,7 +199,6 @@ private:
NET_IOCTL net_type; NET_IOCTL net_type;
SSL_IOCTL ssl_type; SSL_IOCTL ssl_type;
}; };
void Abort(s32 value);
}; };
enum class ConnectingState enum class ConnectingState
@ -216,6 +215,7 @@ private:
s32 Shutdown(u32 how); s32 Shutdown(u32 how);
s32 CloseFd(); s32 CloseFd();
s32 FCntl(u32 cmd, u32 arg); s32 FCntl(u32 cmd, u32 arg);
void Abort(sockop* op, s32 value) const;
const Timeout& GetTimeout(); const Timeout& GetTimeout();
void ResetTimeout(); void ResetTimeout();
@ -256,7 +256,7 @@ public:
s64 timeout = 0; s64 timeout = 0;
}; };
WiiSockMan(); explicit WiiSockMan(EmulationKernel& ios);
WiiSockMan(const WiiSockMan&) = delete; WiiSockMan(const WiiSockMan&) = delete;
WiiSockMan& operator=(const WiiSockMan&) = delete; WiiSockMan& operator=(const WiiSockMan&) = delete;
WiiSockMan(WiiSockMan&&) = delete; WiiSockMan(WiiSockMan&&) = delete;
@ -283,6 +283,7 @@ public:
s32 GetLastNetError() const { return errno_last; } s32 GetLastNetError() const { return errno_last; }
void SetLastNetError(s32 error) { errno_last = error; } void SetLastNetError(s32 error) { errno_last = error; }
void Clean() { WiiSockets.clear(); } void Clean() { WiiSockets.clear(); }
void EnqueueIPCReply(const Request& request, s32 return_value) const;
template <typename T> template <typename T>
void DoSock(s32 sock, const Request& request, T type) void DoSock(s32 sock, const Request& request, T type)
{ {
@ -291,7 +292,7 @@ public:
{ {
ERROR_LOG_FMT(IOS_NET, "DoSock: Error, fd not found ({:08x}, {:08X}, {:08X})", sock, ERROR_LOG_FMT(IOS_NET, "DoSock: Error, fd not found ({:08x}, {:08X}, {:08X})", sock,
request.address, Common::ToUnderlying(type)); request.address, Common::ToUnderlying(type));
GetIOS()->EnqueueIPCReply(request, -SO_EBADF); EnqueueIPCReply(request, -SO_EBADF);
} }
else else
{ {
@ -304,6 +305,7 @@ public:
private: private:
void UpdatePollCommands(); void UpdatePollCommands();
EmulationKernel& m_ios;
std::unordered_map<s32, WiiSocket> WiiSockets; std::unordered_map<s32, WiiSocket> WiiSockets;
s32 errno_last = 0; s32 errno_last = 0;
std::vector<PollCommand> pending_polls; std::vector<PollCommand> pending_polls;