Skip to content

Commit

Permalink
Socket: Fix a nullptr dereference when operations are pending
Browse files Browse the repository at this point in the history
  • Loading branch information
sepalani committed Dec 23, 2023
1 parent 57327be commit 79ee8e4
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Source/Core/Core/IOS/IOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ void EmulationKernel::AddStaticDevices()
if (HasFeature(features, Feature::KD) || HasFeature(features, Feature::SO) ||
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))
{
Expand Down
30 changes: 18 additions & 12 deletions Source/Core/Core/IOS/Network/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -176,19 +178,19 @@ s32 WiiSocket::Shutdown(u32 how)
{
case IOCTL_SO_ACCEPT:
if (shut_write)
op.Abort(-SO_EINVAL);
Abort(&op, -SO_EINVAL);
break;
case IOCTL_SO_CONNECT:
if (shut_write && !nonBlock)
op.Abort(-SO_ENETUNREACH);
Abort(&op, -SO_ENETUNREACH);
break;
case IOCTLV_SO_RECVFROM:
if (shut_read)
op.Abort(-SO_ENOTCONN);
Abort(&op, -SO_ENOTCONN);
break;
case IOCTLV_SO_SENDTO:
if (shut_write)
op.Abort(-SO_ENOTCONN);
Abort(&op, -SO_ENOTCONN);
break;
default:
break;
Expand All @@ -213,7 +215,7 @@ s32 WiiSocket::CloseFd()

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);
}
connecting_state = ConnectingState::None;
Expand Down Expand Up @@ -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),
ReturnValue, nonBlock, forceNonBlock);

// TODO: remove the dependency on a running IOS instance.
GetIOS()->EnqueueIPCReply(it->request, ReturnValue);
m_socket_manager.EnqueueIPCReply(it->request, ReturnValue);
it = pending_sockops.erase(it);
}
else
Expand Down Expand Up @@ -974,6 +975,11 @@ s32 WiiSockMan::DeleteSocket(s32 wii_fd)
return ReturnValue;
}

void WiiSockMan::EnqueueIPCReply(const Request& request, s32 return_value) const
{
m_ios.EnqueueIPCReply(request, return_value);
}

void WiiSockMan::Update()
{
s32 nfds = 0;
Expand Down Expand Up @@ -1099,7 +1105,7 @@ void WiiSockMan::UpdatePollCommands()
DEBUG_LOG_FMT(IOS_NET, "IOCTL_SO_POLL socket {} wevents {:08X} events {:08X} revents {:08X}",
i, revents, pfds[i].events, pfds[i].revents);
}
GetIOS()->EnqueueIPCReply(request, ret);
EnqueueIPCReply(request, ret);
return true;
});
}
Expand Down Expand Up @@ -1195,10 +1201,10 @@ void WiiSockMan::UpdateWantDeterminism(bool want)
Clean();
}

void WiiSocket::sockop::Abort(s32 value)
void WiiSocket::Abort(WiiSocket::sockop* op, s32 value) const
{
is_aborted = true;
GetIOS()->EnqueueIPCReply(request, value);
op->is_aborted = true;
m_socket_manager.EnqueueIPCReply(op->request, value);
}
#undef ERRORCODE
#undef EITHER
Expand Down
8 changes: 5 additions & 3 deletions Source/Core/Core/IOS/Network/Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ class WiiSocket
NET_IOCTL net_type;
SSL_IOCTL ssl_type;
};
void Abort(s32 value);
};

enum class ConnectingState
Expand All @@ -216,6 +215,7 @@ class WiiSocket
s32 Shutdown(u32 how);
s32 CloseFd();
s32 FCntl(u32 cmd, u32 arg);
void Abort(sockop* op, s32 value) const;

const Timeout& GetTimeout();
void ResetTimeout();
Expand Down Expand Up @@ -256,7 +256,7 @@ class WiiSockMan
s64 timeout = 0;
};

WiiSockMan();
WiiSockMan(EmulationKernel& m_ios);
WiiSockMan(const WiiSockMan&) = delete;
WiiSockMan& operator=(const WiiSockMan&) = delete;
WiiSockMan(WiiSockMan&&) = delete;
Expand All @@ -283,6 +283,7 @@ class WiiSockMan
s32 GetLastNetError() const { return errno_last; }
void SetLastNetError(s32 error) { errno_last = error; }
void Clean() { WiiSockets.clear(); }
void EnqueueIPCReply(const Request& request, s32 return_value) const;
template <typename T>
void DoSock(s32 sock, const Request& request, T type)
{
Expand All @@ -291,7 +292,7 @@ class WiiSockMan
{
ERROR_LOG_FMT(IOS_NET, "DoSock: Error, fd not found ({:08x}, {:08X}, {:08X})", sock,
request.address, Common::ToUnderlying(type));
GetIOS()->EnqueueIPCReply(request, -SO_EBADF);
EnqueueIPCReply(request, -SO_EBADF);
}
else
{
Expand All @@ -304,6 +305,7 @@ class WiiSockMan
private:
void UpdatePollCommands();

EmulationKernel& m_ios;
std::unordered_map<s32, WiiSocket> WiiSockets;
s32 errno_last = 0;
std::vector<PollCommand> pending_polls;
Expand Down

0 comments on commit 79ee8e4

Please sign in to comment.