Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'objtool_urgent_for_5.8_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool fixes from Borislav Petkov:
"Three fixes from Peter Zijlstra suppressing KCOV instrumentation in
noinstr sections.

Peter Zijlstra says:
"Address KCOV vs noinstr. There is no function attribute to
selectively suppress KCOV instrumentation, instead teach objtool
to NOP out the calls in noinstr functions"

This cures a bunch of KCOV crashes (as used by syzcaller)"

* tag 'objtool_urgent_for_5.8_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
objtool: Fix noinstr vs KCOV
objtool: Provide elf_write_{insn,reloc}()
objtool: Clean up elf_write() condition

+109 -9
+1 -1
arch/x86/Kconfig
··· 67 67 select ARCH_HAS_FILTER_PGPROT 68 68 select ARCH_HAS_FORTIFY_SOURCE 69 69 select ARCH_HAS_GCOV_PROFILE_ALL 70 - select ARCH_HAS_KCOV if X86_64 70 + select ARCH_HAS_KCOV if X86_64 && STACK_VALIDATION 71 71 select ARCH_HAS_MEM_ENCRYPT 72 72 select ARCH_HAS_MEMBARRIER_SYNC_CORE 73 73 select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+2
tools/objtool/arch.h
··· 84 84 85 85 unsigned long arch_dest_rela_offset(int addend); 86 86 87 + const char *arch_nop_insn(int len); 88 + 87 89 #endif /* _ARCH_H */
+18
tools/objtool/arch/x86/decode.c
··· 565 565 state->regs[16].base = CFI_CFA; 566 566 state->regs[16].offset = -8; 567 567 } 568 + 569 + const char *arch_nop_insn(int len) 570 + { 571 + static const char nops[5][5] = { 572 + /* 1 */ { 0x90 }, 573 + /* 2 */ { 0x66, 0x90 }, 574 + /* 3 */ { 0x0f, 0x1f, 0x00 }, 575 + /* 4 */ { 0x0f, 0x1f, 0x40, 0x00 }, 576 + /* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 }, 577 + }; 578 + 579 + if (len < 1 || len > 5) { 580 + WARN("invalid NOP size: %d\n", len); 581 + return NULL; 582 + } 583 + 584 + return nops[len-1]; 585 + }
+6
tools/objtool/arch/x86/include/arch_elf.h
··· 1 + #ifndef _OBJTOOL_ARCH_ELF 2 + #define _OBJTOOL_ARCH_ELF 3 + 4 + #define R_NONE R_X86_64_NONE 5 + 6 + #endif /* _OBJTOOL_ARCH_ELF */
+22 -1
tools/objtool/check.c
··· 12 12 #include "check.h" 13 13 #include "special.h" 14 14 #include "warn.h" 15 + #include "arch_elf.h" 15 16 16 17 #include <linux/hashtable.h> 17 18 #include <linux/kernel.h> ··· 765 764 } 766 765 } else 767 766 insn->call_dest = rela->sym; 767 + 768 + /* 769 + * Many compilers cannot disable KCOV with a function attribute 770 + * so they need a little help, NOP out any KCOV calls from noinstr 771 + * text. 772 + */ 773 + if (insn->sec->noinstr && 774 + !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { 775 + if (rela) { 776 + rela->type = R_NONE; 777 + elf_write_rela(file->elf, rela); 778 + } 779 + 780 + elf_write_insn(file->elf, insn->sec, 781 + insn->offset, insn->len, 782 + arch_nop_insn(insn->len)); 783 + insn->type = INSN_NOP; 784 + } 768 785 769 786 /* 770 787 * Whatever stack impact regular CALLs have, should be undone ··· 2785 2766 2786 2767 objname = _objname; 2787 2768 2788 - file.elf = elf_open_read(objname, orc ? O_RDWR : O_RDONLY); 2769 + file.elf = elf_open_read(objname, O_RDWR); 2789 2770 if (!file.elf) 2790 2771 return 1; 2791 2772 ··· 2846 2827 ret = create_orc_sections(&file); 2847 2828 if (ret < 0) 2848 2829 goto out; 2830 + } 2849 2831 2832 + if (file.elf->changed) { 2850 2833 ret = elf_write(file.elf); 2851 2834 if (ret < 0) 2852 2835 goto out;
+50 -3
tools/objtool/elf.c
··· 529 529 rela->addend = rela->rela.r_addend; 530 530 rela->offset = rela->rela.r_offset; 531 531 symndx = GELF_R_SYM(rela->rela.r_info); 532 - rela->sym = find_symbol_by_index(elf, symndx); 533 532 rela->sec = sec; 533 + rela->idx = i; 534 + rela->sym = find_symbol_by_index(elf, symndx); 534 535 if (!rela->sym) { 535 536 WARN("can't find rela entry symbol %d for %s", 536 537 symndx, sec->name); ··· 714 713 elf_hash_add(elf->section_hash, &sec->hash, sec->idx); 715 714 elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name)); 716 715 716 + elf->changed = true; 717 + 717 718 return sec; 718 719 } 719 720 ··· 749 746 return sec; 750 747 } 751 748 752 - int elf_rebuild_rela_section(struct section *sec) 749 + int elf_rebuild_rela_section(struct elf *elf, struct section *sec) 753 750 { 754 751 struct rela *rela; 755 752 int nr, idx = 0, size; ··· 765 762 perror("malloc"); 766 763 return -1; 767 764 } 765 + 766 + sec->changed = true; 767 + elf->changed = true; 768 768 769 769 sec->data->d_buf = relas; 770 770 sec->data->d_size = size; ··· 785 779 return 0; 786 780 } 787 781 788 - int elf_write(const struct elf *elf) 782 + int elf_write_insn(struct elf *elf, struct section *sec, 783 + unsigned long offset, unsigned int len, 784 + const char *insn) 785 + { 786 + Elf_Data *data = sec->data; 787 + 788 + if (data->d_type != ELF_T_BYTE || data->d_off) { 789 + WARN("write to unexpected data for section: %s", sec->name); 790 + return -1; 791 + } 792 + 793 + memcpy(data->d_buf + offset, insn, len); 794 + elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY); 795 + 796 + elf->changed = true; 797 + 798 + return 0; 799 + } 800 + 801 + int elf_write_rela(struct elf *elf, struct rela *rela) 802 + { 803 + struct section *sec = rela->sec; 804 + 805 + rela->rela.r_info = GELF_R_INFO(rela->sym->idx, rela->type); 806 + rela->rela.r_addend = rela->addend; 807 + rela->rela.r_offset = rela->offset; 808 + 809 + if (!gelf_update_rela(sec->data, rela->idx, &rela->rela)) { 810 + WARN_ELF("gelf_update_rela"); 811 + return -1; 812 + } 813 + 814 + elf->changed = true; 815 + 816 + return 0; 817 + } 818 + 819 + int elf_write(struct elf *elf) 789 820 { 790 821 struct section *sec; 791 822 Elf_Scn *s; ··· 839 796 WARN_ELF("gelf_update_shdr"); 840 797 return -1; 841 798 } 799 + 800 + sec->changed = false; 842 801 } 843 802 } 844 803 ··· 852 807 WARN_ELF("elf_update"); 853 808 return -1; 854 809 } 810 + 811 + elf->changed = false; 855 812 856 813 return 0; 857 814 }
+9 -3
tools/objtool/elf.h
··· 64 64 GElf_Rela rela; 65 65 struct section *sec; 66 66 struct symbol *sym; 67 - unsigned int type; 68 67 unsigned long offset; 68 + unsigned int type; 69 69 int addend; 70 + int idx; 70 71 bool jump_table_start; 71 72 }; 72 73 ··· 77 76 Elf *elf; 78 77 GElf_Ehdr ehdr; 79 78 int fd; 79 + bool changed; 80 80 char *name; 81 81 struct list_head sections; 82 82 DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS); ··· 120 118 struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr); 121 119 struct section *elf_create_rela_section(struct elf *elf, struct section *base); 122 120 void elf_add_rela(struct elf *elf, struct rela *rela); 123 - int elf_write(const struct elf *elf); 121 + int elf_write_insn(struct elf *elf, struct section *sec, 122 + unsigned long offset, unsigned int len, 123 + const char *insn); 124 + int elf_write_rela(struct elf *elf, struct rela *rela); 125 + int elf_write(struct elf *elf); 124 126 void elf_close(struct elf *elf); 125 127 126 128 struct section *find_section_by_name(const struct elf *elf, const char *name); ··· 136 130 struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec, 137 131 unsigned long offset, unsigned int len); 138 132 struct symbol *find_func_containing(struct section *sec, unsigned long offset); 139 - int elf_rebuild_rela_section(struct section *sec); 133 + int elf_rebuild_rela_section(struct elf *elf, struct section *sec); 140 134 141 135 #define for_each_sec(file, sec) \ 142 136 list_for_each_entry(sec, &file->elf->sections, list)
+1 -1
tools/objtool/orc_gen.c
··· 222 222 } 223 223 } 224 224 225 - if (elf_rebuild_rela_section(ip_relasec)) 225 + if (elf_rebuild_rela_section(file->elf, ip_relasec)) 226 226 return -1; 227 227 228 228 return 0;