#include "env.h" #include #include #include #include #include #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(); }