| @@ -191,12 +191,12 @@ static int klp_find_object_symbol(const char *objname, const char *name, · 190 unmodified lines |
| 191 | 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 | 197 | int i, cnt, vmlinux, ret; |
| 197 | 198 | char objname[MODULE_NAME_LEN]; |
| 198 | 199 | char symname[KSYM_NAME_LEN]; |
| 199 | | − char *strtab = pmod->core_kallsyms.strtab; |
| 200 | 200 | Elf_Rela *relas; |
| 201 | 201 | Elf_Sym *sym; |
| 202 | 202 | unsigned long sympos, addr; |
| @@ -216,7 +216,7 @@ static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) · 13 unmodified lines |
| 216 | 216 | relas = (Elf_Rela *) relasec->sh_addr; |
| 217 | 217 | /* For each rela in this klp relocation section */ |
| 218 | 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 | 220 | if (sym->st_shndx != SHN_LIVEPATCH) { |
| 221 | 221 | pr_err("symbol %s is not marked as a livepatch symbol\n", |
| 222 | 222 | strtab + sym->st_name); |
| @@ -246,54 +246,59 @@ static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) · 23 unmodified lines |
| 246 | 246 | return 0; |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | | −static int klp_write_object_relocations(struct module *pmod, |
| 250 | | − struct klp_object *obj) |
| 249 | +/* |
| 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; |
| 253 | | − const char *objname, *secname; |
| 277 | + int cnt, ret; |
| 254 | 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 | 291 | return -EINVAL; |
| 292 | + } |
| 259 | 293 | |
| 260 | | − objname = klp_is_module(obj) ? obj->name : "vmlinux"; |
| 261 | | − |
| 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; |
| 294 | + if (strcmp(objname ? objname : "vmlinux", sec_objname)) |
| 295 | + return 0; |
| 288 | 296 | |
| 289 | | − ret = apply_relocate_add(pmod->klp_info->sechdrs, |
| 290 | | − pmod->core_kallsyms.strtab, |
| 291 | | − pmod->klp_info->symndx, i, pmod); |
| 292 | | − if (ret) |
| 293 | | − break; |
| 294 | | − } |
| 297 | + ret = klp_resolve_symbols(sechdrs, strtab, symndx, sec); |
| 298 | + if (ret) |
| 299 | + return ret; |
| 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 | 760 | /* parts of the initialization that is done only when the object is loaded */ |
| 734 | 761 | static int klp_init_object_loaded(struct klp_patch *patch, |
| 735 | 762 | struct klp_object *obj) |
| @@ -738,18 +765,26 @@ static int klp_init_object_loaded(struct klp_patch *patch, · 2 unmodified lines |
| 738 | 765 | int ret; |
| 739 | 766 | |
| 740 | 767 | mutex_lock(&text_mutex); |
| 741 | | − |
| 742 | 768 | module_disable_ro(patch->mod); |
| 743 | | − ret = klp_write_object_relocations(patch->mod, obj); |
| 744 | | − if (ret) { |
| 745 | | − module_enable_ro(patch->mod, true); |
| 746 | | − mutex_unlock(&text_mutex); |
| 747 | | − return ret; |
| 769 | + |
| 770 | + if (klp_is_module(obj)) { |
| 771 | + /* |
| 772 | + * Only write module-specific relocations here |
| 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 | 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 | 788 | mutex_unlock(&text_mutex); |
| 754 | 789 | |
| 755 | 790 | klp_for_each_func(obj, func) { |