mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +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 {
|
||||
public:
|
||||
static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code;
|
||||
static constexpr u32 FlagAlignedHeader = 1;
|
||||
private:
|
||||
u32 m_entrypoint_insn;
|
||||
u32 m_mod_offset;
|
||||
u8 m_reserved_08[0x8];
|
||||
u32 m_magic;
|
||||
u8 m_reserved_14[0x4];
|
||||
u8 m_version;
|
||||
u32 m_size;
|
||||
u8 m_reserved_1C[0x4];
|
||||
u32 m_flags;
|
||||
u32 m_text_offset;
|
||||
u32 m_text_size;
|
||||
u32 m_ro_offset;
|
||||
|
@ -158,10 +159,22 @@ namespace ams::ro {
|
|||
return m_magic == Magic;
|
||||
}
|
||||
|
||||
u32 GetVersion() const {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
u32 GetSize() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
u32 GetFlags() const {
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
bool IsAlignedHeader() const {
|
||||
return m_flags & FlagAlignedHeader;
|
||||
}
|
||||
|
||||
u32 GetTextOffset() const {
|
||||
return m_text_offset;
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ namespace ams::ro::impl {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SetNroPerms(os::NativeHandle process_handle, u64 base_address, u64 rx_size, u64 ro_size, u64 rw_size) {
|
||||
const u64 rx_offset = 0;
|
||||
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 = is_aligned_header ? os::MemoryPageSize : 0;
|
||||
const u64 ro_offset = rx_offset + rx_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 + ro_offset, ro_size, os::MemoryPermission_ReadOnly));
|
||||
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. */
|
||||
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);
|
||||
|
||||
}
|
|
@ -247,7 +247,7 @@ namespace ams::ro::impl {
|
|||
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. */
|
||||
void *mapped_memory = nullptr;
|
||||
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_ro_size = ro_size;
|
||||
*out_rw_size = rw_size;
|
||||
*out_aligned_header = header->IsAlignedHeader();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -557,10 +558,11 @@ namespace ams::ro::impl {
|
|||
|
||||
/* Validate the NRO (parsing region extents). */
|
||||
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. */
|
||||
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);
|
||||
nro_info->code_size = rx_size + ro_size;
|
||||
|
|
Loading…
Reference in a new issue