fs: fix clang-build, os: StackGuardManager

This commit is contained in:
Michael Scire 2022-03-12 15:05:43 -08:00 committed by SciresM
parent be9338eb33
commit cb3d20ef79
13 changed files with 264 additions and 28 deletions

View file

@ -19,6 +19,12 @@
namespace ams::os::impl {
enum AddressAllocationResult {
AddressAllocationResult_Success,
AddressAllocationResult_OutOfMemory,
AddressAllocationResult_OutOfSpace,
};
template<std::unsigned_integral AddressType, std::unsigned_integral SizeType>
class AddressSpaceAllocatorBase {
NON_COPYABLE(AddressSpaceAllocatorBase);

View file

@ -17,6 +17,7 @@
#include <stratosphere.hpp>
#include "os_rng_manager_impl.hpp"
#include "os_thread_manager_types.hpp"
#include "os_stack_guard_manager_types.hpp"
#include "os_tick_manager_impl.hpp"
#include "os_aslr_space_manager_types.hpp"
#include "os_tls_manager_types.hpp"
@ -29,7 +30,7 @@ namespace ams::os::impl {
private:
RngManager m_rng_manager{};
AslrSpaceManager m_aslr_space_manager{};
/* TODO */
StackGuardManager m_stack_guard_manager;
ThreadManager m_thread_manager{};
//TlsManager m_tls_manager{};
TickManager m_tick_manager{};
@ -42,6 +43,7 @@ namespace ams::os::impl {
constexpr ALWAYS_INLINE RngManager &GetRngManager() { return m_rng_manager; }
constexpr ALWAYS_INLINE AslrSpaceManager &GetAslrSpaceManager() { return m_aslr_space_manager; }
constexpr ALWAYS_INLINE ThreadManager &GetThreadManager() { return m_thread_manager; }
constexpr ALWAYS_INLINE StackGuardManager &GetStackGuardManager() { return m_stack_guard_manager; }
//constexpr ALWAYS_INLINE TlsManager &GetTlsManager() { return m_tls_manager; }
constexpr ALWAYS_INLINE TickManager &GetTickManager() { return m_tick_manager; }
constexpr ALWAYS_INLINE VammManager &GetVammManager() { return m_vamm_manager; }

View file

@ -0,0 +1,26 @@
/*
* 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>
#include "os_resource_manager.hpp"
namespace ams::os::impl {
ALWAYS_INLINE StackGuardManager &GetStackGuardManager() {
return GetResourceManager().GetStackGuardManager();
}
}

View file

@ -0,0 +1,36 @@
/*
* 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 StackGuardManagerHorizonImpl {
private:
static u64 GetStackInfo(svc::InfoType type) {
u64 value;
R_ABORT_UNLESS(svc::GetInfo(std::addressof(value), type, svc::PseudoHandle::CurrentProcess, 0));
AMS_ASSERT(value <= std::numeric_limits<size_t>::max());
return static_cast<u64>(static_cast<size_t>(value));
}
public:
static u64 GetStackGuardBeginAddress() { return GetStackInfo(svc::InfoType_StackRegionAddress); }
static u64 GetStackGuardEndAddress() { return GetStackInfo(svc::InfoType_StackRegionSize); }
};
using StackGuardManagerImpl = StackGuardManagerHorizonImpl;
}

View file

@ -0,0 +1,29 @@
/*
* 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 StackGuardManagerLinuxImpl {
public:
static u64 GetStackGuardBeginAddress() { return 256_MB; }
static u64 GetStackGuardEndAddress() { return 256_MB + 1_GB; }
};
using StackGuardManagerImpl = StackGuardManagerLinuxImpl;
}

View file

@ -0,0 +1,29 @@
/*
* 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 StackGuardManagerMacosImpl {
public:
static u64 GetStackGuardBeginAddress() { return 256_MB; }
static u64 GetStackGuardEndAddress() { return 256_MB + 1_GB; }
};
using StackGuardManagerImpl = StackGuardManagerMacosImpl;
}

View file

@ -0,0 +1,29 @@
/*
* 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 StackGuardManagerWindowsImpl {
public:
static u64 GetStackGuardBeginAddress() { return 256_MB; }
static u64 GetStackGuardEndAddress() { return 256_MB + 1_GB; }
};
using StackGuardManagerImpl = StackGuardManagerWindowsImpl;
}

View file

@ -0,0 +1,81 @@
/*
* 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>
#include "os_address_space_allocator.hpp"
#if defined(ATMOSPHERE_OS_HORIZON)
#include "os_stack_guard_manager_impl.os.horizon.hpp"
#elif defined(ATMOSPHERE_OS_WINDOWS)
#include "os_stack_guard_manager_impl.os.windows.hpp"
#elif defined(ATMOSPHERE_OS_LINUX)
#include "os_stack_guard_manager_impl.os.linux.hpp"
#elif defined(ATMOSPHERE_OS_MACOS)
#include "os_stack_guard_manager_impl.os.macos.hpp"
#else
#error "Unknown OS for StackGuardManagerImpl"
#endif
namespace ams::os::impl {
constexpr inline size_t StackGuardSize = 4 * os::MemoryPageSize;
class StackGuardManager {
private:
StackGuardManagerImpl m_impl;
AddressSpaceAllocator m_allocator;
public:
StackGuardManager() : m_impl(), m_allocator(m_impl.GetStackGuardBeginAddress(), m_impl.GetStackGuardEndAddress(), StackGuardSize, nullptr, 0) {
/* ... */
}
void *AllocateStackGuardSpace(size_t size) {
return reinterpret_cast<void *>(m_allocator.AllocateSpace(size, os::MemoryPageSize, 0));
}
bool CheckGuardSpace(uintptr_t address, size_t size) {
return m_allocator.CheckGuardSpace(address, size, StackGuardSize);
}
AddressAllocationResult MapAtRandomAddress(void **out, bool (*map)(const void *, const void *, size_t), void (*unmap)(const void *, const void *, size_t), const void *address, size_t size) {
/* Try to map up to 0x40 times. */
constexpr int TryCountMax = 0x40;
for (auto i = 0; i < TryCountMax; ++i) {
/* Get stack guard space. */
void * const space = this->AllocateStackGuardSpace(size);
if (space == nullptr) {
return AddressAllocationResult_OutOfMemory;
}
/* Try to map. */
if (map(space, address, size)) {
/* Check that the guard space is still there. */
if (this->CheckGuardSpace(reinterpret_cast<uintptr_t>(space), size)) {
*out = space;
return AddressAllocationResult_Success;
} else {
/* We need to retry. */
unmap(space, address, size);
}
}
}
/* We failed. */
return AddressAllocationResult_OutOfSpace;
}
};
}

View file

@ -33,12 +33,6 @@ namespace ams::os::impl {
namespace {
enum AddressAllocationResult {
AddressAllocationResult_Success,
AddressAllocationResult_OutOfMemory,
AddressAllocationResult_OutOfSpace,
};
class AddressRegion : public util::IntrusiveRedBlackTreeBaseNode<AddressRegion> {
private:
uintptr_t m_address;