selfpatch-slr/selfpatch/src/env.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();
}