| @@ -191,12 +191,12 @@ static int klp_find_object_symbol(const char *objname, const char *name, · 190 unmodified lines |
| 191 | return -EINVAL; | 191 | return -EINVAL; |
| 192 | } | 192 | } |
| 193 | | 193 | |
| 194 | static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) | 194 | static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab, |
| | 195 | unsigned int symndx, Elf_Shdr *relasec) |
| 195 | { | 196 | { |
| 196 | int i, cnt, vmlinux, ret; | 197 | int i, cnt, vmlinux, ret; |
| 197 | char objname[MODULE_NAME_LEN]; | 198 | char objname[MODULE_NAME_LEN]; |
| 198 | char symname[KSYM_NAME_LEN]; | 199 | char symname[KSYM_NAME_LEN]; |
| 199 | char *strtab = pmod->core_kallsyms.strtab; | | |
| 200 | Elf_Rela *relas; | 200 | Elf_Rela *relas; |
| 201 | Elf_Sym *sym; | 201 | Elf_Sym *sym; |
| 202 | unsigned long sympos, addr; | 202 | unsigned long sympos, addr; |
| @@ -216,7 +216,7 @@ static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) · 13 unmodified lines |
| 216 | relas = (Elf_Rela *) relasec->sh_addr; | 216 | relas = (Elf_Rela *) relasec->sh_addr; |
| 217 | /* For each rela in this klp relocation section */ | 217 | /* For each rela in this klp relocation section */ |
| 218 | for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) { | 218 | for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) { |
| 219 | sym = pmod->core_kallsyms.symtab + ELF_R_SYM(relas[i].r_info); | 219 | sym = (Elf64_Sym *)sechdrs[symndx].sh_addr + ELF_R_SYM(relas[i].r_info); |
| 220 | if (sym->st_shndx != SHN_LIVEPATCH) { | 220 | if (sym->st_shndx != SHN_LIVEPATCH) { |
| 221 | pr_err("symbol %s is not marked as a livepatch symbol\n", | 221 | pr_err("symbol %s is not marked as a livepatch symbol\n", |
| 222 | strtab + sym->st_name); | 222 | strtab + sym->st_name); |
| @@ -246,54 +246,59 @@ static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) · 23 unmodified lines |
| 246 | return 0; | 246 | return 0; |
| 247 | } | 247 | } |
| 248 | | 248 | |
| 249 | static int klp_write_object_relocations(struct module *pmod, | 249 | /* |
| 250 | struct klp_object *obj) | 250 | * At a high-level, there are two types of klp relocation sections: those which |
| | 251 | * reference symbols which live in vmlinux; and those which reference symbols |
| | 252 | * which live in other modules. This function is called for both types: |
| | 253 | * |
| | 254 | * 1) When a klp module itself loads, the module code calls this function to |
| | 255 | * write vmlinux-specific klp relocations (.klp.rela.vmlinux.* sections). |
| | 256 | * These relocations are written to the klp module text to allow the patched |
| | 257 | * code/data to reference unexported vmlinux symbols. They're written as |
| | 258 | * early as possible to ensure that other module init code (.e.g., |
| | 259 | * jump_label_apply_nops) can access any unexported vmlinux symbols which |
| | 260 | * might be referenced by the klp module's special sections. |
| | 261 | * |
| | 262 | * 2) When a to-be-patched module loads -- or is already loaded when a |
| | 263 | * corresponding klp module loads -- klp code calls this function to write |
| | 264 | * module-specific klp relocations (.klp.rela.{module}.* sections). These |
| | 265 | * are written to the klp module text to allow the patched code/data to |
| | 266 | * reference symbols which live in the to-be-patched module or one of its |
| | 267 | * module dependencies. Exported symbols are supported, in addition to |
| | 268 | * unexported symbols, in order to enable late module patching, which allows |
| | 269 | * the to-be-patched module to be loaded and patched sometime *after* the |
| | 270 | * klp module is loaded. |
| | 271 | */ |
| | 272 | int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, |
| | 273 | const char *shstrtab, const char *strtab, |
| | 274 | unsigned int symndx, unsigned int secndx, |
| | 275 | const char *objname) |
| 251 | { | 276 | { |
| 252 | int i, cnt, ret = 0; | 277 | int cnt, ret; |
| 253 | const char *objname, *secname; | | |
| 254 | char sec_objname[MODULE_NAME_LEN]; | 278 | char sec_objname[MODULE_NAME_LEN]; |
| 255 | Elf_Shdr *sec; | 279 | Elf_Shdr *sec = sechdrs + secndx; |
| 256 | | 280 | |
| 257 | if (WARN_ON(!klp_is_object_loaded(obj))) | 281 | /* |
| | 282 | * Format: .klp.rela.sec_objname.section_name |
| | 283 | * See comment in klp_resolve_symbols() for an explanation |
| | 284 | * of the selected field width value. |
| | 285 | */ |
| | 286 | cnt = sscanf(shstrtab + sec->sh_name, ".klp.rela.%55[^.]", |
| | 287 | sec_objname); |
| | 288 | if (cnt != 1) { |
| | 289 | pr_err("section %s has an incorrectly formatted name\n", |
| | 290 | shstrtab + sec->sh_name); |
| 258 | return -EINVAL; | 291 | return -EINVAL; |
| | 292 | } |
| 259 | | 293 | |
| 260 | objname = klp_is_module(obj) ? obj->name : "vmlinux"; | 294 | if (strcmp(objname ? objname : "vmlinux", sec_objname)) |
| 261 | | 295 | return 0; |
| 262 | /* For each klp relocation section */ | | |
| 263 | for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) { | | |
| 264 | sec = pmod->klp_info->sechdrs + i; | | |
| 265 | secname = pmod->klp_info->secstrings + sec->sh_name; | | |
| 266 | if (!(sec->sh_flags & SHF_RELA_LIVEPATCH)) | | |
| 267 | continue; | | |
| 268 | | | |
| 269 | /* | | |
| 270 | * Format: .klp.rela.sec_objname.section_name | | |
| 271 | * See comment in klp_resolve_symbols() for an explanation | | |
| 272 | * of the selected field width value. | | |
| 273 | */ | | |
| 274 | cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname); | | |
| 275 | if (cnt != 1) { | | |
| 276 | pr_err("section %s has an incorrectly formatted name\n", | | |
| 277 | secname); | | |
| 278 | ret = -EINVAL; | | |
| 279 | break; | | |
| 280 | } | | |
| 281 | | | |
| 282 | if (strcmp(objname, sec_objname)) | | |
| 283 | continue; | | |
| 284 | | | |
| 285 | ret = klp_resolve_symbols(sec, pmod); | | |
| 286 | if (ret) | | |
| 287 | break; | | |
| 288 | | 296 | |
| 289 | ret = apply_relocate_add(pmod->klp_info->sechdrs, | 297 | ret = klp_resolve_symbols(sechdrs, strtab, symndx, sec); |
| 290 | pmod->core_kallsyms.strtab, | 298 | if (ret) |
| 291 | pmod->klp_info->symndx, i, pmod); | 299 | return ret; |
| 292 | if (ret) | | |
| 293 | break; | | |
| 294 | } | | |
| 295 | | 300 | |
| 296 | return ret; | 301 | return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod); |
| 297 | } | 302 | } |
| 298 | | 303 | |
| 299 | /* | 304 | /* |
| @@ -730,6 +735,28 @@ void __weak arch_klp_init_object_loaded(struct klp_patch *patch, · 430 unmodified lines |
| 730 | { | 735 | { |
| 731 | } | 736 | } |
| 732 | | 737 | |
| | 738 | int klp_apply_object_relocs(struct klp_patch *patch, struct klp_object *obj) |
| | 739 | { |
| | 740 | int i, ret; |
| | 741 | struct klp_modinfo *info = patch->mod->klp_info; |
| | 742 | |
| | 743 | for (i = 1; i < info->hdr.e_shnum; i++) { |
| | 744 | Elf_Shdr *sec = info->sechdrs + i; |
| | 745 | |
| | 746 | if (!(sec->sh_flags & SHF_RELA_LIVEPATCH)) |
| | 747 | continue; |
| | 748 | |
| | 749 | ret = klp_apply_section_relocs(patch->mod, info->sechdrs, |
| | 750 | info->secstrings, |
| | 751 | patch->mod->core_kallsyms.strtab, |
| | 752 | info->symndx, i, obj->name); |
| | 753 | if (ret) |
| | 754 | return ret; |
| | 755 | } |
| | 756 | |
| | 757 | return 0; |
| | 758 | } |
| | 759 | |
| 733 | /* parts of the initialization that is done only when the object is loaded */ | 760 | /* parts of the initialization that is done only when the object is loaded */ |
| 734 | static int klp_init_object_loaded(struct klp_patch *patch, | 761 | static int klp_init_object_loaded(struct klp_patch *patch, |
| 735 | struct klp_object *obj) | 762 | struct klp_object *obj) |
| @@ -738,18 +765,26 @@ static int klp_init_object_loaded(struct klp_patch *patch, · 2 unmodified lines |
| 738 | int ret; | 765 | int ret; |
| 739 | | 766 | |
| 740 | mutex_lock(&text_mutex); | 767 | mutex_lock(&text_mutex); |
| 741 | | | |
| 742 | module_disable_ro(patch->mod); | 768 | module_disable_ro(patch->mod); |
| 743 | ret = klp_write_object_relocations(patch->mod, obj); | 769 | |
| 744 | if (ret) { | 770 | if (klp_is_module(obj)) { |
| 745 | module_enable_ro(patch->mod, true); | 771 | /* |
| 746 | mutex_unlock(&text_mutex); | 772 | * Only write module-specific relocations here |
| 747 | return ret; | 773 | * (.klp.rela.{module}.*). vmlinux-specific relocations were |
| | 774 | * written earlier during the initialization of the klp module |
| | 775 | * itself. |
| | 776 | */ |
| | 777 | ret = klp_apply_object_relocs(patch, obj); |
| | 778 | if (ret) { |
| | 779 | module_enable_ro(patch->mod, true); |
| | 780 | mutex_unlock(&text_mutex); |
| | 781 | return ret; |
| | 782 | } |
| 748 | } | 783 | } |
| 749 | | 784 | |
| 750 | arch_klp_init_object_loaded(patch, obj); | 785 | arch_klp_init_object_loaded(patch, obj); |
| 751 | module_enable_ro(patch->mod, true); | | |
| 752 | | 786 | |
| | 787 | module_enable_ro(patch->mod, true); |
| 753 | mutex_unlock(&text_mutex); | 788 | mutex_unlock(&text_mutex); |
| 754 | | 789 | |
| 755 | klp_for_each_func(obj, func) { | 790 | klp_for_each_func(obj, func) { |