Socket: Fix a nullptr dereference when operations are pending
This commit is contained in:
parent
57327be7f3
commit
e9fa335fbe
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue