Skip to content

Commit

Permalink
Check the page size of the system at runtime.
Browse files Browse the repository at this point in the history
This commit fixes the EINVAL(Invalid argument) error when mprotect() is called with
an address which isn't at a page boundary.
closes #51
  • Loading branch information
kubo committed Dec 16, 2023
1 parent 7cb8819 commit d5faee5
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 17 deletions.
3 changes: 3 additions & 0 deletions src/arch_arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include "funchook_internal.h"
#include "disasm.h"

#undef PAGE_SIZE
#define PAGE_SIZE 4096

// imm26 at bit 25~0
#define IMM26_MASK 0x03FFFFFF
#define IMM26_OFFSET(ins) ((int64_t)(int32_t)((ins) << 6) >> 4)
Expand Down
17 changes: 4 additions & 13 deletions src/funchook_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,6 @@

#define TRAMPOLINE_BYTE_SIZE (TRAMPOLINE_SIZE * sizeof(insn_t))

/* This must be same with sysconf(_SC_PAGE_SIZE) on Unix
* or the dwPageSize member of the SYSTEM_INFO structure on Windows.
*/
#undef PAGE_SIZE
#define PAGE_SIZE 0x1000 /* 4k */

/* This must be same with the dwAllocationGranularity
* member of the SYSTEM_INFO structure on Windows.
*/
#define ALLOCATION_UNIT 0x10000 /* 64k */

struct funchook_arg_handle {
const size_t *base_pointer;
uint32_t flags;
Expand Down Expand Up @@ -158,8 +147,10 @@ void funchook_set_error_message(funchook_t *funchook, const char *fmt, ...) ATTR
void *funchook_hook_caller(size_t transit_addr, const size_t *base_pointer);

/* Functions in os_unix.c & os_windows.c */
extern const size_t page_size;
extern const size_t allocation_unit; /* windows only */
#define page_size funchook_page_size
#define allocation_unit funchook_allocation_unit
extern size_t page_size;
extern size_t allocation_unit; /* Windows only */

funchook_t *funchook_alloc(void);
int funchook_free(funchook_t *funchook);
Expand Down
5 changes: 4 additions & 1 deletion src/os_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#define MAP_ANONYMOUS MAP_ANON
#endif

const size_t page_size = PAGE_SIZE;
size_t page_size;

const char *funchook_strerror(int errnum, char *buf, size_t buflen)
{
Expand All @@ -69,6 +69,9 @@ const char *funchook_strerror(int errnum, char *buf, size_t buflen)

funchook_t *funchook_alloc(void)
{
if (page_size == 0) {
page_size = sysconf(_SC_PAGE_SIZE);
}
size_t size = ROUND_UP(funchook_size, page_size);
void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mem == (void*)-1) {
Expand Down
12 changes: 9 additions & 3 deletions src/os_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@ typedef struct page_info {
char used[1];
} page_list_t;

const size_t page_size = PAGE_SIZE; /* 4K */
const size_t allocation_unit = ALLOCATION_UNIT; /* 64K */
size_t page_size;
size_t allocation_unit;

static size_t max_num_pages = ALLOCATION_UNIT / PAGE_SIZE - 1; /* 15 */
static page_list_t page_list = {
&page_list,
&page_list,
Expand All @@ -71,6 +70,12 @@ static const char *to_errmsg(DWORD err, char *buf, size_t bufsiz)

funchook_t *funchook_alloc(void)
{
if (page_size == 0) {
SYSTEM_INFO si;
GetSystemInfo(&si);
page_size = si.dwPageSize;
allocation_unit = si.dwAllocationGranularity;
}
size_t size = ROUND_UP(funchook_size, page_size);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
}
Expand Down Expand Up @@ -159,6 +164,7 @@ int funchook_page_alloc(funchook_t *funchook, funchook_page_t **page_out, uint8_
{
page_list_t *pl;
funchook_page_t *page = NULL;
size_t max_num_pages = allocation_unit / page_size - 1;
size_t i;

for (pl = page_list.next; pl != &page_list; pl = pl->next) {
Expand Down

0 comments on commit d5faee5

Please sign in to comment.