From aef8e69b9ed4b82cbbfd6ed2fb44b8394e8fe7ef Mon Sep 17 00:00:00 2001 From: Inviuz Date: Mon, 3 Apr 2017 23:16:14 +0200 Subject: [PATCH 1/3] cellSave fix plus bugfixes allows allocation of last byte in memory block prevents rpcs3 from crashing when closing non existent socket --- rpcs3/Emu/Cell/Modules/cellSaveData.cpp | 13 +++++++++++++ rpcs3/Emu/Cell/Modules/sys_net.cpp | 6 ++++++ rpcs3/Emu/Memory/vm.cpp | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index d6b14e6e3b74..83efacf35adf 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -307,6 +307,10 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version, return CELL_OK; // ??? } } + if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)) + { + return CELL_OK; + } } if (funcFixed) @@ -338,6 +342,10 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version, { save_entry.dirName = fixedSet->dirName.get_ptr(); } + if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)) + { + return CELL_OK; + } } if (selected >= 0) @@ -519,6 +527,11 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version, } } + if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)) + { + return CELL_OK; + } + // Create save directory if necessary if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path)) { diff --git a/rpcs3/Emu/Cell/Modules/sys_net.cpp b/rpcs3/Emu/Cell/Modules/sys_net.cpp index 9400683f8b41..521635ec9b75 100644 --- a/rpcs3/Emu/Cell/Modules/sys_net.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_net.cpp @@ -723,6 +723,12 @@ namespace sys_net libnet.warning("socketclose(s=%d)", s); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("socketclose(): socket does not exist, or was already closed"); + return -1; + } + #ifdef _WIN32 s32 ret = ::closesocket(sock->s); #else diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 2137fbcd38e1..edf3376ee4b2 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -621,7 +621,7 @@ namespace vm size = ::align(size, 4096); // return if addr or size is invalid - if (!size || size > this->size || addr < this->addr || addr + size - 1 >= this->addr + this->size - 1) + if (!size || size > this->size || addr < this->addr || addr + size - 1 >= this->addr + this->size) { return 0; } From e127df29b157712364da08eb94fbac4d41efcb52 Mon Sep 17 00:00:00 2001 From: Inviuz Date: Tue, 4 Apr 2017 00:15:29 +0200 Subject: [PATCH 2/3] Fix overflow --- rpcs3/Emu/Memory/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index edf3376ee4b2..4f6aa8a2188a 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -621,7 +621,7 @@ namespace vm size = ::align(size, 4096); // return if addr or size is invalid - if (!size || size > this->size || addr < this->addr || addr + size - 1 >= this->addr + this->size) + if (!size || size > this->size || addr < this->addr || addr + size - 1 > this->addr + this->size -1) { return 0; } From a65766d184d59ba410c97211f104354bb38abc5b Mon Sep 17 00:00:00 2001 From: Inviuz Date: Tue, 4 Apr 2017 12:57:58 +0200 Subject: [PATCH 3/3] add more socket options fix typo prevent sys_net from operating on nullptr sockets --- rpcs3/Emu/Cell/Modules/sys_net.cpp | 66 ++++++++++++++++++++++++++++++ rpcs3/Emu/Memory/vm.cpp | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/Modules/sys_net.cpp b/rpcs3/Emu/Cell/Modules/sys_net.cpp index 521635ec9b75..ccbcfbc627b9 100644 --- a/rpcs3/Emu/Cell/Modules/sys_net.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_net.cpp @@ -222,6 +222,12 @@ namespace sys_net libnet.warning("accept(s=%d, family=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("accept(): socket does not exist"); + return -1; + } + s32 ret; if (!addr) @@ -261,6 +267,12 @@ namespace sys_net libnet.warning("bind(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("bind(): socket does not exist"); + return -1; + } + ::sockaddr_in saddr; memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in)); saddr.sin_family = addr->sa_family; @@ -282,6 +294,12 @@ namespace sys_net libnet.warning("connect(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("connect(): socket does not exist"); + return -1; + } + ::sockaddr_in saddr; memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in)); saddr.sin_family = addr->sa_family; @@ -406,6 +424,12 @@ namespace sys_net libnet.warning("listen(s=%d, backlog=%d)", s, backlog); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("listen(): socket does not exist"); + return -1; + } + s32 ret = ::listen(sock->s, backlog); if (ret != 0) @@ -422,6 +446,12 @@ namespace sys_net libnet.warning("recv(s=%d, buf=*0x%x, len=%d, flags=0x%x)", s, buf, len, flags); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("recv(): socket does not exist"); + return -1; + } + s32 ret = ::recv(sock->s, buf.get_ptr(), len, flags); if (ret < 0) @@ -478,6 +508,12 @@ namespace sys_net libnet.warning("send(s=%d, buf=*0x%x, len=%d, flags=0x%x)", s, buf, len, flags); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("send(): socket does not exist"); + return -1; + } + s32 ret = ::send(sock->s, buf.get_ptr(), len, flags); if (ret < 0) @@ -500,6 +536,12 @@ namespace sys_net libnet.warning("sendto(s=%d, buf=*0x%x, len=%d, flags=0x%x, addr=*0x%x, addrlen=%d)", s, buf, len, flags, addr, addrlen); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("sendto(): socket does not exist"); + return -1; + } + ::sockaddr _addr; memcpy(&_addr, addr.get_ptr(), sizeof(::sockaddr)); _addr.sa_family = addr->sa_family; @@ -519,6 +561,12 @@ namespace sys_net libnet.warning("setsockopt(s=%d, level=%d, optname=%d, optval=*0x%x, optlen=%d)", s, level, optname, optval, optlen); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("setsockopt(): socket does not exist"); + return -1; + } + if (level != SOL_SOCKET && level != IPPROTO_TCP) { fmt::throw_exception("Invalid socket option level!" HERE); @@ -583,6 +631,18 @@ namespace sys_net libnet.warning("Socket option OP_SO_USESIGNATURE is unimplemented"); break; } + case OP_SO_BROADCAST: + { + u32 enablebroadcast = *(u32*)optval.get_ptr(); + ret = ::setsockopt(sock->s, SOL_SOCKET, SO_BROADCAST, (char*)&enablebroadcast, sizeof(enablebroadcast)); + break; + } + case OP_SO_REUSEADDR: + { + u32 reuseaddr = *(u32*)optval.get_ptr(); + ret = ::setsockopt(sock->s, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof(reuseaddr)); + break; + } default: libnet.error("Unknown socket option for Win32: 0x%x", optname); } @@ -673,6 +733,12 @@ namespace sys_net libnet.warning("shutdown(s=%d, how=%d)", s, how); std::shared_ptr sock = idm::get(s); + if (!sock) + { + libnet.error("shutdown(): non existent socket cannot be shutdown"); + return -1; + } + s32 ret = ::shutdown(sock->s, how); if (ret != 0) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 4f6aa8a2188a..ee8ec91a10d4 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -621,7 +621,7 @@ namespace vm size = ::align(size, 4096); // return if addr or size is invalid - if (!size || size > this->size || addr < this->addr || addr + size - 1 > this->addr + this->size -1) + if (!size || size > this->size || addr < this->addr || addr + size - 1 > this->addr + this->size - 1) { return 0; }