mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-10 14:11:43 +00:00
Loader: Implement NSO Extent calculation (note: ASLR currently disabled due to lack of entropy source.)
This commit is contained in:
parent
6afd59d2a2
commit
b11c2fe755
3 changed files with 103 additions and 1 deletions
|
@ -85,5 +85,87 @@ Result NsoUtils::ValidateNsoLoadSet() {
|
|||
}
|
||||
}
|
||||
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
|
||||
Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLoadExtents *extents) {
|
||||
*extents = (const NsoUtils::NsoLoadExtents){0};
|
||||
/* Calculate base offsets. */
|
||||
for (unsigned int i = 0; i < NSO_NUM_MAX; i++) {
|
||||
if (g_nso_present[i]) {
|
||||
extents->nso_addresses[i] = extents->total_size;
|
||||
u32 text_end = g_nso_headers[i].segments[0].dst_offset + g_nso_headers[i].segments[0].decomp_size;
|
||||
u32 ro_end = g_nso_headers[i].segments[1].dst_offset + g_nso_headers[i].segments[1].decomp_size;
|
||||
u32 rw_end = g_nso_headers[i].segments[2].dst_offset + g_nso_headers[i].segments[2].decomp_size + g_nso_headers[i].segments[2].align_or_total_size;
|
||||
extents->nso_sizes[i] = text_end;
|
||||
if (extents->nso_sizes[i] < ro_end) {
|
||||
extents->nso_sizes[i] = ro_end;
|
||||
}
|
||||
if (extents->nso_sizes[i] < rw_end) {
|
||||
extents->nso_sizes[i] = rw_end;
|
||||
}
|
||||
extents->nso_sizes[i] += 0xFFF;
|
||||
extents->nso_sizes[i] &= ~0xFFFULL;
|
||||
extents->total_size += extents->nso_sizes[i];
|
||||
if (args_size && !extents->args_size) {
|
||||
extents->args_address = extents->total_size;
|
||||
/* What the fuck? Where does 0x9007 come from? */
|
||||
extents->args_size = (2 * args_size + 0x9007);
|
||||
extents->args_size &= ~0xFFFULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate ASLR extents for address space type. */
|
||||
u64 addspace_start, addspace_size, addspace_end;
|
||||
if (kernelAbove200()) {
|
||||
switch (addspace_type & 0xE) {
|
||||
case 0:
|
||||
case 4:
|
||||
addspace_start = 0x200000ULL;
|
||||
addspace_size = 0x3FE00000ULL;
|
||||
break;
|
||||
case 2:
|
||||
addspace_start = 0x8000000ULL;
|
||||
addspace_size = 0x78000000ULL;
|
||||
break;
|
||||
case 6:
|
||||
addspace_start = 0x8000000ULL;
|
||||
addspace_size = 0x7FF8000000ULL;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Panic. */
|
||||
return 0xD001;
|
||||
}
|
||||
} else {
|
||||
if (addspace_type & 2) {
|
||||
addspace_start = 0x8000000ULL;
|
||||
addspace_size = 0x78000000ULL;
|
||||
} else {
|
||||
addspace_start = 0x200000ULL;
|
||||
addspace_size = 0x3FE00000ULL;
|
||||
}
|
||||
}
|
||||
addspace_end = addspace_start + addspace_size;
|
||||
if (addspace_start + extents->total_size > addspace_end) {
|
||||
return 0xD001;
|
||||
}
|
||||
|
||||
u64 aslr_slide = 0;
|
||||
if (addspace_type & 0x20) {
|
||||
/* TODO: Apply a random ASLR slide. */
|
||||
}
|
||||
|
||||
extents->base_address = addspace_start + aslr_slide;
|
||||
for (unsigned int i = 0; i < NSO_NUM_MAX; i++) {
|
||||
if (g_nso_present[i]) {
|
||||
extents->nso_addresses[i] += extents->base_address;
|
||||
}
|
||||
}
|
||||
if (extents->args_address) {
|
||||
extents->args_address += extents->base_address;
|
||||
}
|
||||
|
||||
return 0x0;
|
||||
}
|
|
@ -28,6 +28,15 @@ class NsoUtils {
|
|||
u8 section_hashes[3][0x20];
|
||||
};
|
||||
|
||||
struct NsoLoadExtents {
|
||||
u64 base_address;
|
||||
u64 total_size;
|
||||
u64 args_address;
|
||||
u64 args_size;
|
||||
u64 nso_addresses[NSO_NUM_MAX];
|
||||
u64 nso_sizes[NSO_NUM_MAX];
|
||||
};
|
||||
|
||||
|
||||
static_assert(sizeof(NsoHeader) == 0x100, "Incorrectly defined NsoHeader!");
|
||||
|
||||
|
@ -72,4 +81,5 @@ class NsoUtils {
|
|||
static bool IsNsoPresent(unsigned int index);
|
||||
static Result LoadNsoHeaders(u64 title_id);
|
||||
static Result ValidateNsoLoadSet();
|
||||
static Result CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLoadExtents *extents);
|
||||
};
|
|
@ -89,6 +89,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle
|
|||
Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nca_path, LaunchQueue::LaunchItem *launch_item, u64 arg_flags, Handle reslimit_h) {
|
||||
NpdmUtils::NpdmInfo npdm_info = {0};
|
||||
ProcessInfo process_info = {0};
|
||||
NsoUtils::NsoLoadExtents nso_extents = {0};
|
||||
Registration::Process *target_process;
|
||||
Handle process_h = 0;
|
||||
Result rc;
|
||||
|
@ -141,7 +142,16 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
|
||||
/* TODO: Figure out where NSOs will be mapped, and how much space they (and arguments) will take up. */
|
||||
/* Figure out where NSOs will be mapped, and how much space they (and arguments) will take up. */
|
||||
rc = NsoUtils::CalculateNsoLoadExtents(launch_item != NULL ? launch_item->arg_size : 0, process_info.process_flags, &nso_extents);
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
|
||||
/* Set Address Space information in ProcessInfo. */
|
||||
process_info.code_addr = nso_extents.base_address;
|
||||
process_info.code_num_pages = nso_extents.total_size + 0xFFF;
|
||||
process_info.code_num_pages >>= 12;
|
||||
|
||||
/* Call svcCreateProcess(). */
|
||||
rc = svcCreateProcess(&process_h, &process_info, (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32));
|
||||
|
|
Loading…
Reference in a new issue