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