@@ -383,6 +383,7 @@ static int decode_instructions(struct objtool_file *file)
383383 memset (insn , 0 , sizeof (* insn ));
384384 INIT_LIST_HEAD (& insn -> alts );
385385 INIT_LIST_HEAD (& insn -> stack_ops );
386+ INIT_LIST_HEAD (& insn -> call_node );
386387
387388 insn -> sec = sec ;
388389 insn -> offset = offset ;
@@ -420,8 +421,9 @@ static int decode_instructions(struct objtool_file *file)
420421
421422 sym_for_each_insn (file , func , insn ) {
422423 insn -> func = func ;
423- if (insn -> type == INSN_ENDBR ) {
424+ if (insn -> type == INSN_ENDBR && list_empty ( & insn -> call_node ) ) {
424425 if (insn -> offset == insn -> func -> offset ) {
426+ list_add_tail (& insn -> call_node , & file -> endbr_list );
425427 file -> nr_endbr ++ ;
426428 } else {
427429 file -> nr_endbr_int ++ ;
@@ -742,6 +744,58 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
742744 return 0 ;
743745}
744746
747+ static int create_ibt_endbr_seal_sections (struct objtool_file * file )
748+ {
749+ struct instruction * insn ;
750+ struct section * sec ;
751+ int idx ;
752+
753+ sec = find_section_by_name (file -> elf , ".ibt_endbr_seal" );
754+ if (sec ) {
755+ WARN ("file already has .ibt_endbr_seal, skipping" );
756+ return 0 ;
757+ }
758+
759+ idx = 0 ;
760+ list_for_each_entry (insn , & file -> endbr_list , call_node )
761+ idx ++ ;
762+
763+ if (stats ) {
764+ printf ("ibt: ENDBR at function start: %d\n" , file -> nr_endbr );
765+ printf ("ibt: ENDBR inside functions: %d\n" , file -> nr_endbr_int );
766+ printf ("ibt: superfluous ENDBR: %d\n" , idx );
767+ }
768+
769+ if (!idx )
770+ return 0 ;
771+
772+ sec = elf_create_section (file -> elf , ".ibt_endbr_seal" , 0 ,
773+ sizeof (int ), idx );
774+ if (!sec ) {
775+ WARN ("elf_create_section: .ibt_endbr_seal" );
776+ return -1 ;
777+ }
778+
779+ idx = 0 ;
780+ list_for_each_entry (insn , & file -> endbr_list , call_node ) {
781+
782+ int * site = (int * )sec -> data -> d_buf + idx ;
783+ * site = 0 ;
784+
785+ if (elf_add_reloc_to_insn (file -> elf , sec ,
786+ idx * sizeof (int ),
787+ R_X86_64_PC32 ,
788+ insn -> sec , insn -> offset )) {
789+ WARN ("elf_add_reloc_to_insn: .ibt_endbr_seal" );
790+ return -1 ;
791+ }
792+
793+ idx ++ ;
794+ }
795+
796+ return 0 ;
797+ }
798+
745799static int create_mcount_loc_sections (struct objtool_file * file )
746800{
747801 struct section * sec ;
@@ -3120,8 +3174,12 @@ validate_ibt_reloc(struct objtool_file *file, struct reloc *reloc)
31203174 if (!dest )
31213175 return NULL ;
31223176
3123- if (dest -> type == INSN_ENDBR )
3177+ if (dest -> type == INSN_ENDBR ) {
3178+ if (!list_empty (& dest -> call_node ))
3179+ list_del_init (& dest -> call_node );
3180+
31243181 return NULL ;
3182+ }
31253183
31263184 if (reloc -> sym -> static_call_tramp )
31273185 return NULL ;
@@ -3860,6 +3918,13 @@ int check(struct objtool_file *file)
38603918 warnings += ret ;
38613919 }
38623920
3921+ if (ibt ) {
3922+ ret = create_ibt_endbr_seal_sections (file );
3923+ if (ret < 0 )
3924+ goto out ;
3925+ warnings += ret ;
3926+ }
3927+
38633928 if (stats ) {
38643929 printf ("nr_insns_visited: %ld\n" , nr_insns_visited );
38653930 printf ("nr_cfi: %ld\n" , nr_cfi );
0 commit comments