1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Read the intermediate KLP reloc/symbol representations created by klp diff 4 * and convert them to the proper format required by livepatch. This needs to 5 * run last to avoid linker wreckage. Linkers don't tend to handle the "two 6 * rela sections for a single base section" case very well, nor do they like 7 * SHN_LIVEPATCH. 8 * 9 * This is the final tool in the livepatch module generation pipeline: 10 * 11 * kernel builds -> objtool klp diff -> module link -> objtool klp post-link 12 */ 13 14 #include <fcntl.h> 15 #include <gelf.h> 16 #include <objtool/objtool.h> 17 #include <objtool/warn.h> 18 #include <objtool/klp.h> 19 #include <objtool/util.h> 20 #include <linux/livepatch_external.h> 21 22 static int fix_klp_reloc_sec(struct elf *elf, struct section *symtab, 23 struct section *klp_relocs) 24 { 25 /* section format: __klp_relocs.sec_objname */ 26 const char *sec_objname = klp_relocs->name + strlen(KLP_RELOCS_SEC "."); 27 28 for (int i = 0; i < sec_size(klp_relocs) / sizeof(struct klp_reloc); i++) { 29 struct klp_reloc *klp_reloc; 30 unsigned long klp_reloc_off; 31 struct section *sec, *tmp, *klp_rsec; 32 unsigned long offset; 33 struct reloc *reloc; 34 char rsec_name[SEC_NAME_LEN]; 35 u64 addend; 36 struct symbol *sym, *klp_sym; 37 38 klp_reloc_off = i * sizeof(*klp_reloc); 39 klp_reloc = klp_relocs->data->d_buf + klp_reloc_off; 40 41 /* 42 * Read __klp_relocs[i]: 43 */ 44 45 /* klp_reloc.sec_offset */ 46 reloc = find_reloc_by_dest(elf, klp_relocs, 47 klp_reloc_off + offsetof(struct klp_reloc, offset)); 48 if (!reloc) { 49 ERROR("malformed %s section", klp_relocs->name); 50 return -1; 51 } 52 53 sec = reloc->sym->sec; 54 offset = reloc_addend(reloc); 55 56 /* klp_reloc.sym */ 57 reloc = find_reloc_by_dest(elf, klp_relocs, 58 klp_reloc_off + offsetof(struct klp_reloc, sym)); 59 if (!reloc) { 60 ERROR("malformed %s section", klp_relocs->name); 61 return -1; 62 } 63 64 klp_sym = reloc->sym; 65 addend = reloc_addend(reloc); 66 67 /* 68 * Create the KLP rela: 69 */ 70 71 /* section format: .klp.rela.sec_objname.section_name */ 72 if (snprintf_check(rsec_name, SEC_NAME_LEN, 73 KLP_RELOC_SEC_PREFIX "%s.%s", 74 sec_objname, sec->name)) 75 return -1; 76 77 klp_rsec = find_section_by_name(elf, rsec_name); 78 if (!klp_rsec) { 79 klp_rsec = elf_create_section(elf, rsec_name, 0, 80 elf_rela_size(elf), 81 SHT_RELA, elf_addr_size(elf), 82 SHF_ALLOC | SHF_INFO_LINK | SHF_RELA_LIVEPATCH); 83 if (!klp_rsec) 84 return -1; 85 86 klp_rsec->sh.sh_link = symtab->idx; 87 klp_rsec->sh.sh_info = sec->idx; 88 klp_rsec->base = sec; 89 } 90 91 tmp = sec->rsec; 92 sec->rsec = klp_rsec; 93 if (!elf_create_reloc(elf, sec, offset, klp_sym, addend, klp_reloc->type)) 94 return -1; 95 sec->rsec = tmp; 96 97 /* 98 * Fix up the corresponding KLP symbol: 99 */ 100 101 klp_sym->sym.st_shndx = SHN_LIVEPATCH; 102 if (!gelf_update_sym(symtab->data, klp_sym->idx, &klp_sym->sym)) { 103 ERROR_ELF("gelf_update_sym"); 104 return -1; 105 } 106 107 /* 108 * Disable the original non-KLP reloc by converting it to R_*_NONE: 109 */ 110 111 reloc = find_reloc_by_dest(elf, sec, offset); 112 sym = reloc->sym; 113 sym->sym.st_shndx = SHN_LIVEPATCH; 114 set_reloc_type(elf, reloc, 0); 115 if (!gelf_update_sym(symtab->data, sym->idx, &sym->sym)) { 116 ERROR_ELF("gelf_update_sym"); 117 return -1; 118 } 119 } 120 121 return 0; 122 } 123 124 static int fix_klp_relocs(struct elf *elf) 125 { 126 struct section *symtab, *sec; 127 128 symtab = find_section_by_name(elf, ".symtab"); 129 if (!symtab) { 130 ERROR("missing .symtab"); 131 return -1; 132 } 133 134 for_each_sec(elf, sec) { 135 if (strncmp(sec->name, KLP_RELOCS_SEC ".", 136 strlen(KLP_RELOCS_SEC "."))) 137 continue; 138 139 if (fix_klp_reloc_sec(elf, symtab, sec)) 140 return -1; 141 } 142 143 return 0; 144 } 145 146 /* 147 * This runs on the livepatch module after all other linking has been done. It 148 * converts the intermediate __klp_relocs.* sections into proper KLP relocs to 149 * be processed by livepatch. This needs to run last to avoid linker wreckage. 150 * Linkers don't tend to handle the "two rela sections for a single base 151 * section" case very well, nor do they appreciate SHN_LIVEPATCH. 152 */ 153 int cmd_klp_post_link(int argc, const char **argv) 154 { 155 struct elf *elf; 156 157 argc--; 158 argv++; 159 160 if (argc != 1) { 161 fprintf(stderr, "%d\n", argc); 162 fprintf(stderr, "usage: objtool link <file.ko>\n"); 163 return -1; 164 } 165 166 elf = elf_open_read(argv[0], O_RDWR); 167 if (!elf) 168 return -1; 169 170 if (fix_klp_relocs(elf)) 171 return -1; 172 173 if (elf_write(elf)) 174 return -1; 175 176 return elf_close(elf); 177 } 178