@@ -171,6 +171,7 @@ _gum_interceptor_backend_create_trampoline (GumInterceptorBackend * self,
171
171
GumX86Relocator * rl = & self -> relocator ;
172
172
GumX86FunctionContextData * data = GUM_FCDATA (ctx );
173
173
GumAddress function_ctx_ptr ;
174
+ gpointer after_push_to_shadow_stack ;
174
175
guint reloc_bytes ;
175
176
176
177
if (!gum_interceptor_backend_prepare_trampoline (self , ctx ))
@@ -184,11 +185,24 @@ _gum_interceptor_backend_create_trampoline (GumInterceptorBackend * self,
184
185
gum_x86_writer_put_bytes (cw , (guint8 * ) & ctx ,
185
186
sizeof (GumFunctionContext * ));
186
187
187
- ctx -> on_enter_trampoline = gum_x86_writer_cur (cw );
188
+ after_push_to_shadow_stack = gum_x86_writer_cur (cw );
188
189
190
+ gum_x86_writer_put_lea_reg_reg_offset (cw , GUM_X86_XSP ,
191
+ GUM_X86_XSP , ((gssize ) sizeof (gpointer )));
189
192
gum_x86_writer_put_push_near_ptr (cw , function_ctx_ptr );
190
193
gum_x86_writer_put_jmp_address (cw , GUM_ADDRESS (self -> enter_thunk -> data ));
191
194
195
+ ctx -> on_enter_trampoline = gum_x86_writer_cur (cw );
196
+
197
+ // We use a call instruction to push on_leave_trampoline as a legit return
198
+ // address on the shadow stack.
199
+ //
200
+ // SAFETY: We call to a label that is only a few bytes away, so this will
201
+ // only emit a call instruction (not a call-jump combo). So the
202
+ // current position of the writer after emission is the exact return
203
+ // address that will be pushed on the stack and the shadow stack.
204
+ gum_x86_writer_put_call_address (cw , GUM_ADDRESS (after_push_to_shadow_stack ));
205
+
192
206
ctx -> on_leave_trampoline = gum_x86_writer_cur (cw );
193
207
194
208
gum_x86_writer_put_push_near_ptr (cw , function_ctx_ptr );
@@ -338,7 +352,7 @@ gum_emit_enter_thunk (GumX86Writer * cw)
338
352
GUM_ARG_REGISTER , GUM_X86_XDX ,
339
353
GUM_ARG_REGISTER , GUM_X86_XCX );
340
354
341
- gum_emit_epilog (cw );
355
+ gum_emit_epilog (cw , FALSE );
342
356
}
343
357
344
358
static void
@@ -359,7 +373,7 @@ gum_emit_leave_thunk (GumX86Writer * cw)
359
373
GUM_ARG_REGISTER , GUM_X86_XSI ,
360
374
GUM_ARG_REGISTER , GUM_X86_XDX );
361
375
362
- gum_emit_epilog (cw );
376
+ gum_emit_epilog (cw , TRUE );
363
377
}
364
378
365
379
static void
@@ -401,7 +415,7 @@ gum_emit_prolog (GumX86Writer * cw,
401
415
}
402
416
403
417
static void
404
- gum_emit_epilog (GumX86Writer * cw )
418
+ gum_emit_epilog (GumX86Writer * cw , gboolean do_ret )
405
419
{
406
420
guint8 fxrstor [] = {
407
421
0x0f , 0xae , 0x0c , 0x24 /* fxrstor [esp] */
@@ -415,5 +429,15 @@ gum_emit_epilog (GumX86Writer * cw)
415
429
GumCpuContext.xip */
416
430
gum_x86_writer_put_popax (cw );
417
431
gum_x86_writer_put_popfx (cw );
418
- gum_x86_writer_put_ret (cw );
432
+
433
+ if (do_ret ) {
434
+ gum_x86_writer_put_ret (cw );
435
+ }
436
+ else {
437
+ // emulates a ret, but does not affect the shadow stack
438
+ gum_x86_writer_put_lea_reg_reg_offset (cw , GUM_X86_XSP ,
439
+ GUM_X86_XSP , ((gssize ) sizeof (gpointer )));
440
+ gum_x86_writer_put_jmp_reg_offset_ptr (cw , GUM_X86_XSP ,
441
+ - ((gssize ) sizeof (gpointer )));
442
+ }
419
443
}
0 commit comments