diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/k_process.cpp | 25 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.h | 7 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/service.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/sockets/bsd.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/service/sockets/bsd.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/ssl/ssl.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/service/ssl/ssl_backend_openssl.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/service/ssl/ssl_backend_schannel.cpp | 25 |
10 files changed, 64 insertions, 33 deletions
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index e573e2a57..703049ede 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -38,7 +38,7 @@ namespace { */ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, KProcessAddress stack_top) { - const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart(); + const KProcessAddress entry_point = owner_process.GetEntryPoint(); ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); KThread* thread = KThread::Create(system.Kernel()); @@ -358,6 +358,21 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: m_system_resource_size = metadata.GetSystemResourceSize(); m_image_size = code_size; + if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) { + // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large. + // However, some (buggy) programs/libraries like skyline incorrectly depend on the + // existence of ASLR pages before the entry point, so we will adjust the load address + // to point to about 2GiB into the ASLR region. + m_code_address = 0x8000'0000; + } else { + // All other processes can be mapped at the beginning of the code region. + if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is36Bit) { + m_code_address = 0x800'0000; + } else { + m_code_address = 0x20'0000; + } + } + KScopedResourceReservation memory_reservation( m_resource_limit, LimitableResource::PhysicalMemoryMax, code_size + m_system_resource_size); if (!memory_reservation.Succeeded()) { @@ -368,15 +383,15 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: // Initialize process address space if (const Result result{m_page_table.InitializeForProcess( metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application, - 0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), m_resource_limit, - m_kernel.System().ApplicationMemory())}; + this->GetEntryPoint(), code_size, std::addressof(m_kernel.GetAppSystemResource()), + m_resource_limit, m_kernel.System().ApplicationMemory())}; result.IsError()) { R_RETURN(result); } // Map process code region - if (const Result result{m_page_table.MapProcessCode(m_page_table.GetCodeRegionStart(), - code_size / PageSize, KMemoryState::Code, + if (const Result result{m_page_table.MapProcessCode(this->GetEntryPoint(), code_size / PageSize, + KMemoryState::Code, KMemoryPermission::None)}; result.IsError()) { R_RETURN(result); diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index c9b37e138..4fdeaf11a 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -177,6 +177,10 @@ public: return m_program_id; } + KProcessAddress GetEntryPoint() const { + return m_code_address; + } + /// Gets the resource limit descriptor for this process KResourceLimit* GetResourceLimit() const; @@ -485,6 +489,9 @@ private: /// Address indicating the location of the process' dedicated TLS region. KProcessAddress m_plr_address = 0; + /// Address indicating the location of the process's entry point. + KProcessAddress m_code_address = 0; + /// Random values for svcGetInfo RandomEntropy std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{}; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 4c1ea1a5b..508db7360 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -4,6 +4,7 @@ #include <utility> #include "common/assert.h" +#include "common/fs/fs.h" #include "common/fs/path_util.h" #include "common/settings.h" #include "core/core.h" @@ -154,10 +155,18 @@ Result VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, std::string src_path(Common::FS::SanitizePath(src_path_)); std::string dest_path(Common::FS::SanitizePath(dest_path_)); auto src = backing->GetFileRelative(src_path); + auto dst = backing->GetFileRelative(dest_path); if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { // Use more-optimized vfs implementation rename. - if (src == nullptr) + if (src == nullptr) { return FileSys::ERROR_PATH_NOT_FOUND; + } + + if (dst && Common::FS::Exists(dst->GetFullPath())) { + LOG_ERROR(Service_FS, "File at new_path={} already exists", dst->GetFullPath()); + return FileSys::ERROR_PATH_ALREADY_EXISTS; + } + if (!src->Rename(Common::FS::GetFilename(dest_path))) { // TODO(DarkLordZach): Find a better error code for this return ResultUnknown; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 07e570a9f..7d7bb8687 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -204,9 +204,11 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { if (!mapping->fixed) { auto& allocator{mapping->big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; u32 page_size_bits{mapping->big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; + u32 page_size{mapping->big_page ? vm.big_page_size : VM::YUZU_PAGESIZE}; + u64 aligned_size{Common::AlignUp(mapping->size, page_size)}; allocator.Free(static_cast<u32>(mapping->offset >> page_size_bits), - static_cast<u32>(mapping->size >> page_size_bits)); + static_cast<u32>(aligned_size >> page_size_bits)); } // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 45b2c43b7..d539ed0f4 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -79,8 +79,8 @@ protected: using HandlerFnP = void (Self::*)(HLERequestContext&); /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. - [[nodiscard]] std::scoped_lock<std::mutex> LockService() { - return std::scoped_lock{lock_service}; + [[nodiscard]] virtual std::unique_lock<std::mutex> LockService() { + return std::unique_lock{lock_service}; } /// System context that the service operates under. diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 11f8efbac..d8509c1dd 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -1029,6 +1029,11 @@ BSD::~BSD() { } } +std::unique_lock<std::mutex> BSD::LockService() { + // Do not lock socket IClient instances. + return {}; +} + BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { // clang-format off static const FunctionInfo functions[] = { diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 430edb97c..161f22b9b 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -186,6 +186,9 @@ private: // Callback identifier for the OnProxyPacketReceived event. Network::RoomMember::CallbackHandle<Network::ProxyPacket> proxy_packet_received; + +protected: + virtual std::unique_lock<std::mutex> LockService() override; }; class BSDCFG final : public ServiceFramework<BSDCFG> { diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 2cba9e5c9..6c8427b0d 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -139,7 +139,6 @@ private: bool do_not_close_socket = false; bool get_server_cert_chain = false; std::shared_ptr<Network::SocketBase> socket; - bool did_set_host_name = false; bool did_handshake = false; Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { @@ -174,11 +173,7 @@ private: Result SetHostNameImpl(const std::string& hostname) { LOG_DEBUG(Service_SSL, "called. hostname={}", hostname); ASSERT(!did_handshake); - Result res = backend->SetHostName(hostname); - if (res == ResultSuccess) { - did_set_host_name = true; - } - return res; + return backend->SetHostName(hostname); } Result SetVerifyOptionImpl(u32 option) { @@ -208,9 +203,6 @@ private: Result DoHandshakeImpl() { ASSERT_OR_EXECUTE(!did_handshake && socket, { return ResultNoSocket; }); - ASSERT_OR_EXECUTE_MSG( - did_set_host_name, { return ResultInternalError; }, - "Expected SetHostName before DoHandshake"); Result res = backend->DoHandshake(); did_handshake = res.IsSuccess(); return res; diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp index b2dd37cd4..5714e6f3c 100644 --- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp +++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp @@ -167,9 +167,8 @@ public: } ~SSLConnectionBackendOpenSSL() { - // these are null-tolerant: + // this is null-tolerant: SSL_free(ssl); - BIO_free(bio); } static void KeyLogCallback(const SSL* ssl, const char* line) { diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp index bda12b761..d834a0c1f 100644 --- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp +++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp @@ -31,9 +31,9 @@ CredHandle cred_handle; static void OneTimeInit() { schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; schannel_cred.dwFlags = - SCH_USE_STRONG_CRYPTO | // don't allow insecure protocols - SCH_CRED_AUTO_CRED_VALIDATION | // validate certs - SCH_CRED_NO_DEFAULT_CREDS; // don't automatically present a client certificate + SCH_USE_STRONG_CRYPTO | // don't allow insecure protocols + SCH_CRED_NO_SERVERNAME_CHECK | // don't validate server names + SCH_CRED_NO_DEFAULT_CREDS; // don't automatically present a client certificate // ^ I'm assuming that nobody would want to connect Yuzu to a // service that requires some OS-provided corporate client // certificate, and presenting one to some arbitrary server @@ -227,16 +227,15 @@ public: ciphertext_read_buf.size()); } - const SECURITY_STATUS ret = - InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt : nullptr, - // Caller ensured we have set a hostname: - const_cast<char*>(hostname.value().c_str()), req, - 0, // Reserved1 - 0, // TargetDataRep not used with Schannel - initial_call_done ? &input_desc : nullptr, - 0, // Reserved2 - initial_call_done ? nullptr : &ctxt, &output_desc, &attr, - nullptr); // ptsExpiry + char* hostname_ptr = hostname ? const_cast<char*>(hostname->c_str()) : nullptr; + const SECURITY_STATUS ret = InitializeSecurityContextA( + &cred_handle, initial_call_done ? &ctxt : nullptr, hostname_ptr, req, + 0, // Reserved1 + 0, // TargetDataRep not used with Schannel + initial_call_done ? &input_desc : nullptr, + 0, // Reserved2 + initial_call_done ? nullptr : &ctxt, &output_desc, &attr, + nullptr); // ptsExpiry if (output_buffers[0].pvBuffer) { const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer), |