diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/file_sys/registered_cache.cpp | 37 | ||||
-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 | ||||
-rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 2 | ||||
-rw-r--r-- | src/core/loader/kip.cpp | 2 | ||||
-rw-r--r-- | src/core/loader/nro.cpp | 2 | ||||
-rw-r--r-- | src/core/loader/nso.cpp | 2 | ||||
-rw-r--r-- | src/core/reporter.cpp | 4 |
16 files changed, 98 insertions, 48 deletions
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index a28af3594..f70adab82 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -606,9 +606,9 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex const auto result = RemoveExistingEntry(title_id); // Install Metadata File - const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); - if (res != InstallResult::Success) { - return res; + const auto meta_result = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); + if (meta_result != InstallResult::Success) { + return meta_result; } // Install all the other NCAs @@ -621,9 +621,19 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex if (nca == nullptr) { return InstallResult::ErrorCopyFailed; } - const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); - if (res2 != InstallResult::Success) { - return res2; + if (nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && + nca->GetTitleId() != title_id) { + // Create fake cnmt for patch to multiprogram application + const auto sub_nca_result = + InstallEntry(*nca, TitleType::Update, overwrite_if_exists, copy); + if (sub_nca_result != InstallResult::Success) { + return sub_nca_result; + } + continue; + } + const auto nca_result = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); + if (nca_result != InstallResult::Success) { + return nca_result; } } @@ -663,6 +673,8 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, } bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { + bool removed_data = false; + const auto delete_nca = [this](const NcaID& id) { const auto path = GetRelativePathFromNcaID(id, false, true, false); @@ -706,11 +718,18 @@ bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { const auto deleted_html = delete_nca(html_id); const auto deleted_legal = delete_nca(legal_id); - return deleted_meta && (deleted_meta || deleted_program || deleted_data || - deleted_control || deleted_html || deleted_legal); + removed_data |= (deleted_meta || deleted_program || deleted_data || deleted_control || + deleted_html || deleted_legal); } - return false; + // If patch entries for any program exist in yuzu meta, remove them + for (u8 i = 0; i < 0x10; i++) { + const auto meta_dir = dir->CreateDirectoryRelative("yuzu_meta"); + const auto filename = GetCNMTName(TitleType::Update, title_id + i); + removed_data |= meta_dir->DeleteFile(filename); + } + + return removed_data; } InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, 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), diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index e04ad19db..f4eaf3331 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect // Load NSO modules modules.clear(); - const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())}; + const VAddr base_address{GetInteger(process.GetEntryPoint())}; VAddr next_load_addr{base_address}; const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider()}; diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index ffe976b94..d722459c6 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, } codeset.memory = std::move(program_image); - const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); + const VAddr base_address = GetInteger(process.GetEntryPoint()); process.LoadModule(std::move(codeset), base_address); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 506808b5d..d7562b4bc 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) // Load codeset for current process codeset.memory = std::move(program_image); - process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart()); + process.LoadModule(std::move(codeset), process.GetEntryPoint()); return true; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 74cc9579f..549822506 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S modules.clear(); // Load module - const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); + const VAddr base_address = GetInteger(process.GetEntryPoint()); if (!LoadModule(process, system, *file, base_address, true, true)) { return {ResultStatus::ErrorLoadingNSO, {}}; } diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index b5b3e7eda..ed875d444 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) { arm.SaveContext(context); return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", - GetInteger(process->GetPageTable().GetCodeRegionStart()), - context.sp, context.pc, context.pstate, context.cpu_registers); + GetInteger(process->GetEntryPoint()), context.sp, context.pc, + context.pstate, context.cpu_registers); } json GetBacktraceData(Core::System& system) { |