diff --git a/Dockerfile b/Dockerfile index 7421d0037..577f336af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,7 +56,7 @@ RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfir # rm -rf /tmp/switch-tools # Install libnx from Git (optional) -# ENV LIBNX_REV=dbcc1beafc6b47b5ffbeb8ba82463a7d45da40bb +# ENV LIBNX_REV=146c3d1446d35546943c7b6cfcd479bc1f5e9b67 # RUN cd /tmp && \ # mkdir -p /tmp/libnx && \ # cd /tmp/libnx && \ @@ -65,9 +65,8 @@ RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfir # git fetch --depth 1 origin $LIBNX_REV && \ # git reset --hard FETCH_HEAD && \ # make -j$(nproc) && \ -# mkdir -p /opt/devkitpro/libnx && \ # cd nx && \ -# make DESTDIR=/opt/devkitpro/libnx install && \ +# make install && \ # cd /tmp && \ # rm -rf /tmp/libnx diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp index 8e1829849..ae12326a1 100644 --- a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp @@ -51,9 +51,7 @@ namespace ams::kern::board::nintendo::nx { static NOINLINE u32 GetCreateProcessMemoryPool(); /* Randomness. */ - static void GenerateRandom(u64 *dst, size_t count); - static u64 GenerateRandomRange(u64 min, u64 max); - static u64 GenerateRandomU64(); + static void GenerateRandomBytesForUninitialized(void *dst, size_t size); /* Privileged Access. */ static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index 9e9e9c7a4..7e95a98cb 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -119,6 +119,8 @@ namespace ams::kern { KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, + + KMemoryState_ShadowStack = ams::svc::MemoryState_ShadowStack, }; #if 1 @@ -147,6 +149,7 @@ namespace ams::kern { static_assert(KMemoryState_CodeOut == 0x04402015); static_assert(KMemoryState_Coverage == 0x00002016); /* TODO: Is this correct? */ static_assert(KMemoryState_Insecure == 0x055C3817); + static_assert(KMemoryState_ShadowStack == 0x0000001A); #endif enum KMemoryPermission : u8 { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp index 3d7ea5310..95d601959 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp @@ -37,13 +37,12 @@ namespace ams::kern { public: /* This can be overridden as needed. */ static constexpr size_t SecureAppletMemorySize = 0; - protected: - /* Nintendo uses std::mt19937_t for randomness. */ - /* To save space (and because mt19337_t isn't secure anyway), */ - /* We will use TinyMT. */ - static constinit inline bool s_uninitialized_random_generator{true}; - static constinit inline util::TinyMT s_random_generator{util::ConstantInitialize}; - static constinit inline KSpinLock s_random_lock; + private: + /* Randomness helpers. */ + static void InitializeRandomGenerator(const void *seed, size_t size); + static void ReseedRandomGeneratorInternal(); + static u32 GenerateRandomU32(); + static u64 GenerateRandomU64Internal(); public: class Init { private: @@ -66,7 +65,7 @@ namespace ams::kern { static u64 GenerateRandomRange(u64 min, u64 max); }; protected: - static NOINLINE void InitializePhase1Base(u64 seed); + static NOINLINE void InitializePhase1Base(const void *seed, size_t size); public: /* Initialization. */ static NOINLINE void ConfigureKTargetSystem(); @@ -78,6 +77,10 @@ namespace ams::kern { static void GenerateRandom(u64 *dst, size_t count); static u64 GenerateRandomRange(u64 min, u64 max); static u64 GenerateRandomU64(); + static void ReseedRandomGenerator(); + + /* Obtains random bytes while the generator is not yet initialized. Board-provided. */ + static void GenerateRandomBytesForUninitialized(void *dst, size_t size); /* Register access Access. */ static Result ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index f6193dd71..429af04ec 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -29,6 +29,7 @@ namespace ams::kern { class KProcess; class KConditionVariable; class KAddressArbiter; + class KPageBuffer; using KThreadFunction = void (*)(uintptr_t); @@ -305,6 +306,8 @@ namespace ams::kern { u32 *m_light_ipc_data; KProcessAddress m_tls_address; void *m_tls_heap_address; + KProcessAddress m_shadow_stack_address; + KPageBuffer *m_shadow_stack_page; KLightLock m_activity_pause_lock; SyncObjectBuffer m_sync_object_buffer; s64 m_schedule_count; @@ -347,7 +350,7 @@ namespace ams::kern { : KAutoObjectWithSlabHeapAndContainer(util::ConstantInitialize), KTimerTask(util::ConstantInitialize), m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{}, m_caller_save_fpu_registers{}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null}, m_parent{}, - m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize}, + m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null}, m_tls_heap_address{}, m_shadow_stack_address{Null}, m_shadow_stack_page{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize}, m_schedule_count{}, m_last_scheduled_tick{}, m_per_core_priority_queue_entry{}, m_wait_queue{}, m_held_lock_info_list{}, m_waiting_lock_info{}, m_pinned_waiter_list{}, m_debug_params{}, m_closed_object{}, m_address_key_value{}, m_suspend_request_flags{}, m_suspend_allowed_flags{}, m_synced_index{}, m_wait_result{svc::ResultNoSynchronizationObject()}, m_debug_exception_result{ResultSuccess()}, m_base_priority{}, m_base_priority_on_unpin{}, diff --git a/libraries/libmesosphere/libmesosphere.mk b/libraries/libmesosphere/libmesosphere.mk index 2ab310a25..7998d5f78 100644 --- a/libraries/libmesosphere/libmesosphere.mk +++ b/libraries/libmesosphere/libmesosphere.mk @@ -108,6 +108,8 @@ $(OFILES_SRC) : $(HFILES_BIN) kern_libc_generic.o: CFLAGS += -fno-builtin +crypto_aes_impl.arch.arm64.o: CXXFLAGS := $(filter-out -mgeneral-regs-only,$(CXXFLAGS)) + #--------------------------------------------------------------------------------- %_bin.h %.bin.o : %.bin #--------------------------------------------------------------------------------- diff --git a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp index 6c21b455b..712ac7bd7 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp @@ -196,6 +196,7 @@ namespace ams::kern::arch::arm64 { case EsrEc_Cp14McrMrc: case EsrEc_Cp14Mrrc: case EsrEc_SystemInstruction64: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: type = ams::svc::ExceptionType_InstructionAbort; @@ -267,6 +268,7 @@ namespace ams::kern::arch::arm64 { switch (ec) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: { @@ -474,6 +476,7 @@ namespace ams::kern::arch::arm64 { switch (ec) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: { @@ -564,6 +567,7 @@ namespace ams::kern::arch::arm64 { switch ((esr >> 26) & 0x3F) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: far = context->pc; diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index bb7581c83..2cc6f0f81 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -74,12 +74,6 @@ namespace ams::kern::board::nintendo::nx { return value; } - ALWAYS_INLINE u64 GenerateRandomU64FromSmc() { - u64 value; - smc::GenerateRandomBytes(std::addressof(value), sizeof(value)); - return value; - } - ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) { u64 value; smc::GetConfig(&value, 1, which); @@ -477,9 +471,9 @@ namespace ams::kern::board::nintendo::nx { /* Initialize random and resource limit. */ { - u64 seed; - smc::GenerateRandomBytes(std::addressof(seed), sizeof(seed)); - KSystemControlBase::InitializePhase1Base(seed); + u8 seed[32]; + smc::GenerateRandomBytes(seed, sizeof(seed)); + KSystemControlBase::InitializePhase1Base(seed, sizeof(seed)); } /* Configure the Kernel Carveout region. */ @@ -524,32 +518,8 @@ namespace ams::kern::board::nintendo::nx { } /* Randomness. */ - void KSystemControl::GenerateRandom(u64 *dst, size_t count) { - MESOSPHERE_INIT_ABORT_UNLESS(count <= 7); - smc::GenerateRandomBytes(dst, count * sizeof(u64)); - } - - u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { - KScopedInterruptDisable intr_disable; - KScopedSpinLock lk(s_random_lock); - - - if (AMS_LIKELY(!s_uninitialized_random_generator)) { - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); - } else { - return KSystemControlBase::GenerateUniformRange(min, max, GenerateRandomU64FromSmc); - } - } - - u64 KSystemControl::GenerateRandomU64() { - KScopedInterruptDisable intr_disable; - KScopedSpinLock lk(s_random_lock); - - if (AMS_LIKELY(!s_uninitialized_random_generator)) { - return s_random_generator.GenerateRandomU64(); - } else { - return GenerateRandomU64FromSmc(); - } + void KSystemControl::GenerateRandomBytesForUninitialized(void *dst, size_t size) { + smc::GenerateRandomBytes(dst, size); } void KSystemControl::SleepSystem() { diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index ad49b783b..0bdcaab85 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -264,6 +264,11 @@ namespace ams::kern { m_is_default_application_system_resource = false; m_is_immortal = immortal; + /* Reseed the random generator on application launch. */ + if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) { + KSystemControl::ReseedRandomGenerator(); + } + /* Setup our system resource. */ if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { /* Create a secure system resource. */ @@ -332,6 +337,11 @@ namespace ams::kern { m_is_default_application_system_resource = false; m_is_immortal = false; + /* Reseed the random generator on application launch. */ + if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) { + KSystemControl::ReseedRandomGenerator(); + } + /* Get the memory sizes. */ const size_t code_num_pages = params.code_num_pages; const size_t system_resource_num_pages = params.system_resource_num_pages; diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index 38c507486..c92bbe60e 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -14,6 +14,8 @@ * along with this program. If not, see . */ #include +#include +#include #if defined(ATMOSPHERE_ARCH_ARM64) #include #endif @@ -27,6 +29,41 @@ namespace ams::kern { } + namespace { + + /* The kernel is otherwise FP/SIMD-free, but AES instructions require the NEON registers. */ + class KScopedFpuEnable { + private: + u64 m_saved_cpacr_el1; + public: + ALWAYS_INLINE KScopedFpuEnable() : m_saved_cpacr_el1(cpu::GetCpacrEl1()) { + cpu::SetCpacrEl1(m_saved_cpacr_el1 | 0x100000); + cpu::InstructionMemoryBarrier(); + } + + ALWAYS_INLINE ~KScopedFpuEnable() { + cpu::SetCpacrEl1(m_saved_cpacr_el1); + cpu::InstructionMemoryBarrier(); + } + }; + + using RandomGenerator = ::ams::crypto::impl::CtrDrbg<::ams::crypto::AesEncryptor128, 16, false>; + + constexpr size_t RandomGeneratorOutputSize = 8 * RandomGenerator::OutSize; + constexpr u32 RandomGeneratorOutputCount = RandomGeneratorOutputSize / sizeof(u32); + + constinit util::TypedStorage s_random_generator = {}; + constinit bool s_uninitialized_random_generator = true; + constinit u8 s_random_output[RandomGeneratorOutputSize] = {}; + constinit u32 s_random_remaining = 0; + constinit KSpinLock s_random_lock; + + void GenerateRandomSeed(void *dst, size_t size) { + KSystemControl::GenerateRandomBytesForUninitialized(dst, size); + } + + } + /* Initialization. */ size_t KSystemControlBase::Init::GetRealMemorySize() { return ams::kern::MainMemorySize; @@ -102,25 +139,13 @@ namespace ams::kern { /* Randomness for Initialization. */ void KSystemControlBase::Init::GenerateRandom(u64 *dst, size_t count) { - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - const u64 seed = KHardwareTimer::GetTick(); - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } - for (size_t i = 0; i < count; ++i) { - dst[i] = s_random_generator.GenerateRandomU64(); + dst[i] = KSystemControlBase::GenerateRandomU64(); } } u64 KSystemControlBase::Init::GenerateRandomRange(u64 min, u64 max) { - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - const u64 seed = KHardwareTimer::GetTick(); - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } - - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); + return KSystemControlBase::GenerateRandomRange(min, max); } /* System Initialization. */ @@ -135,15 +160,17 @@ namespace ams::kern { } /* Initialize random and resource limit. */ - KSystemControlBase::InitializePhase1Base(KHardwareTimer::GetTick()); + u64 seed[4]; + for (size_t i = 0; i < util::size(seed); ++i) { + seed[i] = KHardwareTimer::GetTick(); + } + KSystemControlBase::InitializePhase1Base(seed, sizeof(seed)); } - void KSystemControlBase::InitializePhase1Base(u64 seed) { - /* Initialize the rng, if we somehow haven't already. */ - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } + void KSystemControlBase::InitializePhase1Base(const void *seed, size_t size) { + /* Initialize the random generator. */ + KSystemControlBase::InitializeRandomGenerator(seed, size); + s_uninitialized_random_generator = false; /* Initialize debug logging. */ KDebugLog::Initialize(); @@ -213,13 +240,77 @@ namespace ams::kern { R_THROW(svc::ResultNotImplemented()); } + /* Randomness helpers. Assume the caller holds the random lock. */ + void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) { + MESOSPHERE_ASSERT(size == RandomGenerator::SeedSize); + + KScopedFpuEnable fp_enabled; + + /* Construct the generator, and derive the initial state from the seed. */ + util::ConstructAt(s_random_generator); + util::GetReference(s_random_generator).Initialize(seed, size, nullptr, 0, nullptr, 0); + + s_random_remaining = 0; + } + + void KSystemControlBase::ReseedRandomGeneratorInternal() { + KScopedFpuEnable fp_enabled; + + /* Pull fresh entropy, then derive a new state from it. */ + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + util::GetReference(s_random_generator).Reseed(seed, sizeof(seed), nullptr, 0); + + s_random_remaining = 0; + } + + u32 KSystemControlBase::GenerateRandomU32() { + if (s_random_remaining == 0) { + KScopedFpuEnable fp_enabled; + + auto &drbg = util::GetReference(s_random_generator); + + /* Derive the next state, or reseed if we've exhausted this generation's entropy. */ + if (AMS_UNLIKELY(!drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0))) { + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + drbg.Reseed(seed, sizeof(seed), nullptr, 0); + + MESOSPHERE_ABORT_UNLESS(drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0)); + } + + s_random_remaining = RandomGeneratorOutputCount; + } + + /* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */ + const size_t index = RandomGeneratorOutputCount - s_random_remaining; + u32 value; + std::memcpy(std::addressof(value), s_random_output + sizeof(value) * index, sizeof(value)); + std::memset(s_random_output + sizeof(value) * index, 0, sizeof(value)); + --s_random_remaining; + return value; + } + + u64 KSystemControlBase::GenerateRandomU64Internal() { + /* Fall back to the board's raw source while the generator is uninitialized. */ + if (AMS_UNLIKELY(s_uninitialized_random_generator)) { + u64 value; + KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value)); + return value; + } + + const u64 high = KSystemControlBase::GenerateRandomU32(); + const u64 low = KSystemControlBase::GenerateRandomU32(); + return (high << 32) | low; + } + /* Randomness. */ void KSystemControlBase::GenerateRandom(u64 *dst, size_t count) { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); for (size_t i = 0; i < count; ++i) { - dst[i] = s_random_generator.GenerateRandomU64(); + dst[i] = KSystemControlBase::GenerateRandomU64Internal(); } } @@ -227,14 +318,46 @@ namespace ams::kern { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); + /* While uninitialized, fall back to a raw single-draw modulo. */ + if (AMS_UNLIKELY(s_uninitialized_random_generator)) { + u64 value; + KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value)); + + const u64 difference = max - min; + if (difference == std::numeric_limits::max()) { + return value; + } + + return min + (value % (difference + 1)); + } + + return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return KSystemControlBase::GenerateRandomU64Internal(); }); } u64 KSystemControlBase::GenerateRandomU64() { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); - return s_random_generator.GenerateRandomU64(); + return KSystemControlBase::GenerateRandomU64Internal(); + } + + void KSystemControlBase::ReseedRandomGenerator() { + /* This must be unreachable while the generator is uninitialized. */ + MESOSPHERE_ABORT_UNLESS(!s_uninitialized_random_generator); + + KScopedInterruptDisable intr_disable; + KScopedSpinLock lk(s_random_lock); + + KSystemControlBase::ReseedRandomGeneratorInternal(); + } + + void KSystemControlBase::GenerateRandomBytesForUninitialized(void *dst, size_t size) { + /* The default board has no secure monitor; fall back to the hardware timer. */ + u8 *dst_8 = static_cast(dst); + for (size_t offset = 0; offset < size; offset += sizeof(u64)) { + const u64 tick = KHardwareTimer::GetTick(); + std::memcpy(dst_8 + offset, std::addressof(tick), std::min(sizeof(tick), size - offset)); + } } void KSystemControlBase::SleepSystem() { diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index 9cf5ea862..b2ec76302 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -214,6 +214,10 @@ namespace ams::kern { m_tls_address = 0; m_tls_heap_address = 0; + /* Set shadow stack address and page. */ + m_shadow_stack_address = Null; + m_shadow_stack_page = nullptr; + /* Set parent and condvar tree. */ m_parent = nullptr; m_condvar_tree = nullptr; @@ -281,6 +285,29 @@ namespace ams::kern { R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); m_tls_heap_address = owner->GetThreadLocalRegionPointer(m_tls_address); std::memset(m_tls_heap_address, 0, ams::svc::ThreadLocalRegionSize); + + /* If the owning process has a shadow stack, allocate and map a page for this thread. */ + if (owner->GetCreateProcessParameterFlags() & ams::svc::CreateProcessParameterFlag_EnableShadowStack) { + /* Allocate the backing page. */ + KPageBuffer *page = KPageBuffer::AllocateChecked(); + if (page == nullptr) { + owner->DeleteThreadLocalRegion(m_tls_address); + m_tls_address = Null; + R_THROW(svc::ResultOutOfMemory()); + } + + /* If we fail to map the page, free it and undo the TLS region we just created. */ + ON_RESULT_FAILURE { + KPageBuffer::Free(page); + owner->DeleteThreadLocalRegion(m_tls_address); + m_tls_address = Null; + }; + + /* Map the page into the process's shadow stack region. */ + R_TRY(owner->GetPageTable().MapPages(std::addressof(m_shadow_stack_address), 1, PageSize, page->GetPhysicalAddress(), KMemoryState_ShadowStack, KMemoryPermission_UserReadWrite)); + + m_shadow_stack_page = page; + } } /* Set parent, if relevant. */ @@ -390,6 +417,12 @@ namespace ams::kern { m_parent->UnregisterThread(this); } + /* If the thread has a shadow stack, unmap and free its page. */ + if (m_shadow_stack_address != Null) { + MESOSPHERE_R_ABORT_UNLESS(m_parent->GetPageTable().UnmapPages(m_shadow_stack_address, 1, KMemoryState_ShadowStack)); + KPageBuffer::Free(m_shadow_stack_page); + } + /* If the thread has a local region, delete it. */ if (m_tls_address != Null) { m_parent->DeleteThreadLocalRegion(m_tls_address); diff --git a/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp b/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp index 3d60504fe..ec6de4ebc 100644 --- a/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp @@ -89,6 +89,12 @@ namespace ams::spl { return ::ams::spl::GetConfigBool(::ams::spl::ConfigItem::ExosphereForceEnableUsb30); } + inline std::pair GetLogConfiguration() { + u64 v; + R_ABORT_UNLESS(::ams::spl::GetConfig(std::addressof(v), ::ams::spl::ConfigItem::ExosphereLogConfiguration)); + return std::make_pair(static_cast(v >> 32), static_cast(v)); + } + Result SetBootReason(BootReasonValue boot_reason); Result GetBootReason(BootReasonValue *out); diff --git a/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp b/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp index ecb9e2d0a..414953364 100644 --- a/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp +++ b/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp @@ -14,14 +14,14 @@ * along with this program. If not, see . */ #include -#include "../spl/impl/spl_ctr_drbg.hpp" +#include #include namespace ams::crypto { namespace { - using Drbg = ::ams::spl::impl::CtrDrbg; + using Drbg = ::ams::crypto::impl::CtrDrbg; constinit util::TypedStorage g_drbg = {}; diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp index e687f9bbc..5212724cc 100644 --- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp +++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp @@ -17,7 +17,6 @@ #include "pinmux_pad_index.hpp" #include "pinmux_board_driver_api.hpp" #include "pinmux_platform_pads.hpp" -#include "pinmux_build_config.hpp" namespace ams::pinmux::driver::board::nintendo::nx { @@ -101,30 +100,33 @@ namespace ams::pinmux::driver::board::nintendo::nx { UpdateSinglePinmuxPad({ PinmuxPadIndex_Sdmmc2Dat7, 0x2000, 0x2000 }); } - #if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART) - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart2Tx, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart2Cts, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - #endif - #if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART) - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart3Tx, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart3Cts, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - #endif + auto [log_port, log_baud_rate] = spl::GetLogConfiguration(); + AMS_UNUSED(log_baud_rate); + + if (log_port == 1) { + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Tx, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Cts, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + } + if (log_port == 2) { + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Tx, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Cts, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + } } void SetInitialDrivePadConfig() { diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp deleted file mode 100644 index 530af4325..000000000 --- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 . - */ -#pragma once -#include - -// #define AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART -// #define AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART \ No newline at end of file diff --git a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp index c5c450b1b..93821f85b 100644 --- a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp +++ b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #include -#include "spl_ctr_drbg.hpp" +#include #include "spl_device_address_mapper.hpp" #include "spl_key_slot_cache.hpp" @@ -29,7 +29,7 @@ namespace ams::spl::impl { namespace { /* Drbg type. */ - using Drbg = CtrDrbg; + using Drbg = crypto::impl::CtrDrbg; /* Convenient defines. */ #if defined(ATMOSPHERE_OS_HORIZON) diff --git a/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp b/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp index 066687771..42e72d7d6 100644 --- a/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp +++ b/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp @@ -33,7 +33,7 @@ namespace ams::crypto::impl { #ifdef ATMOSPHERE_IS_EXOSPHERE int m_slot; #endif - #ifdef ATMOSPHERE_IS_STRATOSPHERE + #if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) u32 m_round_keys[RoundKeySize / sizeof(u32)]; #endif public: @@ -43,7 +43,7 @@ namespace ams::crypto::impl { void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const; void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const; - #ifdef ATMOSPHERE_IS_STRATOSPHERE + #if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) const u8 *GetRoundKey() const { return reinterpret_cast(m_round_keys); } diff --git a/libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp b/libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp similarity index 99% rename from libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp rename to libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp index b615f02c1..6454fae02 100644 --- a/libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp +++ b/libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp @@ -14,9 +14,9 @@ * along with this program. If not, see . */ #pragma once -#include +#include -namespace ams::spl::impl { +namespace ams::crypto::impl { constexpr inline int BitsPerByte = BITSIZEOF(u8); diff --git a/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp b/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp index 35fdf4fa2..c07a20f2e 100644 --- a/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp +++ b/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp @@ -14,13 +14,16 @@ * along with this program. If not, see . */ #include -#if defined(ATMOSPHERE_IS_STRATOSPHERE) +#if defined(ATMOSPHERE_IS_MESOSPHERE) +#include +#endif +#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) #include #endif namespace ams::crypto::impl { -#if defined(ATMOSPHERE_IS_STRATOSPHERE) +#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) namespace {