sys_net: Fix sys_net_bnet_poll page faults

This commit is contained in:
Eladash 2020-04-12 09:47:33 +03:00 committed by Ani
parent 926e0467cf
commit 179a9b3bf0
1 changed files with 28 additions and 23 deletions

View File

@ -1767,8 +1767,12 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
u64 timeout = ms < 0 ? 0 : ms * 1000ull; u64 timeout = ms < 0 ? 0 : ms * 1000ull;
if (nfds) std::vector<sys_net_pollfd> fds_buf;
if (nfds > 0)
{ {
fds_buf.assign(fds.get_ptr(), fds.get_ptr() + nfds);
std::lock_guard nw_lock(g_fxo->get<network_context>()->s_nw_mutex); std::lock_guard nw_lock(g_fxo->get<network_context>()->s_nw_mutex);
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
@ -1781,26 +1785,26 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
for (s32 i = 0; i < nfds; i++) for (s32 i = 0; i < nfds; i++)
{ {
_fds[i].fd = -1; _fds[i].fd = -1;
fds[i].revents = 0; fds_buf[i].revents = 0;
if (fds[i].fd < 0) if (fds_buf[i].fd < 0)
{ {
continue; continue;
} }
if (auto sock = idm::check_unlocked<lv2_socket>(fds[i].fd)) if (auto sock = idm::check_unlocked<lv2_socket>(fds_buf[i].fd))
{ {
// Check for fake packet for dns interceptions // Check for fake packet for dns interceptions
const auto nph = g_fxo->get<named_thread<np_handler>>(); const auto nph = g_fxo->get<named_thread<np_handler>>();
if (fds[i].events & SYS_NET_POLLIN && nph->is_dns(fds[i].fd) && nph->is_dns_queue(fds[i].fd)) if (fds_buf[i].events & SYS_NET_POLLIN && nph->is_dns(fds_buf[i].fd) && nph->is_dns_queue(fds_buf[i].fd))
fds[i].revents |= SYS_NET_POLLIN; fds_buf[i].revents |= SYS_NET_POLLIN;
if (fds[i].events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR)) if (fds_buf[i].events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR))
sys_net.error("sys_net_bnet_poll(fd=%d): events=0x%x", fds[i].fd, fds[i].events); sys_net.error("sys_net_bnet_poll(fd=%d): events=0x%x", fds[i].fd, fds[i].events);
_fds[i].fd = sock->socket; _fds[i].fd = sock->socket;
if (fds[i].events & SYS_NET_POLLIN) if (fds_buf[i].events & SYS_NET_POLLIN)
_fds[i].events |= POLLIN; _fds[i].events |= POLLIN;
if (fds[i].events & SYS_NET_POLLOUT) if (fds_buf[i].events & SYS_NET_POLLOUT)
_fds[i].events |= POLLOUT; _fds[i].events |= POLLOUT;
#ifdef _WIN32 #ifdef _WIN32
connecting[i] = sock->is_connecting; connecting[i] = sock->is_connecting;
@ -1808,7 +1812,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
} }
else else
{ {
fds[i].revents |= SYS_NET_POLLNVAL; fds_buf[i].revents |= SYS_NET_POLLNVAL;
signaled++; signaled++;
} }
} }
@ -1821,13 +1825,13 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
for (s32 i = 0; i < nfds; i++) for (s32 i = 0; i < nfds; i++)
{ {
if (_fds[i].revents & (POLLIN | POLLHUP)) if (_fds[i].revents & (POLLIN | POLLHUP))
fds[i].revents |= SYS_NET_POLLIN; fds_buf[i].revents |= SYS_NET_POLLIN;
if (_fds[i].revents & POLLOUT) if (_fds[i].revents & POLLOUT)
fds[i].revents |= SYS_NET_POLLOUT; fds_buf[i].revents |= SYS_NET_POLLOUT;
if (_fds[i].revents & POLLERR) if (_fds[i].revents & POLLERR)
fds[i].revents |= SYS_NET_POLLERR; fds_buf[i].revents |= SYS_NET_POLLERR;
if (fds[i].revents) if (fds_buf[i].revents)
{ {
signaled++; signaled++;
} }
@ -1840,12 +1844,12 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
for (s32 i = 0; i < nfds; i++) for (s32 i = 0; i < nfds; i++)
{ {
if (fds[i].fd < 0) if (fds_buf[i].fd < 0)
{ {
continue; continue;
} }
if (auto sock = idm::check_unlocked<lv2_socket>(fds[i].fd)) if (auto sock = idm::check_unlocked<lv2_socket>(fds_buf[i].fd))
{ {
std::lock_guard lock(sock->mutex); std::lock_guard lock(sock->mutex);
@ -1855,24 +1859,24 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
bs_t<lv2_socket::poll> selected = +lv2_socket::poll::error; bs_t<lv2_socket::poll> selected = +lv2_socket::poll::error;
if (fds[i].events & SYS_NET_POLLIN) if (fds_buf[i].events & SYS_NET_POLLIN)
selected += lv2_socket::poll::read; selected += lv2_socket::poll::read;
if (fds[i].events & SYS_NET_POLLOUT) if (fds_buf[i].events & SYS_NET_POLLOUT)
selected += lv2_socket::poll::write; selected += lv2_socket::poll::write;
//if (fds[i].events & SYS_NET_POLLPRI) // Unimplemented //if (fds_buf[i].events & SYS_NET_POLLPRI) // Unimplemented
// selected += lv2_socket::poll::error; // selected += lv2_socket::poll::error;
sock->events += selected; sock->events += selected;
sock->queue.emplace_back(ppu.id, [sock, selected, fds, i, &signaled, &ppu](bs_t<lv2_socket::poll> events) sock->queue.emplace_back(ppu.id, [sock, selected, &fds_buf, i, &signaled, &ppu](bs_t<lv2_socket::poll> events)
{ {
if (events & selected) if (events & selected)
{ {
if (events & selected & lv2_socket::poll::read) if (events & selected & lv2_socket::poll::read)
fds[i].revents |= SYS_NET_POLLIN; fds_buf[i].revents |= SYS_NET_POLLIN;
if (events & selected & lv2_socket::poll::write) if (events & selected & lv2_socket::poll::write)
fds[i].revents |= SYS_NET_POLLOUT; fds_buf[i].revents |= SYS_NET_POLLOUT;
if (events & selected & lv2_socket::poll::error) if (events & selected & lv2_socket::poll::error)
fds[i].revents |= SYS_NET_POLLERR; fds_buf[i].revents |= SYS_NET_POLLERR;
signaled++; signaled++;
g_fxo->get<network_context>()->s_to_awake.emplace_back(&ppu); g_fxo->get<network_context>()->s_to_awake.emplace_back(&ppu);
@ -1926,6 +1930,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
} }
} }
std::memcpy(fds.get_ptr(), fds_buf.data(), nfds * sizeof(fds[0]));
return not_an_error(signaled); return not_an_error(signaled);
} }