mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-14 00:56:35 +00:00
62 lines
2 KiB
C
62 lines
2 KiB
C
|
#include <stdint.h>
|
||
|
|
||
|
#include "utils.h"
|
||
|
#include "userpage.h"
|
||
|
|
||
|
uint64_t g_secure_page_user_address = NULL;
|
||
|
|
||
|
/* Create a user page reference for the desired address. */
|
||
|
/* Returns 1 on success, 0 on failure. */
|
||
|
int upage_init(upage_ref_t *upage, void *user_address) {
|
||
|
upage->user_page = get_page_for_address(user_address);
|
||
|
upage->secure_page = 0ULL;
|
||
|
|
||
|
if (g_secure_page_user_address != NULL) {
|
||
|
/* Different ASLR'd address indicate SPL was rebooted. Panic. */
|
||
|
if (g_secure_page_user_address != upage->user_page) {
|
||
|
panic();
|
||
|
}
|
||
|
upage->secure_page = SECURE_USER_PAGE_ADDR;
|
||
|
} else {
|
||
|
/* Official (weak) validation for SPL's ASLR'd address. */
|
||
|
if (upage->user_page >> 31) {
|
||
|
g_secure_page_user_address = upage->user_page;
|
||
|
/* TODO: Map this page into the MMU and invalidate the TLB. */
|
||
|
upage->secure_page = SECURE_USER_PAGE_ADDR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return upage->secure_page != 0ULL;
|
||
|
}
|
||
|
|
||
|
int user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, size_t size) {
|
||
|
/* Fail if the page doesn't match. */
|
||
|
if (get_page_for_address(user_src) != upage->user_page) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Fail if we go past the page boundary. */
|
||
|
if (size != 0 && get_page_for_address(user_src + size - 1) != upage->user_page) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void *secure_src = (void *)(upage->secure_page + ((uint64_t)user_src - upage->user_page));
|
||
|
memcpy(secure_dst, secure_src, size);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int secure_copy_to_user(upage_ref_t *upage, void *user_dst, void *secure_src, size_t size) {
|
||
|
/* Fail if the page doesn't match. */
|
||
|
if (get_page_for_address(user_dst) != upage->user_page) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Fail if we go past the page boundary. */
|
||
|
if (size != 0 && get_page_for_address(user_dst + size - 1) != upage->user_page) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void *secure_dst = (void *)(upage->secure_page + ((uint64_t)user_dst - upage->user_page));
|
||
|
memcpy(secure_dst, secure_src, size);
|
||
|
return 1;
|
||
|
}
|