diff --git a/src/linux/frida-helper-backend.vala b/src/linux/frida-helper-backend.vala index ed84fc4d6..e3ed21c92 100644 --- a/src/linux/frida-helper-backend.vala +++ b/src/linux/frida-helper-backend.vala @@ -1017,8 +1017,10 @@ namespace Frida { establish_connection (launch, spec, bres, agent_ctrl, fallback_address, cancellable); uint64 loader_base = (uintptr) bres.context.allocation_base; - - var call_builder = new RemoteCallBuilder (loader_base, saved_regs); + // Set the stack pointer to the allocated stack root. + GPRegs regs = saved_regs; + regs.stack_pointer = bres.allocated_stack.stack_root; + var call_builder = new RemoteCallBuilder (loader_base, regs); call_builder.add_argument (loader_base + loader_layout.ctx_offset); RemoteCall loader_call = call_builder.build (this); RemoteCallResult loader_result = yield loader_call.execute (cancellable); @@ -1088,9 +1090,13 @@ namespace Frida { remote_munmap = remote_libc.base_address + munmap_offset; } + uint64 stack_base = 0; + size_t stack_size = 64 << 10; // enough for the bootstrapper if (remote_mmap != 0) { allocation_base = yield allocate_memory (remote_mmap, allocation_size, Posix.PROT_READ | Posix.PROT_WRITE | Posix.PROT_EXEC, cancellable); + stack_base = yield allocate_memory (remote_mmap, stack_size, + Posix.PROT_READ | Posix.PROT_WRITE | Posix.PROT_EXEC, cancellable); } else { var code_swap = yield new ProcessCodeSwapScope (this, bootstrapper_code, cancellable); uint64 code_start = code_swap.code_start; @@ -1104,6 +1110,7 @@ namespace Frida { var bootstrap_ctx = HelperBootstrapContext (); bootstrap_ctx.allocation_size = allocation_size; + bootstrap_ctx.stack_size = stack_size; write_memory (bootstrap_ctx_location, (uint8[]) &bootstrap_ctx); call_builder.add_argument (bootstrap_ctx_location); @@ -1117,10 +1124,13 @@ namespace Frida { Memory.copy (&bootstrap_ctx, output_context, output_context.length); allocation_base = (uintptr) bootstrap_ctx.allocation_base; - + stack_base = (uintptr) bootstrap_ctx.stack_base; code_swap.revert (); } + result.allocated_stack.stack_base = (void *)stack_base; + result.allocated_stack.stack_size = stack_size; + try { write_memory (allocation_base, bootstrapper_code); maybe_fixup_helper_code (allocation_base, bootstrapper_code); @@ -1129,7 +1139,9 @@ namespace Frida { HelperBootstrapStatus status = SUCCESS; do { - var call_builder = new RemoteCallBuilder (code_start, saved_regs); + GPRegs regs = saved_regs; + regs.stack_pointer = result.allocated_stack.stack_root; + var call_builder = new RemoteCallBuilder (code_start, regs); unowned uint8[] fallback_ld_data = fallback_ld.data; unowned uint8[] fallback_libc_data = fallback_libc.data; @@ -1198,6 +1210,10 @@ namespace Frida { yield deallocate_memory (remote_munmap, allocation_base, allocation_size, null); } catch (GLib.Error e) { } + try { + yield deallocate_memory (remote_munmap, stack_base, stack_size, null); + } catch (GLib.Error e) { + } } throw_api_error (e); @@ -1395,6 +1411,8 @@ namespace Frida { public async void deallocate (BootstrapResult bres, Cancellable? cancellable) throws Error, IOError { yield deallocate_memory ((uintptr) bres.libc.munmap, (uintptr) bres.context.allocation_base, bres.context.allocation_size, cancellable); + yield deallocate_memory ((uintptr) bres.libc.munmap, (uintptr) bres.allocated_stack.stack_base, + bres.allocated_stack.stack_size, cancellable); } } @@ -1416,14 +1434,28 @@ namespace Frida { } } + private struct AllocatedStack { + public void * stack_base; + public size_t stack_size; + + public uint64 stack_root { + get { + return (uint64) stack_base + (uint64) stack_size; + } + } + } + + private class BootstrapResult { public HelperBootstrapContext context; public HelperLibcApi libc; + public AllocatedStack allocated_stack; public BootstrapResult clone () { var res = new BootstrapResult (); res.context = context; res.libc = libc; + res.allocated_stack = allocated_stack; return res; } } @@ -1717,6 +1749,9 @@ namespace Frida { bool enable_ctrlfds; int ctrlfds[2]; HelperLibcApi * libc; + + void * stack_base; + size_t stack_size; } protected struct HelperLoaderContext { diff --git a/src/linux/helpers/bootstrapper-arm64.bin b/src/linux/helpers/bootstrapper-arm64.bin index e276d5a69..87a333fc1 100644 Binary files a/src/linux/helpers/bootstrapper-arm64.bin and b/src/linux/helpers/bootstrapper-arm64.bin differ diff --git a/src/linux/helpers/bootstrapper.c b/src/linux/helpers/bootstrapper.c index 5f579ae1e..39da782f4 100644 --- a/src/linux/helpers/bootstrapper.c +++ b/src/linux/helpers/bootstrapper.c @@ -155,6 +155,12 @@ frida_bootstrap (FridaBootstrapContext * ctx) FridaLibcApi * libc = ctx->libc; FridaProcessLayout process; + if (ctx->stack_base == NULL && ctx->stack_size > 0) + { + ctx->stack_base = mmap (NULL, ctx->stack_size, PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ctx->stack_base == MAP_FAILED) + return FRIDA_BOOTSTRAP_ALLOCATION_ERROR; + } if (ctx->allocation_base == NULL) { ctx->allocation_base = mmap (NULL, ctx->allocation_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); diff --git a/src/linux/helpers/inject-context.h b/src/linux/helpers/inject-context.h index 8fa65c069..87fc9b0a1 100644 --- a/src/linux/helpers/inject-context.h +++ b/src/linux/helpers/inject-context.h @@ -50,6 +50,9 @@ struct _FridaBootstrapContext int enable_ctrlfds; int ctrlfds[2]; FridaLibcApi * libc; + + void * stack_base; + size_t stack_size; }; struct _FridaLoaderContext