mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-17 17:36:44 +00:00
ro: support NROs with read-only first page
This commit is contained in:
parent
4baf0e8cce
commit
5c6362c56d
4 changed files with 27 additions and 8 deletions
|
@ -135,14 +135,15 @@ namespace ams::ro {
|
||||||
class NroHeader {
|
class NroHeader {
|
||||||
public:
|
public:
|
||||||
static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code;
|
static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code;
|
||||||
|
static constexpr u32 FlagAlignedHeader = 1;
|
||||||
private:
|
private:
|
||||||
u32 m_entrypoint_insn;
|
u32 m_entrypoint_insn;
|
||||||
u32 m_mod_offset;
|
u32 m_mod_offset;
|
||||||
u8 m_reserved_08[0x8];
|
u8 m_reserved_08[0x8];
|
||||||
u32 m_magic;
|
u32 m_magic;
|
||||||
u8 m_reserved_14[0x4];
|
u8 m_version;
|
||||||
u32 m_size;
|
u32 m_size;
|
||||||
u8 m_reserved_1C[0x4];
|
u32 m_flags;
|
||||||
u32 m_text_offset;
|
u32 m_text_offset;
|
||||||
u32 m_text_size;
|
u32 m_text_size;
|
||||||
u32 m_ro_offset;
|
u32 m_ro_offset;
|
||||||
|
@ -158,10 +159,22 @@ namespace ams::ro {
|
||||||
return m_magic == Magic;
|
return m_magic == Magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetVersion() const {
|
||||||
|
return m_version;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetSize() const {
|
u32 GetSize() const {
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetFlags() const {
|
||||||
|
return m_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAlignedHeader() const {
|
||||||
|
return m_flags & FlagAlignedHeader;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetTextOffset() const {
|
u32 GetTextOffset() const {
|
||||||
return m_text_offset;
|
return m_text_offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,15 @@ namespace ams::ro::impl {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SetNroPerms(os::NativeHandle process_handle, u64 base_address, u64 rx_size, u64 ro_size, u64 rw_size) {
|
Result SetNroPerms(os::NativeHandle process_handle, u64 base_address, u64 rx_size, u64 ro_size, u64 rw_size, bool is_aligned_header) {
|
||||||
const u64 rx_offset = 0;
|
const u64 rx_offset = is_aligned_header ? os::MemoryPageSize : 0;
|
||||||
const u64 ro_offset = rx_offset + rx_size;
|
const u64 ro_offset = rx_offset + rx_size;
|
||||||
const u64 rw_offset = ro_offset + ro_size;
|
const u64 rw_offset = ro_offset + ro_size;
|
||||||
|
|
||||||
|
if (is_aligned_header) {
|
||||||
|
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address, os::MemoryPageSize, os::MemoryPermission_ReadOnly));
|
||||||
|
}
|
||||||
|
|
||||||
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + rx_offset, rx_size, os::MemoryPermission_ReadExecute));
|
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + rx_offset, rx_size, os::MemoryPermission_ReadExecute));
|
||||||
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + ro_offset, ro_size, os::MemoryPermission_ReadOnly));
|
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + ro_offset, ro_size, os::MemoryPermission_ReadOnly));
|
||||||
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + rw_offset, rw_size, os::MemoryPermission_ReadWrite));
|
R_TRY(os::SetProcessMemoryPermission(process_handle, base_address + rw_offset, rw_size, os::MemoryPermission_ReadWrite));
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace ams::ro::impl {
|
||||||
|
|
||||||
/* Utilities for working with NROs. */
|
/* Utilities for working with NROs. */
|
||||||
Result MapNro(u64 *out_base_address, os::NativeHandle process_handle, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size);
|
Result MapNro(u64 *out_base_address, os::NativeHandle process_handle, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size);
|
||||||
Result SetNroPerms(os::NativeHandle process_handle, u64 base_address, u64 rx_size, u64 ro_size, u64 rw_size);
|
Result SetNroPerms(os::NativeHandle process_handle, u64 base_address, u64 rx_size, u64 ro_size, u64 rw_size, bool is_aligned_header);
|
||||||
Result UnmapNro(os::NativeHandle process_handle, u64 base_address, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size);
|
Result UnmapNro(os::NativeHandle process_handle, u64 base_address, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size);
|
||||||
|
|
||||||
}
|
}
|
|
@ -247,7 +247,7 @@ namespace ams::ro::impl {
|
||||||
R_THROW(ro::ResultNotAuthorized());
|
R_THROW(ro::ResultNotAuthorized());
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
Result ValidateNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, bool *out_aligned_header, u64 base_address, u64 expected_nro_size, u64 expected_bss_size) {
|
||||||
/* Map the NRO. */
|
/* Map the NRO. */
|
||||||
void *mapped_memory = nullptr;
|
void *mapped_memory = nullptr;
|
||||||
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) {
|
R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) {
|
||||||
|
@ -306,6 +306,7 @@ namespace ams::ro::impl {
|
||||||
*out_rx_size = text_size;
|
*out_rx_size = text_size;
|
||||||
*out_ro_size = ro_size;
|
*out_ro_size = ro_size;
|
||||||
*out_rw_size = rw_size;
|
*out_rw_size = rw_size;
|
||||||
|
*out_aligned_header = header->IsAlignedHeader();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,10 +558,11 @@ namespace ams::ro::impl {
|
||||||
|
|
||||||
/* Validate the NRO (parsing region extents). */
|
/* Validate the NRO (parsing region extents). */
|
||||||
u64 rx_size = 0, ro_size = 0, rw_size = 0;
|
u64 rx_size = 0, ro_size = 0, rw_size = 0;
|
||||||
R_TRY(context->ValidateNro(std::addressof(nro_info->module_id), std::addressof(rx_size), std::addressof(ro_size), std::addressof(rw_size), nro_info->base_address, nro_size, bss_size));
|
bool aligned_header = false;
|
||||||
|
R_TRY(context->ValidateNro(std::addressof(nro_info->module_id), std::addressof(rx_size), std::addressof(ro_size), std::addressof(rw_size), std::addressof(aligned_header), nro_info->base_address, nro_size, bss_size));
|
||||||
|
|
||||||
/* Set NRO perms. */
|
/* Set NRO perms. */
|
||||||
R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, rx_size, ro_size, rw_size + bss_size));
|
R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, rx_size, ro_size, rw_size + bss_size, aligned_header));
|
||||||
|
|
||||||
context->SetNroInfoInUse(nro_info, true);
|
context->SetNroInfoInUse(nro_info, true);
|
||||||
nro_info->code_size = rx_size + ro_size;
|
nro_info->code_size = rx_size + ro_size;
|
||||||
|
|
Loading…
Reference in a new issue