From 97bef2992f6aadcea25429cf84868383cebc8e95 Mon Sep 17 00:00:00 2001 From: Chai T Date: Thu, 29 Oct 2026 08:39:30 +0100 Subject: [PATCH] appcontent: reject duplicate mounts without transferring ownership --- src/libs/libAppContent.cpp | 7 +++---- tests/KernelFileSystemTests.cpp | 9 ++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libs/libAppContent.cpp b/src/libs/libAppContent.cpp index 287b46a6b..4f947986a 100644 --- a/src/libs/libAppContent.cpp +++ b/src/libs/libAppContent.cpp @@ -32,6 +32,7 @@ namespace AppContent { constexpr uint32_t APP_CONTENT_APPPARAM_SKU_FLAG_FULL = 3; constexpr int APP_CONTENT_ERROR_PARAMETER = -2133262334; /* 0x80D90002 */ +constexpr int APP_CONTENT_ERROR_BUSY = -2133262333; /* 0x80D90003 */ constexpr int APP_CONTENT_ERROR_NOT_MOUNTED = -2133262332; /* 0x80D90004 */ constexpr int APP_CONTENT_ERROR_NOT_FOUND = -2133262331; /* 0x80D90005 */ constexpr int APP_CONTENT_ERROR_MOUNT_FULL = -2133262330; /* 0x80D90006 */ @@ -210,10 +211,8 @@ int KYTY_SYSV_ABI AppContentAddcontMount(uint32_t servic for (const auto& m: g_addcont_mounts) { if (m.label == entry->entitlement_label) { - const auto guest_point = m.point.substr(0, m.point.size() - 1); - std::strncpy(mount_point->data, guest_point.c_str(), sizeof(mount_point->data) - 1); - LOGF("\t already mounted %s\n", guest_point.c_str()); - return OK; + LOGF("\t already mounted %s\n", m.point.c_str()); + return APP_CONTENT_ERROR_BUSY; } } diff --git a/tests/KernelFileSystemTests.cpp b/tests/KernelFileSystemTests.cpp index 2bc64ac1b..c548983c5 100644 --- a/tests/KernelFileSystemTests.cpp +++ b/tests/KernelFileSystemTests.cpp @@ -577,17 +577,16 @@ void TestAddContent(const std::filesystem::path& root) { Check(mount(0, &info[3].label, &point) == OK && !std::string_view(point.data).ends_with('/'), "mount owned add-on without trailing slash"); + MountPoint repeated {}; + Check(mount(0, &info[3].label, &repeated) == static_cast(0x80d90003u), + "duplicate mount reports BUSY"); const std::string mounted_file = std::string(point.data) + "/payload.txt"; const int fd = FileSystem::KernelOpen(mounted_file.c_str(), 0, 0); std::array payload {}; Check(fd >= 3 && FileSystem::KernelRead(fd, payload.data(), payload.size()) == payload.size() && std::string_view(payload.data(), payload.size()) == "DLC payload" && FileSystem::KernelClose(fd) == OK, - "guest reads files from the selected title's add-on"); - MountPoint repeated {}; - Check(mount(0, &info[3].label, &repeated) == OK && - std::strcmp(repeated.data, point.data) == 0, - "duplicate mount returns the same mount point"); + "guest reads the original mount after a rejected duplicate mount"); Check(unmount(&point) == OK && FileSystem::GetRealFilename(mounted_file).empty() && unmount(&point) == static_cast(0x80d90004u), "unmount removes mapping and repeated unmount reports NOT_MOUNTED");