aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcomex2015-02-22 22:43:43 -0500
committercomex2015-02-23 00:54:13 -0500
commitd555fb6089da308956e49db7f60dfbb4d182c3df (patch)
treefad1fa0d64e7fb591d0a2030633c2a3ed76e41c7
parentremove old comment (diff)
downloadsubstitute-d555fb6089da308956e49db7f60dfbb4d182c3df.tar.gz
Fix vm_remap, of trouble with which the previous diagnosis was completely incorrect.
It's actually the fact that no vm_map_server actually exists on the kernel side - even though the otherwise useless function vm_remap exists in the kernel source, and mig generates server code for it, apparently that server code isn't built or linked into the kobject table. Bizarre. Anyway, switch to mach_vm_remap, which is what vm_remap in userspace calls into.
-rw-r--r--Makefile4
-rw-r--r--lib/darwin/execmem.c22
-rwxr-xr-xscript/gen-manual-mach.sh2
-rw-r--r--test/test-hook-functions.c11
4 files changed, 26 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 8a29164..c94e4e7 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ $(eval $(call do_prefix,thumb,-n _thumb,ARM))
$(eval $(call do_prefix,arm,-n _arm,ARM))
$(eval $(call do_prefix,arm64,,AArch64))
-HEADERS := lib/*.h lib/*/*.h
+HEADERS := lib/*.h lib/*/*.h generated/manual-mach.inc.h
out/%.o: lib/%.c Makefile $(HEADERS)
@mkdir -p $(dir $@)
@@ -141,7 +141,7 @@ $(eval $(call define_test,interpose,interpose,$(CC) -std=c11 -lsubstitute))
$(eval $(call define_test,inject,inject,$(CC) -std=c11 -lsubstitute out/darwin/inject.o out/darwin/read.o))
$(eval $(call define_test,pc-patch,pc-patch,$(CC) -std=c11 out/darwin/execmem.o))
$(eval $(call define_test,execmem,execmem,$(CC) -std=c11 out/darwin/execmem.o -segprot __TEST rwx rx))
-$(eval $(call define_test,hook-functions,hook-functions,$(CC) -std=c11 -lsubstitute))
+$(eval $(call define_test,hook-functions,hook-functions,$(CC) -std=c11 -lsubstitute -segprot __TEST rwx rx))
$(eval $(call define_test,posixspawn-hook,posixspawn-hook,$(CC) -std=c11))
$(eval $(call define_test,htab,htab,$(CC) -std=c11))
diff --git a/lib/darwin/execmem.c b/lib/darwin/execmem.c
index 7d8e802..666fa8a 100644
--- a/lib/darwin/execmem.c
+++ b/lib/darwin/execmem.c
@@ -45,6 +45,8 @@ static void manual_memcpy(void *restrict dest, const void *src, size_t len) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
+#define __MachMsgErrorWithTimeout(_R_)
+#define __MachMsgErrorWithoutTimeout(_R_)
#include "../generated/manual-mach.inc.h"
#pragma GCC diagnostic pop
@@ -298,8 +300,8 @@ static int compare_dsts(const void *a, const void *b) {
return dst_a < dst_b ? -1 : dst_a > dst_b ? 1 : 0;
}
-static kern_return_t get_page_prot(uintptr_t ptr, vm_prot_t *prot,
- vm_inherit_t *inherit) {
+static kern_return_t get_page_info(uintptr_t ptr, vm_prot_t *prot_p,
+ vm_inherit_t *inherit_p) {
vm_address_t region = (vm_address_t) ptr;
vm_size_t region_len = 0;
@@ -310,8 +312,8 @@ static kern_return_t get_page_prot(uintptr_t ptr, vm_prot_t *prot,
&max_depth,
(vm_region_recurse_info_t) &info,
&info_count);
- *prot = info.protection & (PROT_READ | PROT_WRITE | PROT_EXEC);
- *inherit = info.inheritance;
+ *prot_p = info.protection & (PROT_READ | PROT_WRITE | PROT_EXEC);
+ *inherit_p = info.inheritance;
return kr;
}
@@ -369,7 +371,7 @@ int execmem_foreign_write_with_pc_patch(struct execmem_foreign_write *writes,
/* Assume that a single patch region will be pages of all the same
* protection, since the alternative is probably someone doing
* something wrong. */
- kern_return_t kr = get_page_prot(page_start, &prot, &inherit);
+ kern_return_t kr = get_page_info(page_start, &prot, &inherit);
if (kr) {
/* Weird; this probably means the region doesn't exist, but we should
* have already read from the memory in order to generate the patch. */
@@ -427,16 +429,16 @@ int execmem_foreign_write_with_pc_patch(struct execmem_foreign_write *writes,
}
/* Protect new like the original, and move it into place. */
- vm_address_t target = page_start;
if (manual_mprotect(new, len, prot)) {
ret = SUBSTITUTE_ERR_VM;
goto fail_unmap;
}
vm_prot_t c, m;
- printf("new=%p\n", new);
- kr = manual_vm_remap(task_self, &target, len, 0, VM_FLAGS_OVERWRITE,
- task_self, (vm_address_t) new, /*copy*/ FALSE,
- &c, &m, inherit, reply_port);
+ mach_vm_address_t target = page_start;
+ kr = manual_mach_vm_remap(mach_task_self(), &target, len, 0,
+ VM_FLAGS_OVERWRITE, task_self,
+ (mach_vm_address_t) new, /*copy*/ TRUE,
+ &c, &m, inherit, reply_port);
if (kr) {
ret = SUBSTITUTE_ERR_VM;
goto fail_unmap;
diff --git a/script/gen-manual-mach.sh b/script/gen-manual-mach.sh
index 02f7eda..b740af9 100755
--- a/script/gen-manual-mach.sh
+++ b/script/gen-manual-mach.sh
@@ -1,6 +1,6 @@
#!/bin/bash
out=generated/manual-mach.inc.h
-(mig -user /dev/stdout -server /dev/null -header /dev/null /usr/include/mach/{thread_act,vm_map}.defs |
+(mig -user /dev/stdout -server /dev/null -header /dev/null /usr/include/mach/{thread_act,mach_vm}.defs |
unifdef -U__MigTypeCheck |
grep -v '#define USING_VOUCHERS' |
sed -E 's/(mach_msg|memcpy)\(/manual_\1(/g;
diff --git a/test/test-hook-functions.c b/test/test-hook-functions.c
index ab027de..7978658 100644
--- a/test/test-hook-functions.c
+++ b/test/test-hook-functions.c
@@ -31,7 +31,17 @@ void break_after() {
__asm__ volatile("");
}
+__attribute__((section("__TEST,__foo"), noinline))
+static int my_own_function(int x) {
+ return x + 4;
+}
+
+static int hook_my_own_function(int x) {
+ return x + 5;
+}
+
static const struct substitute_function_hook hooks[] = {
+ {my_own_function, hook_my_own_function, NULL},
{getpid, hook_getpid, &old_getpid},
{hcreate, hook_hcreate, NULL},
{fwrite, hook_fwrite, &old_fwrite},
@@ -55,6 +65,7 @@ int main() {
printf("errno = %d\n", e);
printf("getpid() => %d\n", getpid());
printf("hcreate() => %d\n", hcreate(42));
+ printf("my_own_function() => %d\n", my_own_function(0));
#else
(void) hooks;
printf("can't test this here\n");