Files
LM 03d016fd31 etaHEN Goes Open Source
etaHEN Goes Open Source

clean tmp files

....
2025-09-07 11:10:19 -04:00

225 lines
6.3 KiB
C++

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <ps5/kernel.h>
#include "debug_log.h"
#include "kdlsym.h"
#include "mirror.h"
#include "paging.h"
#define MAX_MIRRORS 0x100
#define UNUSED(x) (void) (x)
extern "C"
{
int sceKernelUsleep(int usecs);
}
struct mirrored_page {
uint64_t user_addr;
uint64_t kernel_va;
uint64_t kernel_pa;
uint64_t orig_pa;
};
static struct mirrored_page g_mirrored_pages[MAX_MIRRORS];
int g_mirrored_page_index = 0;
void *mirror_page(uint64_t kernel_va)
{
void *user_mirror;
uint64_t pmap;
uint64_t kernel_pa;
uint64_t orig_pa;
uint64_t pf_read;
UNUSED(pf_read);
// We can only do MAX_MIRRORS mirrors, this should be plenty
if (g_mirrored_page_index >= MAX_MIRRORS) {
//SOCK_LOG("[!] exceeded mirror limit\n");
return NULL;
}
// Mask virtual address to page alignment and extract physical address
kernel_va &= 0xFFFFFFFFFFFFF000;
kernel_pa = pmap_kextract(kernel_va);
// Get process pmap
pmap = get_proc_pmap();
if (pmap == 0) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to find proc\n", kernel_va);
return NULL;
}
// Map a user page
user_mirror = mmap(0, 0x4000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_PREFAULT_READ, -1, 0);
if (user_mirror == MAP_FAILED) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to mmap failure (%s)\n", kernel_va, strerror(errno));
return NULL;
}
// Prefault page
*(uint64_t *) (user_mirror) = 0x40404040;
pf_read = *(uint64_t *) (user_mirror);
sceKernelUsleep(50000);
orig_pa = remap_page(pmap, (uint64_t) user_mirror, kernel_pa);
if (orig_pa == 0xFFFFFFFFFFFFFFFFull) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to remap page\n", kernel_va);
return NULL;
}
// Store for later for lookup & restore
g_mirrored_pages[g_mirrored_page_index].user_addr = (uint64_t) user_mirror;
g_mirrored_pages[g_mirrored_page_index].kernel_va = kernel_va;
g_mirrored_pages[g_mirrored_page_index].kernel_pa = kernel_pa;
g_mirrored_pages[g_mirrored_page_index].orig_pa = orig_pa;
g_mirrored_page_index++;
return user_mirror;
}
void *mirror_page_no_store(uint64_t kernel_va)
{
void *user_mirror;
uint64_t pmap;
uint64_t kernel_pa;
uint64_t orig_pa;
uint64_t pf_read;
UNUSED(pf_read);
// Mask virtual address to page alignment and extract physical address
kernel_va &= 0xFFFFFFFFFFFFF000;
kernel_pa = pmap_kextract(kernel_va);
// Get process pmap
pmap = get_proc_pmap();
if (pmap == 0) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to find proc\n", kernel_va);
return NULL;
}
// Map a user page
user_mirror = mmap(0, 0x4000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_PREFAULT_READ, -1, 0);
if (user_mirror == MAP_FAILED) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to mmap failure (%s)\n", kernel_va, strerror(errno));
return NULL;
}
// Prefault page
*(uint64_t *) (user_mirror) = 0x40404040;
pf_read = *(uint64_t *) (user_mirror);
sceKernelUsleep(50000);
orig_pa = remap_page(pmap, (uint64_t) user_mirror, kernel_pa);
if (orig_pa == 0xFFFFFFFFFFFFFFFFull) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to remap page\n", kernel_va);
return NULL;
}
return user_mirror;
}
// TODO: fix this to make it actually.. work
void *mirror_page_range(uint64_t kernel_va, int num_pages)
{
void *user_mirror;
uint64_t pmap;
uint64_t kernel_pa;
uint64_t orig_pa;
uint64_t pf_read;
UNUSED(pf_read);
// We can only do MAX_MIRRORS mirrors, this should be plenty
if (g_mirrored_page_index >= MAX_MIRRORS) {
//SOCK_LOG("[!] exceeded mirror limit\n");
return NULL;
}
// Mask virtual address to page alignment and extract physical address
kernel_va &= 0xFFFFFFFFFFFFF000;
kernel_pa = pmap_kextract(kernel_va);
// Get process pmap
pmap = get_proc_pmap();
if (pmap == 0) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to find proc\n", kernel_va);
return NULL;
}
// Map a user region
user_mirror = mmap(0, num_pages * 0x1000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_PREFAULT_READ, -1, 0);
if (user_mirror == MAP_FAILED) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to mmap failure (%s)\n", kernel_va, strerror(errno));
return NULL;
}
sceKernelUsleep(50000);
for (int i = 0; i < num_pages; i++) {
orig_pa = remap_page(pmap, (uint64_t) user_mirror + (i * 0x1000), kernel_pa + (i * 0x1000));
if (orig_pa == 0xFFFFFFFFFFFFFFFFull) {
//SOCK_LOG("[!] failed to mirror 0x%lx due to failure to remap page\n", kernel_va);
return NULL;
}
}
// TODO: store for later cleanup
return user_mirror;
}
void *get_mirrored_addr(uint64_t kernel_va)
{
uint64_t aligned_kernel_va;
uint64_t aligned_kernel_pa;
void *mirrored_addr;
// Mask virtual address to page alignment and extract physical address
aligned_kernel_va = kernel_va & 0xFFFFFFFFFFFFF000;
aligned_kernel_pa = pmap_kextract(aligned_kernel_va);
// Check if mirror already exists for this PA
for (int i = 0; i < g_mirrored_page_index; i++) {
if (g_mirrored_pages[i].kernel_pa == aligned_kernel_pa) {
// Return existing mirror
return (void *) (g_mirrored_pages[i].user_addr | (kernel_va & 0xFFF));
}
}
// If one doesn't, create one
mirrored_addr = mirror_page(aligned_kernel_va);
return (void *) ((uint64_t) mirrored_addr | (kernel_va & 0xFFF));
}
void reset_mirrors()
{
uint64_t pmap;
uint64_t va;
uint64_t pa;
pmap = get_proc_pmap();
if (pmap == 0) {
//SOCK_LOG("[!] failed to reset mirrors due to failure to find proc\n");
return;
}
for (int i = 0; i < g_mirrored_page_index; i++) {
va = g_mirrored_pages[i].user_addr;
pa = g_mirrored_pages[i].orig_pa;
remap_page(pmap, va, pa);
bzero(&g_mirrored_pages[i], sizeof(struct mirrored_page));
}
g_mirrored_page_index = 0;
}