| @@ -383,6 +383,7 @@ static int decode_instructions(struct objtool_file *file) · 382 unmodified lines |
| 383 | memset(insn, 0, sizeof(*insn)); | 383 | memset(insn, 0, sizeof(*insn)); |
| 384 | INIT_LIST_HEAD(&insn->alts); | 384 | INIT_LIST_HEAD(&insn->alts); |
| 385 | INIT_LIST_HEAD(&insn->stack_ops); | 385 | INIT_LIST_HEAD(&insn->stack_ops); |
| | 386 | INIT_LIST_HEAD(&insn->call_node); |
| 386 | | 387 | |
| 387 | insn->sec = sec; | 388 | insn->sec = sec; |
| 388 | insn->offset = offset; | 389 | insn->offset = offset; |
| @@ -420,8 +421,9 @@ static int decode_instructions(struct objtool_file *file) · 31 unmodified lines |
| 420 | | 421 | |
| 421 | sym_for_each_insn(file, func, insn) { | 422 | sym_for_each_insn(file, func, insn) { |
| 422 | insn->func = func; | 423 | insn->func = func; |
| 423 | if (insn->type == INSN_ENDBR) { | 424 | if (insn->type == INSN_ENDBR && list_empty(&insn->call_node)) { |
| 424 | if (insn->offset == insn->func->offset) { | 425 | if (insn->offset == insn->func->offset) { |
| | 426 | list_add_tail(&insn->call_node, &file->endbr_list); |
| 425 | file->nr_endbr++; | 427 | file->nr_endbr++; |
| 426 | } else { | 428 | } else { |
| 427 | file->nr_endbr_int++; | 429 | file->nr_endbr_int++; |
| @@ -742,6 +744,58 @@ static int create_retpoline_sites_sections(struct objtool_file *file) · 314 unmodified lines |
| 742 | return 0; | 744 | return 0; |
| 743 | } | 745 | } |
| 744 | | 746 | |
| | 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 | |
| 745 | static int create_mcount_loc_sections(struct objtool_file *file) | 799 | static int create_mcount_loc_sections(struct objtool_file *file) |
| 746 | { | 800 | { |
| 747 | struct section *sec; | 801 | struct section *sec; |
| @@ -3120,8 +3174,12 @@ validate_ibt_reloc(struct objtool_file *file, struct reloc *reloc) · 2372 unmodified lines |
| 3120 | if (!dest) | 3174 | if (!dest) |
| 3121 | return NULL; | 3175 | return NULL; |
| 3122 | | 3176 | |
| 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 | |
| 3124 | return NULL; | 3181 | return NULL; |
| | 3182 | } |
| 3125 | | 3183 | |
| 3126 | if (reloc->sym->static_call_tramp) | 3184 | if (reloc->sym->static_call_tramp) |
| 3127 | return NULL; | 3185 | return NULL; |
| @@ -3860,6 +3918,13 @@ int check(struct objtool_file *file) · 732 unmodified lines |
| 3860 | warnings += ret; | 3918 | warnings += ret; |
| 3861 | } | 3919 | } |
| 3862 | | 3920 | |
| | 3921 | if (ibt) { |
| | 3922 | ret = create_ibt_endbr_seal_sections(file); |
| | 3923 | if (ret < 0) |
| | 3924 | goto out; |
| | 3925 | warnings += ret; |
| | 3926 | } |
| | 3927 | |
| 3863 | if (stats) { | 3928 | if (stats) { |
| 3864 | printf("nr_insns_visited: %ld\n", nr_insns_visited); | 3929 | printf("nr_insns_visited: %ld\n", nr_insns_visited); |
| 3865 | printf("nr_cfi: %ld\n", nr_cfi); | 3930 | printf("nr_cfi: %ld\n", nr_cfi); |