mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
os: update os namespace for 15.0.0, loader/ro: update to use csrng, spl: bump max sessions
This commit is contained in:
parent
dddb5bfdea
commit
d00406e089
30 changed files with 290 additions and 39 deletions
|
@ -28,6 +28,7 @@
|
|||
#include <stratosphere/os/os_process_handle_api.hpp>
|
||||
#include <stratosphere/os/os_process_memory_api.hpp>
|
||||
#include <stratosphere/os/os_process_code_memory_api.hpp>
|
||||
#include <stratosphere/os/os_insecure_memory_api.hpp>
|
||||
#include <stratosphere/os/os_random.hpp>
|
||||
#include <stratosphere/os/os_mutex.hpp>
|
||||
#include <stratosphere/os/os_condition_variable.hpp>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/os/os_memory_common.hpp>
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
Result AllocateInsecureMemory(uintptr_t *out_address, size_t size);
|
||||
void FreeInsecureMemory(uintptr_t address, size_t size);
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/os/os_interrupt_event_common.hpp>
|
||||
#include <stratosphere/os/os_native_handle.hpp>
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
|
@ -31,6 +32,8 @@ namespace ams::os {
|
|||
bool TimedWaitInterruptEvent(InterruptEventType *event, TimeSpan timeout);
|
||||
void ClearInterruptEvent(InterruptEventType *event);
|
||||
|
||||
NativeHandle GetInterruptEventHandle(const InterruptEventType *event);
|
||||
|
||||
void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterruptEventType *event);
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
namespace ams::os {
|
||||
|
||||
using AddressSpaceGenerateRandomFunction = u64 (*)(u64);
|
||||
|
||||
enum MemoryPermission {
|
||||
MemoryPermission_None = (0 << 0),
|
||||
MemoryPermission_ReadOnly = (1 << 0),
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace ams::os {
|
|||
u64 size;
|
||||
};
|
||||
|
||||
Result MapProcessCodeMemory(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions);
|
||||
Result MapProcessCodeMemory(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions, AddressSpaceGenerateRandomFunction generate_random);
|
||||
Result UnmapProcessCodeMemory(NativeHandle handle, u64 process_code_address, const ProcessMemoryRegion *regions, size_t num_regions);
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace ams::os {
|
||||
|
||||
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size);
|
||||
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size, AddressSpaceGenerateRandomFunction generate_random);
|
||||
void UnmapProcessMemory(void *mapped_memory, NativeHandle handle, u64 process_address, size_t process_size);
|
||||
|
||||
Result SetProcessMemoryPermission(NativeHandle handle, u64 process_address, u64 process_size, MemoryPermission perm);
|
||||
|
|
|
@ -503,6 +503,14 @@
|
|||
::svcCallSecureMonitor(reinterpret_cast<::SecmonArgs *>(args));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result MapInsecureMemory(::ams::svc::Address address, ::ams::svc::Size size) {
|
||||
R_RETURN(::svcMapInsecureMemory(reinterpret_cast<void *>(static_cast<uintptr_t>(address)), size));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result UnmapInsecureMemory(::ams::svc::Address address, ::ams::svc::Size size) {
|
||||
R_RETURN(::svcUnmapInsecureMemory(reinterpret_cast<void *>(static_cast<uintptr_t>(address)), size));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,24 @@
|
|||
|
||||
namespace ams::os::impl {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline u64 MaxProbabilityVariationInverseShift = 4;
|
||||
|
||||
}
|
||||
|
||||
u64 AddressSpaceAllocatorDefaultGenerateRandom(u64 max) {
|
||||
/* Check that max is in range. */
|
||||
AMS_ASSERT(max + 1 <= (UINT64_C(1) << (BITSIZEOF(u64) - MaxProbabilityVariationInverseShift)));
|
||||
|
||||
/* Generate random u64. */
|
||||
const u64 rand = GetRngManager().GenerateRandomU64();
|
||||
|
||||
/* Coerce into range. */
|
||||
AMS_ASSERT(max < std::numeric_limits<u64>::max());
|
||||
return rand % (max + 1);
|
||||
}
|
||||
|
||||
template<std::unsigned_integral AddressType, std::unsigned_integral SizeType>
|
||||
AddressSpaceAllocatorBase<AddressType, SizeType>::AddressSpaceAllocatorBase(u64 start_address, u64 end_address, SizeType guard_size, const AddressSpaceAllocatorForbiddenRegion *forbidden_regions, size_t num_forbidden_regions) : m_critical_section(), m_forbidden_region_count(0) {
|
||||
/* Check pre-conditions. */
|
||||
|
@ -64,7 +82,7 @@ namespace ams::os::impl {
|
|||
}
|
||||
|
||||
template<std::unsigned_integral AddressType, std::unsigned_integral SizeType>
|
||||
AddressType AddressSpaceAllocatorBase<AddressType, SizeType>::AllocateSpace(SizeType size, SizeType align, SizeType align_offset) {
|
||||
AddressType AddressSpaceAllocatorBase<AddressType, SizeType>::AllocateSpace(SizeType size, SizeType align, SizeType align_offset, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(align > 0);
|
||||
AMS_ASSERT((align_offset & ~(align - 1)) == 0);
|
||||
|
@ -98,7 +116,9 @@ namespace ams::os::impl {
|
|||
std::scoped_lock lk(m_critical_section);
|
||||
|
||||
/* Determine a random page. */
|
||||
const AddressType target = (((GetRngManager().GenerateRandomU64() % (rand_end - rand_start + 1)) + rand_start) * align_page_count) + align_offset_page_count;
|
||||
const u64 random = generate_random(rand_end - rand_start);
|
||||
|
||||
const AddressType target = ((random + rand_start) * align_page_count) + align_offset_page_count;
|
||||
AMS_ASSERT(m_start_page <= target - m_guard_page_count && target + page_count + m_guard_page_count <= m_end_page);
|
||||
|
||||
/* Check that the page is not forbidden. */
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace ams::os::impl {
|
|||
public:
|
||||
AddressSpaceAllocatorBase(u64 start_address, u64 end_address, SizeType guard_size, const AddressSpaceAllocatorForbiddenRegion *forbidden_regions, size_t num_forbidden_regions);
|
||||
|
||||
AddressType AllocateSpace(SizeType size, SizeType align, SizeType align_offset);
|
||||
AddressType AllocateSpace(SizeType size, SizeType align, SizeType align_offset, AddressSpaceGenerateRandomFunction generate_random);
|
||||
|
||||
bool CheckGuardSpace(AddressType address, SizeType size, SizeType guard_size);
|
||||
private:
|
||||
|
@ -54,6 +54,8 @@ namespace ams::os::impl {
|
|||
virtual bool CheckFreeSpace(AddressType address, SizeType size) = 0;
|
||||
};
|
||||
|
||||
u64 AddressSpaceAllocatorDefaultGenerateRandom(u64 max);
|
||||
|
||||
}
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
|
|
|
@ -55,16 +55,16 @@ namespace ams::os::impl {
|
|||
}
|
||||
#endif
|
||||
|
||||
AddressType AllocateSpace(SizeType size, SizeType align_offset) {
|
||||
AddressType AllocateSpace(SizeType size, SizeType align_offset, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
/* Try to allocate a large-aligned space, if we can. */
|
||||
if (align_offset || (size / AslrSpaceLargeAlign) != 0) {
|
||||
if (auto large_align = m_allocator.AllocateSpace(size, AslrSpaceLargeAlign, align_offset & (AslrSpaceLargeAlign - 1)); large_align != 0) {
|
||||
if (auto large_align = m_allocator.AllocateSpace(size, AslrSpaceLargeAlign, align_offset & (AslrSpaceLargeAlign - 1), generate_random); large_align != 0) {
|
||||
return large_align;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a page-aligned space. */
|
||||
return m_allocator.AllocateSpace(size, MemoryPageSize, 0);
|
||||
return m_allocator.AllocateSpace(size, MemoryPageSize, 0, generate_random);
|
||||
}
|
||||
|
||||
bool CheckGuardSpace(AddressType address, SizeType size) {
|
||||
|
@ -72,11 +72,11 @@ namespace ams::os::impl {
|
|||
}
|
||||
|
||||
template<typename MapFunction, typename UnmapFunction>
|
||||
Result MapAtRandomAddress(AddressType *out, MapFunction map_function, UnmapFunction unmap_function, SizeType size, SizeType align_offset) {
|
||||
Result MapAtRandomAddressWithCustomRandomGenerator(AddressType *out, MapFunction map_function, UnmapFunction unmap_function, SizeType size, SizeType align_offset, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
/* Try to map up to 64 times. */
|
||||
for (auto i = 0; i < 64; ++i) {
|
||||
/* Reserve space to map the memory. */
|
||||
const uintptr_t map_address = this->AllocateSpace(size, align_offset);
|
||||
const uintptr_t map_address = this->AllocateSpace(size, align_offset, generate_random);
|
||||
if (map_address == 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -105,6 +105,11 @@ namespace ams::os::impl {
|
|||
/* We failed to map. */
|
||||
R_THROW(os::ResultOutOfAddressSpace());
|
||||
}
|
||||
|
||||
template<typename MapFunction, typename UnmapFunction>
|
||||
Result MapAtRandomAddress(AddressType *out, MapFunction map_function, UnmapFunction unmap_function, SizeType size, SizeType align_offset) {
|
||||
R_RETURN(this->MapAtRandomAddressWithCustomRandomGenerator(out, map_function, unmap_function, size, align_offset, os::impl::AddressSpaceAllocatorDefaultGenerateRandom));
|
||||
}
|
||||
};
|
||||
|
||||
using AslrSpaceManager = AslrSpaceManagerTemplate<AddressSpaceAllocator, AslrSpaceManagerImpl>;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class InsecureMemoryImpl {
|
||||
public:
|
||||
static Result AllocateInsecureMemoryImpl(uintptr_t *out_address, size_t size);
|
||||
static void FreeInsecureMemoryImpl(uintptr_t address, size_t size);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_insecure_memory_impl.hpp"
|
||||
#include "os_aslr_space_manager.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
Result InsecureMemoryImpl::AllocateInsecureMemoryImpl(uintptr_t *out_address, size_t size) {
|
||||
/* Map at a random address. */
|
||||
R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address,
|
||||
[](uintptr_t map_address, size_t map_size) -> Result {
|
||||
R_TRY_CATCH(svc::MapInsecureMemory(map_address, map_size)) {
|
||||
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
R_SUCCEED();
|
||||
},
|
||||
[](uintptr_t map_address, size_t map_size) -> void {
|
||||
return InsecureMemoryImpl::FreeInsecureMemoryImpl(map_address, map_size);
|
||||
},
|
||||
size,
|
||||
0
|
||||
));
|
||||
}
|
||||
|
||||
void InsecureMemoryImpl::FreeInsecureMemoryImpl(uintptr_t address, size_t size) {
|
||||
R_ABORT_UNLESS(svc::UnmapInsecureMemory(address, size));
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace ams::os::impl {
|
|||
|
||||
class ProcessCodeMemoryImpl {
|
||||
public:
|
||||
static Result Map(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions);
|
||||
static Result Map(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions, AddressSpaceGenerateRandomFunction generate_random);
|
||||
static Result Unmap(NativeHandle handle, u64 process_code_address, const ProcessMemoryRegion *regions, size_t num_regions);
|
||||
};
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace ams::os::impl {
|
|||
|
||||
}
|
||||
|
||||
Result ProcessCodeMemoryImpl::Map(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions) {
|
||||
Result ProcessCodeMemoryImpl::Map(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
/* Get the total process memory region size. */
|
||||
const size_t total_size = GetTotalProcessMemoryRegionSize(regions, num_regions);
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace ams::os::impl {
|
|||
|
||||
/* Map at a random address. */
|
||||
u64 mapped_address;
|
||||
R_TRY(process_aslr_space_manager.MapAtRandomAddress(std::addressof(mapped_address),
|
||||
R_TRY(process_aslr_space_manager.MapAtRandomAddressWithCustomRandomGenerator(std::addressof(mapped_address),
|
||||
[handle, regions, num_regions](u64 map_address, u64 map_size) -> Result {
|
||||
AMS_UNUSED(map_size);
|
||||
|
||||
|
@ -107,7 +107,8 @@ namespace ams::os::impl {
|
|||
R_ABORT_UNLESS(ProcessCodeMemoryImpl::Unmap(handle, map_address, regions, num_regions));
|
||||
},
|
||||
total_size,
|
||||
regions[0].address /* NOTE: This seems like a Nintendo bug, if the caller passed no regions. */
|
||||
regions[0].address, /* NOTE: This seems like a Nintendo bug, if the caller passed no regions. */
|
||||
generate_random
|
||||
));
|
||||
|
||||
/* Set the output address. */
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ams::os::impl {
|
|||
|
||||
class ProcessMemoryImpl {
|
||||
public:
|
||||
static Result Map(void **out, NativeHandle handle, u64 process_address, size_t size);
|
||||
static Result Map(void **out, NativeHandle handle, u64 process_address, size_t size, AddressSpaceGenerateRandomFunction generate_random);
|
||||
static void Unmap(void *mapped_memory, NativeHandle handle, u64 process_address, size_t size);
|
||||
|
||||
static Result SetMemoryPermission(NativeHandle handle, u64 process_address, u64 size, MemoryPermission perm);
|
||||
|
|
|
@ -33,10 +33,10 @@ namespace ams::os::impl {
|
|||
|
||||
}
|
||||
|
||||
Result ProcessMemoryImpl::Map(void **out, NativeHandle handle, u64 process_address, size_t size) {
|
||||
Result ProcessMemoryImpl::Map(void **out, NativeHandle handle, u64 process_address, size_t size, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
/* Map at a random address. */
|
||||
uintptr_t mapped_address;
|
||||
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address),
|
||||
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddressWithCustomRandomGenerator(std::addressof(mapped_address),
|
||||
[handle, process_address](uintptr_t map_address, size_t map_size) -> Result {
|
||||
R_TRY_CATCH(svc::MapProcessMemory(map_address, handle, process_address, map_size)) {
|
||||
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||
|
@ -49,7 +49,8 @@ namespace ams::os::impl {
|
|||
return ProcessMemoryImpl::Unmap(reinterpret_cast<void *>(map_address), handle, process_address, map_size);
|
||||
},
|
||||
size,
|
||||
process_address
|
||||
process_address,
|
||||
generate_random
|
||||
));
|
||||
|
||||
/* Return the address we mapped at. */
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace ams::os::impl {
|
|||
}
|
||||
|
||||
void *AllocateStackGuardSpace(size_t size) {
|
||||
return reinterpret_cast<void *>(m_allocator.AllocateSpace(size, os::MemoryPageSize, 0));
|
||||
return reinterpret_cast<void *>(m_allocator.AllocateSpace(size, os::MemoryPageSize, 0, os::impl::AddressSpaceAllocatorDefaultGenerateRandom));
|
||||
}
|
||||
|
||||
bool CheckGuardSpace(uintptr_t address, size_t size) {
|
||||
|
|
39
libraries/libstratosphere/source/os/os_insecure_memory.cpp
Normal file
39
libraries/libstratosphere/source/os/os_insecure_memory.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_insecure_memory_impl.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
Result AllocateInsecureMemory(uintptr_t *out_address, size_t size) {
|
||||
/* Check arguments. */
|
||||
AMS_ASSERT(size > 0);
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
|
||||
/* Allocate memory. */
|
||||
R_RETURN(impl::InsecureMemoryImpl::AllocateInsecureMemoryImpl(out_address, size));
|
||||
}
|
||||
|
||||
void FreeInsecureMemory(uintptr_t address, size_t size) {
|
||||
/* Check arguments. */
|
||||
AMS_ASSERT(util::IsAligned(address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
|
||||
/* Free memory. */
|
||||
impl::InsecureMemoryImpl::FreeInsecureMemoryImpl(address, size);
|
||||
}
|
||||
|
||||
}
|
|
@ -62,6 +62,11 @@ namespace ams::os {
|
|||
return GetReference(event->impl).Clear();
|
||||
}
|
||||
|
||||
NativeHandle GetInterruptEventHandle(const InterruptEventType *event) {
|
||||
AMS_ASSERT(event->state == InterruptEventType::State_Initialized);
|
||||
return GetReference(event->impl).GetHandle();
|
||||
}
|
||||
|
||||
void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterruptEventType *event) {
|
||||
AMS_ASSERT(event->state == InterruptEventType::State_Initialized);
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
namespace ams::os {
|
||||
|
||||
Result MapProcessCodeMemory(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions) {
|
||||
R_RETURN(::ams::os::impl::ProcessCodeMemoryImpl::Map(out, handle, regions, num_regions));
|
||||
Result MapProcessCodeMemory(u64 *out, NativeHandle handle, const ProcessMemoryRegion *regions, size_t num_regions, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
R_RETURN(::ams::os::impl::ProcessCodeMemoryImpl::Map(out, handle, regions, num_regions, generate_random));
|
||||
}
|
||||
|
||||
Result UnmapProcessCodeMemory(NativeHandle handle, u64 process_code_address, const ProcessMemoryRegion *regions, size_t num_regions) {
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
namespace ams::os {
|
||||
|
||||
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size) {
|
||||
R_RETURN(::ams::os::impl::ProcessMemoryImpl::Map(out, handle, process_address, process_size));
|
||||
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size, AddressSpaceGenerateRandomFunction generate_random) {
|
||||
R_RETURN(::ams::os::impl::ProcessMemoryImpl::Map(out, handle, process_address, process_size, generate_random));
|
||||
}
|
||||
|
||||
void UnmapProcessMemory(void *mapped_memory, NativeHandle handle, u64 process_address, size_t process_size) {
|
||||
|
|
|
@ -142,6 +142,9 @@
|
|||
HANDLER(0x7E, Result, SetResourceLimitLimitValue, INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which), INPUT(int64_t, limit_value)) \
|
||||
HANDLER(0x7F, void, CallSecureMonitor, OUTPUT(::ams::svc::NAMESPACE::SecureMonitorArguments, args)) \
|
||||
\
|
||||
HANDLER(0x90, Result, MapInsecureMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \
|
||||
HANDLER(0x91, Result, UnmapInsecureMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \
|
||||
\
|
||||
HANDLER(0x2E, Result, LegacyGetFutureThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(::ams::svc::Address, out_tls_address), OUTPUT(uint32_t, out_flags), INPUT(int64_t, ns)) \
|
||||
HANDLER(0x55, Result, LegacyQueryIoMapping, OUTPUT(::ams::svc::Address, out_address), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size)) \
|
||||
HANDLER(0x64, Result, LegacyContinueDebugEvent, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint32_t, flags), INPUT(uint64_t, thread_id))
|
||||
|
|
|
@ -399,6 +399,15 @@ namespace ams::ldr {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
u64 GenerateSecureRandom(u64 max) {
|
||||
/* Generate a cryptographically random number. */
|
||||
u64 rand;
|
||||
crypto::GenerateCryptographicallyRandomBytes(std::addressof(rand), sizeof(rand));
|
||||
|
||||
/* Coerce into range. */
|
||||
return rand % (max + 1);
|
||||
}
|
||||
|
||||
Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument) {
|
||||
/* Clear output. */
|
||||
out->args_address = 0;
|
||||
|
@ -468,8 +477,7 @@ namespace ams::ldr {
|
|||
uintptr_t aslr_slide = 0;
|
||||
size_t free_size = (aslr_size - total_size);
|
||||
if (out_param->flags & svc::CreateProcessFlag_EnableAslr) {
|
||||
/* Nintendo uses MT19937 (not os::GenerateRandomBytes), but we'll just use TinyMT for now. */
|
||||
aslr_slide = os::GenerateRandomU64(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize;
|
||||
aslr_slide = GenerateSecureRandom(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize;
|
||||
}
|
||||
|
||||
/* Set out. */
|
||||
|
@ -527,7 +535,7 @@ namespace ams::ldr {
|
|||
{
|
||||
/* Map the process memory. */
|
||||
void *mapped_memory = nullptr;
|
||||
R_TRY(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, nso_address, nso_size));
|
||||
R_TRY(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, nso_address, nso_size, GenerateSecureRandom));
|
||||
ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, process_handle, nso_address, nso_size); };
|
||||
|
||||
const uintptr_t map_address = reinterpret_cast<uintptr_t>(mapped_memory);
|
||||
|
@ -590,7 +598,7 @@ namespace ams::ldr {
|
|||
/* Write argument data into memory. */
|
||||
{
|
||||
void *map_address = nullptr;
|
||||
R_TRY(os::MapProcessMemory(std::addressof(map_address), process_info->process_handle, process_info->args_address, process_info->args_size));
|
||||
R_TRY(os::MapProcessMemory(std::addressof(map_address), process_info->process_handle, process_info->args_address, process_info->args_size, GenerateSecureRandom));
|
||||
ON_SCOPE_EXIT { os::UnmapProcessMemory(map_address, process_info->process_handle, process_info->args_address, process_info->args_size); };
|
||||
|
||||
ProgramArguments *args = static_cast<ProgramArguments *>(map_address);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
"service_access": ["fatal:u", "spl:", "set:sys", "fsp-srv"],
|
||||
"service_access": ["fatal:u", "spl:", "set:sys", "fsp-srv", "csrng"],
|
||||
"service_host": ["ldr:ro", "ro:dmnt", "ro:1"],
|
||||
"kernel_capabilities": [{
|
||||
"type": "kernel_flags",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "ro_nro_utils.hpp"
|
||||
#include "ro_random.hpp"
|
||||
|
||||
namespace ams::ro::impl {
|
||||
|
||||
|
@ -43,7 +44,7 @@ namespace ams::ro::impl {
|
|||
const size_t num_regions = SetupNroProcessMemoryRegions(regions, nro_heap_address, nro_heap_size, bss_heap_address, bss_heap_size);
|
||||
|
||||
/* Re-map the nro/bss as code memory in the destination process. */
|
||||
R_TRY_CATCH(os::MapProcessCodeMemory(out_base_address, process_handle, regions, num_regions)) {
|
||||
R_TRY_CATCH(os::MapProcessCodeMemory(out_base_address, process_handle, regions, num_regions, ro::impl::GenerateSecureRandom)) {
|
||||
R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "ro_nrr_utils.hpp"
|
||||
#include "ro_random.hpp"
|
||||
#include "ro_service_impl.hpp"
|
||||
|
||||
namespace ams::ro::impl {
|
||||
|
@ -198,7 +199,7 @@ namespace ams::ro::impl {
|
|||
/* Re-map the nrr as code memory in the destination process. */
|
||||
u64 code_address = 0;
|
||||
const os::ProcessMemoryRegion region = { nrr_heap_address, nrr_heap_size };
|
||||
R_TRY_CATCH(os::MapProcessCodeMemory(std::addressof(code_address), process_handle, std::addressof(region), 1)) {
|
||||
R_TRY_CATCH(os::MapProcessCodeMemory(std::addressof(code_address), process_handle, std::addressof(region), 1, ro::impl::GenerateSecureRandom)) {
|
||||
R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
@ -207,7 +208,7 @@ namespace ams::ro::impl {
|
|||
|
||||
/* Map the nrr in our process. */
|
||||
void *mapped_memory = nullptr;
|
||||
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, code_address, region.size)) {
|
||||
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, code_address, region.size, ro::impl::GenerateSecureRandom)) {
|
||||
R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
|
30
stratosphere/ro/source/impl/ro_random.cpp
Normal file
30
stratosphere/ro/source/impl/ro_random.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "ro_random.hpp"
|
||||
|
||||
namespace ams::ro::impl {
|
||||
|
||||
u64 GenerateSecureRandom(u64 max) {
|
||||
/* Generate a cryptographically random number. */
|
||||
u64 rand;
|
||||
crypto::GenerateCryptographicallyRandomBytes(std::addressof(rand), sizeof(rand));
|
||||
|
||||
/* Coerce into range. */
|
||||
return rand % (max + 1);
|
||||
}
|
||||
|
||||
}
|
24
stratosphere/ro/source/impl/ro_random.hpp
Normal file
24
stratosphere/ro/source/impl/ro_random.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::ro::impl {
|
||||
|
||||
u64 GenerateSecureRandom(u64 max);
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include "ro_nrr_utils.hpp"
|
||||
#include "ro_nro_utils.hpp"
|
||||
#include "ro_patcher.hpp"
|
||||
#include "ro_random.hpp"
|
||||
#include "ro_service_impl.hpp"
|
||||
|
||||
namespace ams::ro::impl {
|
||||
|
@ -249,7 +250,7 @@ namespace ams::ro::impl {
|
|||
Result ValidateNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, u64 base_address, u64 expected_nro_size, u64 expected_bss_size) {
|
||||
/* Map the NRO. */
|
||||
void *mapped_memory = nullptr;
|
||||
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size)) {
|
||||
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) {
|
||||
R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
|
|
@ -51,26 +51,26 @@ namespace ams {
|
|||
};
|
||||
|
||||
constexpr sm::ServiceName RandomServiceName = sm::ServiceName::Encode("csrng");
|
||||
constexpr size_t RandomMaxSessions = 3;
|
||||
constexpr size_t RandomMaxSessions = 10; /* NOTE: Official is 9. */
|
||||
|
||||
constexpr sm::ServiceName GeneralServiceName = sm::ServiceName::Encode("spl:");
|
||||
constexpr size_t DeprecatedMaxSessions = 13;
|
||||
constexpr size_t GeneralMaxSessions = 7;
|
||||
constexpr size_t GeneralMaxSessions = 9; /* NOTE: Official is 8. */
|
||||
|
||||
constexpr sm::ServiceName CryptoServiceName = sm::ServiceName::Encode("spl:mig");
|
||||
constexpr size_t CryptoMaxSessions = 7;
|
||||
constexpr size_t CryptoMaxSessions = 7; /* NOTE: Official is 6. */
|
||||
|
||||
constexpr sm::ServiceName SslServiceName = sm::ServiceName::Encode("spl:ssl");
|
||||
constexpr size_t SslMaxSessions = 2;
|
||||
constexpr size_t SslMaxSessions = 2; /* NOTE: Official is 2. */
|
||||
|
||||
constexpr sm::ServiceName EsServiceName = sm::ServiceName::Encode("spl:es");
|
||||
constexpr size_t EsMaxSessions = 2;
|
||||
constexpr size_t EsMaxSessions = 2; /* NOTE: Official is 2. */
|
||||
|
||||
constexpr sm::ServiceName FsServiceName = sm::ServiceName::Encode("spl:fs");
|
||||
constexpr size_t FsMaxSessions = 3;
|
||||
constexpr size_t FsMaxSessions = 3; /* NOTE: Official is 1. */
|
||||
|
||||
constexpr sm::ServiceName ManuServiceName = sm::ServiceName::Encode("spl:manu");
|
||||
constexpr size_t ManuMaxSessions = 1;
|
||||
constexpr size_t ManuMaxSessions = 1; /* NOTE: Official is 1. */
|
||||
|
||||
/* csrng, spl:, spl:mig, spl:ssl, spl:es, spl:fs, spl:manu. */
|
||||
/* TODO: Consider max sessions enforcement? */
|
||||
|
|
Loading…
Reference in a new issue