kern/loader: make aware of new address space and shadow stack region
This commit is contained in:
@@ -88,14 +88,14 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
void KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
void KPageTableBase::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
/* Initialize our members. */
|
||||
m_address_space_width = (is_64_bit) ? BITSIZEOF(u64) : BITSIZEOF(u32);
|
||||
m_address_space_start = KProcessAddress(GetInteger(start));
|
||||
m_address_space_end = KProcessAddress(GetInteger(end));
|
||||
m_is_kernel = true;
|
||||
m_enable_aslr = true;
|
||||
m_enable_device_address_space_merge = false;
|
||||
m_allowed_exec_device_mapping = false;
|
||||
|
||||
for (auto i = 0; i < RegionType_Count; ++i) {
|
||||
m_region_starts[i] = 0;
|
||||
@@ -133,7 +133,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
|
||||
}
|
||||
|
||||
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||
/* Validate the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(start <= code_address);
|
||||
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
|
||||
@@ -151,9 +151,9 @@ namespace ams::kern {
|
||||
m_alias_region_extra_size = 0;
|
||||
|
||||
/* Set our width and heap/alias sizes. */
|
||||
m_address_space_width = GetAddressSpaceWidth(flags);
|
||||
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
|
||||
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
|
||||
size_t address_space_width = GetAddressSpaceWidth(flags);
|
||||
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
|
||||
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
|
||||
|
||||
/* Set code regions and determine remaining sizes. */
|
||||
KProcessAddress process_code_start;
|
||||
@@ -162,12 +162,12 @@ namespace ams::kern {
|
||||
size_t kernel_map_region_size;
|
||||
KProcessAddress before_process_code_start, after_process_code_start;
|
||||
size_t before_process_code_size, after_process_code_size;
|
||||
if (m_address_space_width == 39) {
|
||||
if (address_space_width == 39 || address_space_width == 42) {
|
||||
stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack);
|
||||
kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall);
|
||||
|
||||
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit);
|
||||
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit);
|
||||
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapHuge);
|
||||
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapHuge);
|
||||
m_alias_code_region_start = m_code_region_start;
|
||||
m_alias_code_region_end = m_code_region_end;
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace ams::kern {
|
||||
/* If we have a 39-bit address space and should, enable extra size to the alias region. */
|
||||
if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) {
|
||||
/* Extra size is 1/8th of the address space. */
|
||||
m_alias_region_extra_size = (static_cast<size_t>(1) << m_address_space_width) / 8;
|
||||
m_alias_region_extra_size = (static_cast<size_t>(1) << address_space_width) / 8;
|
||||
|
||||
alias_region_size += m_alias_region_extra_size;
|
||||
}
|
||||
@@ -208,6 +208,9 @@ namespace ams::kern {
|
||||
after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge);
|
||||
}
|
||||
|
||||
m_region_starts[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
m_region_ends[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
|
||||
/* Set other basic fields. */
|
||||
m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||
m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||
@@ -237,6 +240,9 @@ namespace ams::kern {
|
||||
|
||||
region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, };
|
||||
region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, };
|
||||
if (flags & ams::svc::CreateProcessFlag_EnableShadowStack) {
|
||||
region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, };
|
||||
}
|
||||
|
||||
/* Selection-sort the regions by size largest-to-smallest. */
|
||||
for (size_t i = 0; i < num_regions - 1; ++i) {
|
||||
@@ -399,6 +405,18 @@ namespace ams::kern {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overlap with shadow stack. */
|
||||
for (size_t ss = 0; ss < num_regions; ++ss) {
|
||||
if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) {
|
||||
if (shadow_stack_region.size != 0) {
|
||||
const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack];
|
||||
const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(kmap_last < shadow_stack_start || shadow_stack_last < kmap_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,6 +512,25 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the ShadowStack region is valid. */
|
||||
for (size_t ss = 0; ss < num_regions; ++ss) {
|
||||
if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) {
|
||||
/* If there's no shadow stack region, we have nothing to check. */
|
||||
if (shadow_stack_region.size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the shadow stack region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_ShadowStack]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_ShadowStack]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack];
|
||||
const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(shadow_stack_last < process_code_start || process_code_last < shadow_stack_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set heap and fill members. */
|
||||
@@ -1997,15 +2034,15 @@ namespace ams::kern {
|
||||
.m_address = GetInteger(m_address_space_end),
|
||||
.m_size = 0 - GetInteger(m_address_space_end),
|
||||
.m_state = static_cast<KMemoryState>(ams::svc::MemoryState_Inaccessible),
|
||||
.m_device_disable_merge_left_count = 0,
|
||||
.m_device_disable_merge_right_count = 0,
|
||||
.m_ipc_lock_count = 0,
|
||||
.m_device_use_count = 0,
|
||||
.m_ipc_disable_merge_count = 0,
|
||||
.m_permission = KMemoryPermission_None,
|
||||
.m_attribute = KMemoryAttribute_None,
|
||||
.m_original_permission = KMemoryPermission_None,
|
||||
.m_ipc_lock_count = 0,
|
||||
.m_device_use_count = 0,
|
||||
.m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None,
|
||||
.m_ipc_disable_merge_count = 0,
|
||||
.m_device_disable_merge_left_count = 0,
|
||||
.m_device_disable_merge_right_count = 0,
|
||||
};
|
||||
out_page_info->flags = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user