122 lines
2.5 KiB
C
122 lines
2.5 KiB
C
#include "env.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mman.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#define PAGE_MASK ~(0x1000ull - 1)
|
|
|
|
static int spslr_env_get_prot(void* addr, int* prot) {
|
|
FILE* f = fopen("/proc/self/maps", "r");
|
|
if (!f)
|
|
return -1;
|
|
|
|
spslr_uintptr query = (spslr_uintptr)addr;
|
|
char line[512];
|
|
|
|
while (fgets(line, sizeof(line), f)) {
|
|
spslr_uintptr start, end;
|
|
char perms[5];
|
|
|
|
if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3)
|
|
continue;
|
|
|
|
if (query < start || query >= end)
|
|
continue;
|
|
|
|
*prot = 0;
|
|
|
|
if (perms[0] == 'r')
|
|
*prot |= PROT_READ;
|
|
if (perms[1] == 'w')
|
|
*prot |= PROT_WRITE;
|
|
if (perms[2] == 'x')
|
|
*prot |= PROT_EXEC;
|
|
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
fclose(f);
|
|
return -1;
|
|
}
|
|
|
|
static void spslr_env_poke_safe(void* dst, const void* src, spslr_u32 n) {
|
|
int original_prot;
|
|
if (spslr_env_get_prot(dst, &original_prot))
|
|
spslr_env_panic("failed to get prot of text poke destination");
|
|
|
|
spslr_u64 ptr_uint = (spslr_u64)dst;
|
|
spslr_u64 ptr_page = ptr_uint & PAGE_MASK;
|
|
spslr_u64 prot_size = n + (ptr_uint - ptr_page);
|
|
|
|
int tmp_prot = original_prot | PROT_WRITE;
|
|
|
|
if (tmp_prot != original_prot)
|
|
mprotect((void*)ptr_page, prot_size, tmp_prot);
|
|
|
|
spslr_env_memcpy(dst, src, n);
|
|
|
|
if (tmp_prot != original_prot)
|
|
mprotect((void*)ptr_page, prot_size, original_prot);
|
|
}
|
|
|
|
void spslr_env_panic(const char* reason) {
|
|
fprintf(stderr, "[spslr_panic] %s\n", reason);
|
|
exit(1);
|
|
}
|
|
|
|
void spslr_env_poke_text_8(void* dst, spslr_u8 value) {
|
|
spslr_env_poke_safe(dst, &value, sizeof(value));
|
|
}
|
|
|
|
void spslr_env_poke_text_16(void* dst, spslr_u16 value) {
|
|
spslr_env_poke_safe(dst, &value, sizeof(value));
|
|
}
|
|
|
|
void spslr_env_poke_text_32(void* dst, spslr_u32 value) {
|
|
spslr_env_poke_safe(dst, &value, sizeof(value));
|
|
}
|
|
|
|
void spslr_env_poke_text_64(void* dst, spslr_u64 value) {
|
|
spslr_env_poke_safe(dst, &value, sizeof(value));
|
|
}
|
|
|
|
void* spslr_env_malloc(spslr_u32 n) {
|
|
void* res = malloc(n);
|
|
if (!res)
|
|
spslr_env_panic("malloc failed");
|
|
|
|
return res;
|
|
}
|
|
|
|
void spslr_env_free(void* ptr) {
|
|
free(ptr);
|
|
}
|
|
|
|
void spslr_env_poke_data(void* dst, const void* src, spslr_u32 n) {
|
|
spslr_env_poke_safe(dst, src, n);
|
|
}
|
|
|
|
void spslr_env_memset(void* dst, int v, spslr_u32 n) {
|
|
memset(dst, v, n);
|
|
}
|
|
|
|
void spslr_env_memcpy(void* dst, const void* src, spslr_u32 n) {
|
|
memcpy(dst, src, n);
|
|
}
|
|
|
|
static int rand_initialized = 0;
|
|
|
|
spslr_u32 spslr_env_random_u32() {
|
|
if (!rand_initialized) {
|
|
srand(time(SPSLR_NULL));
|
|
rand_initialized = 1;
|
|
}
|
|
|
|
return (spslr_u32)rand();
|
|
}
|
|
|