mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 05:42:17 +00:00
kern: add new KCapability checks before creating process
This commit is contained in:
parent
14e768cd10
commit
8cb3cfd835
3 changed files with 48 additions and 5 deletions
|
@ -116,7 +116,7 @@ namespace ams::kern {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class RegionType : u32 {
|
enum class RegionType : u32 {
|
||||||
None = 0,
|
NoMapping = 0,
|
||||||
KernelTraceBuffer = 1,
|
KernelTraceBuffer = 1,
|
||||||
OnMemoryBootImage = 2,
|
OnMemoryBootImage = 2,
|
||||||
DTB = 3,
|
DTB = 3,
|
||||||
|
@ -219,6 +219,10 @@ namespace ams::kern {
|
||||||
Result SetHandleTableCapability(const util::BitPack32 cap);
|
Result SetHandleTableCapability(const util::BitPack32 cap);
|
||||||
Result SetDebugFlagsCapability(const util::BitPack32 cap);
|
Result SetDebugFlagsCapability(const util::BitPack32 cap);
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
static Result ProcessMapRegionCapability(const util::BitPack32 cap, F f);
|
||||||
|
static Result CheckMapRegion(const util::BitPack32 cap);
|
||||||
|
|
||||||
Result SetCapability(const util::BitPack32 cap, u32 &set_flags, u32 &set_svc, KProcessPageTable *page_table);
|
Result SetCapability(const util::BitPack32 cap, u32 &set_flags, u32 &set_svc, KProcessPageTable *page_table);
|
||||||
Result SetCapabilities(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
|
Result SetCapabilities(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
|
||||||
Result SetCapabilities(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);
|
Result SetCapabilities(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);
|
||||||
|
@ -229,6 +233,8 @@ namespace ams::kern {
|
||||||
Result Initialize(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
|
Result Initialize(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
|
||||||
Result Initialize(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);
|
Result Initialize(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);
|
||||||
|
|
||||||
|
static Result CheckCapabilities(svc::KUserPointer<const u32 *> user_caps, s32 num_caps);
|
||||||
|
|
||||||
constexpr u64 GetCoreMask() const { return m_core_mask; }
|
constexpr u64 GetCoreMask() const { return m_core_mask; }
|
||||||
constexpr u64 GetPriorityMask() const { return m_priority_mask; }
|
constexpr u64 GetPriorityMask() const { return m_priority_mask; }
|
||||||
constexpr s32 GetHandleTableSize() const { return m_handle_table_size; }
|
constexpr s32 GetHandleTableSize() const { return m_handle_table_size; }
|
||||||
|
|
|
@ -156,9 +156,10 @@ namespace ams::kern {
|
||||||
R_RETURN(page_table->MapIo(phys_addr, size, KMemoryPermission_UserReadWrite));
|
R_RETURN(page_table->MapIo(phys_addr, size, KMemoryPermission_UserReadWrite));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KCapabilities::MapRegion(const util::BitPack32 cap, KProcessPageTable *page_table) {
|
template<typename F>
|
||||||
|
ALWAYS_INLINE Result KCapabilities::ProcessMapRegionCapability(const util::BitPack32 cap, F f) {
|
||||||
/* Define the allowed memory regions. */
|
/* Define the allowed memory regions. */
|
||||||
constexpr KMemoryRegionType MemoryRegions[] = {
|
constexpr const KMemoryRegionType MemoryRegions[] = {
|
||||||
KMemoryRegionType_None,
|
KMemoryRegionType_None,
|
||||||
KMemoryRegionType_KernelTraceBuffer,
|
KMemoryRegionType_KernelTraceBuffer,
|
||||||
KMemoryRegionType_OnMemoryBootImage,
|
KMemoryRegionType_OnMemoryBootImage,
|
||||||
|
@ -173,12 +174,12 @@ namespace ams::kern {
|
||||||
const auto type = types[i];
|
const auto type = types[i];
|
||||||
const auto perm = ro[i] ? KMemoryPermission_UserRead : KMemoryPermission_UserReadWrite;
|
const auto perm = ro[i] ? KMemoryPermission_UserRead : KMemoryPermission_UserReadWrite;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RegionType::None:
|
case RegionType::NoMapping:
|
||||||
break;
|
break;
|
||||||
case RegionType::KernelTraceBuffer:
|
case RegionType::KernelTraceBuffer:
|
||||||
case RegionType::OnMemoryBootImage:
|
case RegionType::OnMemoryBootImage:
|
||||||
case RegionType::DTB:
|
case RegionType::DTB:
|
||||||
R_TRY(page_table->MapRegion(MemoryRegions[static_cast<u32>(type)], perm));
|
R_TRY(f(MemoryRegions[static_cast<u32>(type)], perm));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
R_THROW(svc::ResultNotFound());
|
R_THROW(svc::ResultNotFound());
|
||||||
|
@ -188,6 +189,22 @@ namespace ams::kern {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::MapRegion(const util::BitPack32 cap, KProcessPageTable *page_table) {
|
||||||
|
/* Map each region into the process's page table. */
|
||||||
|
R_RETURN(ProcessMapRegionCapability(cap, [page_table] ALWAYS_INLINE_LAMBDA (KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
|
||||||
|
R_RETURN(page_table->MapRegion(region_type, perm));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::CheckMapRegion(const util::BitPack32 cap) {
|
||||||
|
/* Check that each region has a physical backing store. */
|
||||||
|
R_RETURN(ProcessMapRegionCapability(cap, [] ALWAYS_INLINE_LAMBDA (KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
|
||||||
|
MESOSPHERE_UNUSED(perm);
|
||||||
|
R_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(region_type) != nullptr, svc::ResultOutOfRange());
|
||||||
|
R_SUCCEED();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
Result KCapabilities::SetInterruptPairCapability(const util::BitPack32 cap) {
|
Result KCapabilities::SetInterruptPairCapability(const util::BitPack32 cap) {
|
||||||
/* Extract interrupts. */
|
/* Extract interrupts. */
|
||||||
const u32 ids[2] = { cap.Get<InterruptPair::InterruptId0>(), cap.Get<InterruptPair::InterruptId1>(), };
|
const u32 ids[2] = { cap.Get<InterruptPair::InterruptId0>(), cap.Get<InterruptPair::InterruptId1>(), };
|
||||||
|
@ -320,4 +337,21 @@ namespace ams::kern {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::CheckCapabilities(svc::KUserPointer<const u32 *> user_caps, s32 num_caps) {
|
||||||
|
for (s32 i = 0; i < num_caps; ++i) {
|
||||||
|
/* Read the cap from userspace. */
|
||||||
|
u32 cap0;
|
||||||
|
R_TRY(user_caps.CopyArrayElementTo(std::addressof(cap0), i));
|
||||||
|
|
||||||
|
/* Check the capability refers to a valid region. */
|
||||||
|
|
||||||
|
const util::BitPack32 cap = { cap0 };
|
||||||
|
if (GetCapabilityType(cap) == CapabilityType::MapRegion) {
|
||||||
|
R_TRY(CheckMapRegion(cap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,9 @@ namespace ams::kern::svc {
|
||||||
const bool is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
const bool is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
||||||
R_UNLESS(!optimize_allocs || is_application, svc::ResultBusy());
|
R_UNLESS(!optimize_allocs || is_application, svc::ResultBusy());
|
||||||
|
|
||||||
|
/* Check that the user-provided capabilities are accessible and refer to valid regions. */
|
||||||
|
R_TRY(KCapabilities::CheckCapabilities(user_caps, num_caps));
|
||||||
|
|
||||||
/* Get the current handle table. */
|
/* Get the current handle table. */
|
||||||
auto &handle_table = GetCurrentProcess().GetHandleTable();
|
auto &handle_table = GetCurrentProcess().GetHandleTable();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue