@@ -115,6 +115,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
115115}
116116
117117extern s32 __retpoline_sites [], __retpoline_sites_end [];
118+ extern s32 __return_sites [], __return_sites_end [];
118119extern s32 __ibt_endbr_seal [], __ibt_endbr_seal_end [];
119120extern struct alt_instr __alt_instructions [], __alt_instructions_end [];
120121extern s32 __smp_locks [], __smp_locks_end [];
@@ -507,9 +508,67 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
507508 }
508509}
509510
511+ /*
512+ * Rewrite the compiler generated return thunk tail-calls.
513+ *
514+ * For example, convert:
515+ *
516+ * JMP __x86_return_thunk
517+ *
518+ * into:
519+ *
520+ * RET
521+ */
522+ static int patch_return (void * addr , struct insn * insn , u8 * bytes )
523+ {
524+ int i = 0 ;
525+
526+ if (cpu_feature_enabled (X86_FEATURE_RETHUNK ))
527+ return -1 ;
528+
529+ bytes [i ++ ] = RET_INSN_OPCODE ;
530+
531+ for (; i < insn -> length ;)
532+ bytes [i ++ ] = INT3_INSN_OPCODE ;
533+
534+ return i ;
535+ }
536+
537+ void __init_or_module noinline apply_returns (s32 * start , s32 * end )
538+ {
539+ s32 * s ;
540+
541+ for (s = start ; s < end ; s ++ ) {
542+ void * addr = (void * )s + * s ;
543+ struct insn insn ;
544+ int len , ret ;
545+ u8 bytes [16 ];
546+ u8 op1 ;
547+
548+ ret = insn_decode_kernel (& insn , addr );
549+ if (WARN_ON_ONCE (ret < 0 ))
550+ continue ;
551+
552+ op1 = insn .opcode .bytes [0 ];
553+ if (WARN_ON_ONCE (op1 != JMP32_INSN_OPCODE ))
554+ continue ;
555+
556+ DPRINTK ("return thunk at: %pS (%px) len: %d to: %pS" ,
557+ addr , addr , insn .length ,
558+ addr + insn .length + insn .immediate .value );
559+
560+ len = patch_return (addr , & insn , bytes );
561+ if (len == insn .length ) {
562+ DUMP_BYTES (((u8 * )addr ), len , "%px: orig: " , addr );
563+ DUMP_BYTES (((u8 * )bytes ), len , "%px: repl: " , addr );
564+ text_poke_early (addr , bytes , len );
565+ }
566+ }
567+ }
510568#else /* !CONFIG_RETPOLINE || !CONFIG_OBJTOOL */
511569
512570void __init_or_module noinline apply_retpolines (s32 * start , s32 * end ) { }
571+ void __init_or_module noinline apply_returns (s32 * start , s32 * end ) { }
513572
514573#endif /* CONFIG_RETPOLINE && CONFIG_OBJTOOL */
515574
@@ -860,6 +919,7 @@ void __init alternative_instructions(void)
860919 * those can rewrite the retpoline thunks.
861920 */
862921 apply_retpolines (__retpoline_sites , __retpoline_sites_end );
922+ apply_returns (__return_sites , __return_sites_end );
863923
864924 /*
865925 * Then patch alternatives, such that those paravirt calls that are in
0 commit comments