mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
pm: add api for ams.mitm to steal application memory
This commit is contained in:
parent
e1c4523c41
commit
9b480e4757
11 changed files with 114 additions and 52 deletions
|
@ -30,7 +30,8 @@
|
|||
AMS_SF_METHOD_INFO(C, H, 7, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, BoostApplicationThreadResourceLimit, (), ()) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, void, GetBootFinishedEventHandle, (sf::OutCopyHandle out), (out), hos::Version_8_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ())
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ()) \
|
||||
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereBoostSystemMemoryResourceLimitForMitm, (u64 boost_size), (boost_size))
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0)
|
||||
|
||||
|
@ -44,6 +45,8 @@ AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE
|
|||
AMS_SF_METHOD_INFO(C, H, 6, Result, ClearExceptionOccurred, (os::ProcessId process_id), (process_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, void, NotifyBootFinished, (), ()) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, GetApplicationProcessIdForShell, (sf::Out<os::ProcessId> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size), hos::Version_4_0_0)
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size), hos::Version_4_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ()) \
|
||||
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereBoostSystemMemoryResourceLimitForMitm, (u64 boost_size), (boost_size))
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IDeprecatedShellInterface, AMS_PM_I_DEPRECATED_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0)
|
||||
|
|
|
@ -32,4 +32,6 @@ namespace ams::pm::shell {
|
|||
Result BoostApplicationThreadResourceLimit();
|
||||
Result BoostSystemThreadResourceLimit();
|
||||
|
||||
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size);
|
||||
|
||||
}
|
||||
|
|
|
@ -90,3 +90,9 @@ Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size) {
|
||||
return serviceDispatchIn(pmshellGetServiceSession(), 65000, size);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ Result pminfoAtmosphereGetProcessInfo(NcmProgramLocation *loc_out, CfgOverrideSt
|
|||
Result pmdmntAtmosphereGetProcessInfo(Handle *out, NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
|
||||
Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource);
|
||||
|
||||
Result pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "pm_ams.os.horizon.h"
|
||||
|
||||
namespace ams::pm::shell {
|
||||
|
||||
|
@ -57,6 +58,10 @@ namespace ams::pm::shell {
|
|||
Result BoostSystemThreadResourceLimit() {
|
||||
R_RETURN(::pmshellBoostSystemThreadResourceLimit());
|
||||
}
|
||||
|
||||
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size) {
|
||||
R_RETURN(pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(size));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -713,4 +713,8 @@ namespace ams::pm::impl {
|
|||
R_RETURN(resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource)));
|
||||
}
|
||||
|
||||
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
|
||||
R_RETURN(resource::BoostSystemMemoryResourceLimitForMitm(boost_size));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,5 +55,6 @@ namespace ams::pm::impl {
|
|||
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out);
|
||||
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out);
|
||||
Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource);
|
||||
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size);
|
||||
|
||||
}
|
||||
|
|
|
@ -52,9 +52,16 @@ namespace ams::pm::resource {
|
|||
constinit os::SdkMutex g_resource_limit_lock;
|
||||
constinit os::NativeHandle g_resource_limit_handles[ResourceLimitGroup_Count];
|
||||
constinit spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard;
|
||||
constinit u64 g_system_memory_boost_size = 0;
|
||||
constinit u64 g_extra_threads_available[ResourceLimitGroup_Count];
|
||||
|
||||
constinit os::SdkMutex g_system_memory_boost_lock;
|
||||
constinit u64 g_system_memory_boost_size = 0;
|
||||
constinit u64 g_system_memory_boost_size_for_mitm = 0;
|
||||
|
||||
ALWAYS_INLINE u64 GetCurrentSystemMemoryBoostSize() {
|
||||
return g_system_memory_boost_size + g_system_memory_boost_size_for_mitm;
|
||||
}
|
||||
|
||||
constinit u64 g_resource_limits[ResourceLimitGroup_Count][svc::LimitableResource_Count] = {
|
||||
[ResourceLimitGroup_System] = {
|
||||
[svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */
|
||||
|
@ -220,6 +227,47 @@ namespace ams::pm::resource {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result BoostSystemMemoryResourceLimitLocked(u64 normal_boost, u64 mitm_boost) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(g_system_memory_boost_lock.IsLockedByCurrentThread());
|
||||
|
||||
/* Determine total boost. */
|
||||
const u64 boost_size = normal_boost + mitm_boost;
|
||||
|
||||
/* Don't allow all application memory to be taken away. */
|
||||
R_UNLESS(boost_size <= g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application], pm::ResultInvalidSize());
|
||||
|
||||
const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size;
|
||||
{
|
||||
std::scoped_lock lk(g_resource_limit_lock);
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
/* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */
|
||||
if (boost_size < GetCurrentSystemMemoryBoostSize()) {
|
||||
R_TRY(svc::SetUnsafeLimit(boost_size));
|
||||
R_ABORT_UNLESS(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
} else {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
R_ABORT_UNLESS(svc::SetUnsafeLimit(boost_size));
|
||||
}
|
||||
} else {
|
||||
const u64 new_sys_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_System] + boost_size;
|
||||
if (boost_size < GetCurrentSystemMemoryBoostSize()) {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
} else {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
|
||||
}
|
||||
}
|
||||
|
||||
g_system_memory_boost_size = normal_boost;
|
||||
g_system_memory_boost_size_for_mitm = mitm_boost;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Resource API. */
|
||||
|
@ -352,37 +400,19 @@ namespace ams::pm::resource {
|
|||
}
|
||||
|
||||
Result BoostSystemMemoryResourceLimit(u64 boost_size) {
|
||||
/* Don't allow all application memory to be taken away. */
|
||||
R_UNLESS(boost_size <= g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application], pm::ResultInvalidSize());
|
||||
/* Ensure only one boost change happens at a time. */
|
||||
std::scoped_lock lk(g_system_memory_boost_lock);
|
||||
|
||||
const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size;
|
||||
{
|
||||
std::scoped_lock lk(g_resource_limit_lock);
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
/* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */
|
||||
if (boost_size < g_system_memory_boost_size) {
|
||||
R_TRY(svc::SetUnsafeLimit(boost_size));
|
||||
R_ABORT_UNLESS(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
} else {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
R_ABORT_UNLESS(svc::SetUnsafeLimit(boost_size));
|
||||
}
|
||||
} else {
|
||||
const u64 new_sys_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_System] + boost_size;
|
||||
if (boost_size < g_system_memory_boost_size) {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
} else {
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
|
||||
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
|
||||
}
|
||||
/* Boost to the appropriate total amount. */
|
||||
R_RETURN(BoostSystemMemoryResourceLimitLocked(boost_size, g_system_memory_boost_size_for_mitm));
|
||||
}
|
||||
|
||||
g_system_memory_boost_size = boost_size;
|
||||
}
|
||||
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
|
||||
/* Ensure only one boost change happens at a time. */
|
||||
std::scoped_lock lk(g_system_memory_boost_lock);
|
||||
|
||||
R_SUCCEED();
|
||||
/* Boost to the appropriate total amount. */
|
||||
R_RETURN(BoostSystemMemoryResourceLimitLocked(g_system_memory_boost_size, boost_size));
|
||||
}
|
||||
|
||||
Result BoostApplicationThreadResourceLimit() {
|
||||
|
|
|
@ -24,6 +24,8 @@ namespace ams::pm::resource {
|
|||
Result BoostApplicationThreadResourceLimit();
|
||||
Result BoostSystemThreadResourceLimit();
|
||||
|
||||
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size);
|
||||
|
||||
os::NativeHandle GetResourceLimitHandle(ResourceLimitGroup group);
|
||||
os::NativeHandle GetResourceLimitHandle(const ldr::ProgramInfo *info);
|
||||
|
||||
|
|
|
@ -87,4 +87,8 @@ namespace ams::pm {
|
|||
R_RETURN(impl::BoostSystemThreadResourceLimit());
|
||||
}
|
||||
|
||||
Result ShellService::AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
|
||||
R_RETURN(impl::BoostSystemMemoryResourceLimitForMitm(boost_size));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace ams::pm {
|
|||
Result BoostApplicationThreadResourceLimit();
|
||||
void GetBootFinishedEventHandle(sf::OutCopyHandle out);
|
||||
Result BoostSystemThreadResourceLimit();
|
||||
|
||||
/* Atmosphere extension command implementations. */
|
||||
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 boost_size);
|
||||
};
|
||||
static_assert(pm::impl::IsIShellInterface<ShellService>);
|
||||
|
||||
|
|
Loading…
Reference in a new issue