mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-06 04:01:44 +00:00
loader: fix ldr:ro unmap semantics for < 3.0.0
This commit is contained in:
parent
e7f941fa3d
commit
db3c5cf20f
2 changed files with 62 additions and 45 deletions
|
@ -151,13 +151,15 @@ struct MappedCodeMemory {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unmap() {
|
Result Unmap() {
|
||||||
|
Result rc = 0;
|
||||||
if (this->IsMapped()) {
|
if (this->IsMapped()) {
|
||||||
if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->code_memory_address, this->size))) {
|
if (R_FAILED((rc = svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->code_memory_address, this->size)))) {
|
||||||
/* TODO: panic(). */
|
/* TODO: panic(). */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->mapped_address = NULL;
|
this->mapped_address = NULL;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() {
|
void Close() {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include <stratosphere.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -46,16 +47,26 @@ Result NroUtils::ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min
|
||||||
}
|
}
|
||||||
|
|
||||||
Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size, u64 *out_address) {
|
Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size, u64 *out_address) {
|
||||||
NroHeader *nro;
|
NroHeader nro_hdr = {0};
|
||||||
MappedCodeMemory mcm_nro = {0};
|
MappedCodeMemory mcm_nro = {0};
|
||||||
MappedCodeMemory mcm_bss = {0};
|
MappedCodeMemory mcm_bss = {0};
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
Result rc;
|
Result rc = 0;
|
||||||
u8 nro_hash[0x20];
|
u8 nro_hash[0x20];
|
||||||
struct sha256_state sha_ctx;
|
struct sha256_state sha_ctx;
|
||||||
|
|
||||||
|
/* Perform cleanup on failure. */
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
mcm_nro.Close();
|
||||||
|
mcm_bss.Close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Ensure there is an available NRO slot. */
|
/* Ensure there is an available NRO slot. */
|
||||||
if (std::all_of(target_proc->nro_infos.begin(), target_proc->nro_infos.end(), std::mem_fn(&Registration::NroInfo::in_use))) {
|
if (std::all_of(target_proc->nro_infos.begin(), target_proc->nro_infos.end(), std::mem_fn(&Registration::NroInfo::in_use))) {
|
||||||
return 0x6E09;
|
rc = 0x6E09;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 0x200; i++) {
|
for (i = 0; i < 0x200; i++) {
|
||||||
if (R_SUCCEEDED(mcm_nro.Open(process_h, target_proc->is_64_bit_addspace, nro_heap_address, nro_heap_size))) {
|
if (R_SUCCEEDED(mcm_nro.Open(process_h, target_proc->is_64_bit_addspace, nro_heap_address, nro_heap_size))) {
|
||||||
|
@ -67,68 +78,72 @@ Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= 0x200) {
|
if (i >= 0x200) {
|
||||||
return 0x6609;
|
rc = 0x6609;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Map the NRO. */
|
||||||
if (R_FAILED((rc = mcm_nro.Map()))) {
|
if (R_FAILED((rc = mcm_nro.Map()))) {
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
nro = (NroHeader *)mcm_nro.mapped_address;
|
/* Read data from NRO while it's mapped. */
|
||||||
if (nro->magic != MAGIC_NRO0) {
|
{
|
||||||
rc = 0x6809;
|
nro_hdr = *((NroHeader *)mcm_nro.mapped_address);
|
||||||
goto LOAD_NRO_END;
|
|
||||||
}
|
|
||||||
if (nro->nro_size != nro_heap_size || nro->bss_size != bss_heap_size) {
|
|
||||||
rc = 0x6809;
|
|
||||||
goto LOAD_NRO_END;
|
|
||||||
}
|
|
||||||
if ((nro->text_size & 0xFFF) || (nro->ro_size & 0xFFF) || (nro->rw_size & 0xFFF) || (nro->bss_size & 0xFFF)) {
|
|
||||||
rc = 0x6809;
|
|
||||||
goto LOAD_NRO_END;
|
|
||||||
}
|
|
||||||
if (nro->text_offset != 0 || nro->text_offset + nro->text_size != nro->ro_offset || nro->ro_offset + nro->ro_size != nro->rw_offset || nro->rw_offset + nro->rw_size != nro->nro_size) {
|
|
||||||
rc = 0x6809;
|
|
||||||
goto LOAD_NRO_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (nro_hdr.magic != MAGIC_NRO0) {
|
||||||
|
rc = 0x6809;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (nro_hdr.nro_size != nro_heap_size || nro_hdr.bss_size != bss_heap_size) {
|
||||||
|
rc = 0x6809;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if ((nro_hdr.text_size & 0xFFF) || (nro_hdr.ro_size & 0xFFF) || (nro_hdr.rw_size & 0xFFF) || (nro_hdr.bss_size & 0xFFF)) {
|
||||||
|
rc = 0x6809;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (nro_hdr.text_offset != 0 || nro_hdr.text_offset + nro_hdr.text_size != nro_hdr.ro_offset || nro_hdr.ro_offset + nro_hdr.ro_size != nro_hdr.rw_offset || nro_hdr.rw_offset + nro_hdr.rw_size != nro_hdr.nro_size) {
|
||||||
|
rc = 0x6809;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
sha256_init(&sha_ctx);
|
sha256_init(&sha_ctx);
|
||||||
sha256_update(&sha_ctx, (u8 *)nro, nro->nro_size);
|
sha256_update(&sha_ctx, (u8 *)mcm_nro.mapped_address, nro_hdr.nro_size);
|
||||||
sha256_finalize(&sha_ctx);
|
sha256_finalize(&sha_ctx);
|
||||||
sha256_finish(&sha_ctx, nro_hash);
|
sha256_finish(&sha_ctx, nro_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmap the NRO. */
|
||||||
|
if (R_FAILED((rc = mcm_nro.Unmap()))) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Registration::IsNroHashPresent(target_proc->index, nro_hash)) {
|
if (!Registration::IsNroHashPresent(target_proc->index, nro_hash)) {
|
||||||
rc = 0x6C09;
|
rc = 0x6C09;
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Registration::IsNroAlreadyLoaded(target_proc->index, nro_hash)) {
|
if (Registration::IsNroAlreadyLoaded(target_proc->index, nro_hash)) {
|
||||||
rc = 0x7209;
|
rc = 0x7209;
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address, nro->text_size, 5)))) {
|
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address, nro_hdr.text_size, 5)))) {
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro->ro_offset, nro->ro_size, 1)))) {
|
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro_hdr.ro_offset, nro_hdr.ro_size, 1)))) {
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro->rw_offset, nro->rw_size + nro->bss_size, 3)))) {
|
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro_hdr.rw_offset, nro_hdr.rw_size + nro_hdr.bss_size, 3)))) {
|
||||||
goto LOAD_NRO_END;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Registration::AddNroToProcess(target_proc->index, &mcm_nro, &mcm_bss, nro->text_size, nro->ro_size, nro->rw_size, nro->build_id);
|
Registration::AddNroToProcess(target_proc->index, &mcm_nro, &mcm_bss, nro_hdr.text_size, nro_hdr.ro_size, nro_hdr.rw_size, nro_hdr.build_id);
|
||||||
*out_address = mcm_nro.code_memory_address;
|
*out_address = mcm_nro.code_memory_address;
|
||||||
mcm_nro.Unmap();
|
|
||||||
mcm_bss.Unmap();
|
|
||||||
rc = 0x0;
|
rc = 0x0;
|
||||||
|
|
||||||
LOAD_NRO_END:
|
return rc;
|
||||||
if (R_FAILED(rc)) {
|
|
||||||
mcm_nro.Close();
|
|
||||||
mcm_bss.Close();
|
|
||||||
}
|
|
||||||
return 0x0;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue