@@ -4392,6 +4392,51 @@ static bool noendbr_range(struct objtool_file *file, struct instruction *insn)
43924392 return insn -> offset == sym -> offset + sym -> len ;
43934393}
43944394
4395+ static int __validate_ibt_insn (struct objtool_file * file , struct instruction * insn ,
4396+ struct instruction * dest )
4397+ {
4398+ if (dest -> type == INSN_ENDBR ) {
4399+ mark_endbr_used (dest );
4400+ return 0 ;
4401+ }
4402+
4403+ if (insn_func (dest ) && insn_func (insn ) &&
4404+ insn_func (dest )-> pfunc == insn_func (insn )-> pfunc ) {
4405+ /*
4406+ * Anything from->to self is either _THIS_IP_ or
4407+ * IRET-to-self.
4408+ *
4409+ * There is no sane way to annotate _THIS_IP_ since the
4410+ * compiler treats the relocation as a constant and is
4411+ * happy to fold in offsets, skewing any annotation we
4412+ * do, leading to vast amounts of false-positives.
4413+ *
4414+ * There's also compiler generated _THIS_IP_ through
4415+ * KCOV and such which we have no hope of annotating.
4416+ *
4417+ * As such, blanket accept self-references without
4418+ * issue.
4419+ */
4420+ return 0 ;
4421+ }
4422+
4423+ /*
4424+ * Accept anything ANNOTATE_NOENDBR.
4425+ */
4426+ if (dest -> noendbr )
4427+ return 0 ;
4428+
4429+ /*
4430+ * Accept if this is the instruction after a symbol
4431+ * that is (no)endbr -- typical code-range usage.
4432+ */
4433+ if (noendbr_range (file , dest ))
4434+ return 0 ;
4435+
4436+ WARN_INSN (insn , "relocation to !ENDBR: %s" , offstr (dest -> sec , dest -> offset ));
4437+ return 1 ;
4438+ }
4439+
43954440static int validate_ibt_insn (struct objtool_file * file , struct instruction * insn )
43964441{
43974442 struct instruction * dest ;
@@ -4404,6 +4449,7 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
44044449 * direct/indirect branches:
44054450 */
44064451 switch (insn -> type ) {
4452+
44074453 case INSN_CALL :
44084454 case INSN_CALL_DYNAMIC :
44094455 case INSN_JUMP_CONDITIONAL :
@@ -4413,6 +4459,23 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
44134459 case INSN_RETURN :
44144460 case INSN_NOP :
44154461 return 0 ;
4462+
4463+ case INSN_LEA_RIP :
4464+ if (!insn_reloc (file , insn )) {
4465+ /* local function pointer reference without reloc */
4466+
4467+ off = arch_jump_destination (insn );
4468+
4469+ dest = find_insn (file , insn -> sec , off );
4470+ if (!dest ) {
4471+ WARN_INSN (insn , "corrupt function pointer reference" );
4472+ return 1 ;
4473+ }
4474+
4475+ return __validate_ibt_insn (file , insn , dest );
4476+ }
4477+ break ;
4478+
44164479 default :
44174480 break ;
44184481 }
@@ -4423,13 +4486,6 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
44234486 reloc_offset (reloc ) + 1 ,
44244487 (insn -> offset + insn -> len ) - (reloc_offset (reloc ) + 1 ))) {
44254488
4426- /*
4427- * static_call_update() references the trampoline, which
4428- * doesn't have (or need) ENDBR. Skip warning in that case.
4429- */
4430- if (reloc -> sym -> static_call_tramp )
4431- continue ;
4432-
44334489 off = reloc -> sym -> offset ;
44344490 if (reloc_type (reloc ) == R_X86_64_PC32 ||
44354491 reloc_type (reloc ) == R_X86_64_PLT32 )
@@ -4441,47 +4497,7 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
44414497 if (!dest )
44424498 continue ;
44434499
4444- if (dest -> type == INSN_ENDBR ) {
4445- mark_endbr_used (dest );
4446- continue ;
4447- }
4448-
4449- if (insn_func (dest ) && insn_func (insn ) &&
4450- insn_func (dest )-> pfunc == insn_func (insn )-> pfunc ) {
4451- /*
4452- * Anything from->to self is either _THIS_IP_ or
4453- * IRET-to-self.
4454- *
4455- * There is no sane way to annotate _THIS_IP_ since the
4456- * compiler treats the relocation as a constant and is
4457- * happy to fold in offsets, skewing any annotation we
4458- * do, leading to vast amounts of false-positives.
4459- *
4460- * There's also compiler generated _THIS_IP_ through
4461- * KCOV and such which we have no hope of annotating.
4462- *
4463- * As such, blanket accept self-references without
4464- * issue.
4465- */
4466- continue ;
4467- }
4468-
4469- /*
4470- * Accept anything ANNOTATE_NOENDBR.
4471- */
4472- if (dest -> noendbr )
4473- continue ;
4474-
4475- /*
4476- * Accept if this is the instruction after a symbol
4477- * that is (no)endbr -- typical code-range usage.
4478- */
4479- if (noendbr_range (file , dest ))
4480- continue ;
4481-
4482- WARN_INSN (insn , "relocation to !ENDBR: %s" , offstr (dest -> sec , dest -> offset ));
4483-
4484- warnings ++ ;
4500+ warnings += __validate_ibt_insn (file , insn , dest );
44854501 }
44864502
44874503 return warnings ;
@@ -4557,6 +4573,7 @@ static int validate_ibt(struct objtool_file *file)
45574573 !strcmp (sec -> name , "__jump_table" ) ||
45584574 !strcmp (sec -> name , "__mcount_loc" ) ||
45594575 !strcmp (sec -> name , ".kcfi_traps" ) ||
4576+ !strcmp (sec -> name , "__tracepoints" ) ||
45604577 strstr (sec -> name , "__patchable_function_entries" ))
45614578 continue ;
45624579
0 commit comments