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 'livepatching-for-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching

Pull livepatching updates from Petr Mladek:

- Allow reloading a livepatched module by clearing livepatch-specific
relocations in the livepatch module.

Otherwise, the repeated load would fail on consistency checks.

* tag 'livepatching-for-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching:
livepatch,x86: Clear relocation targets on a module removal
x86/module: remove unused code in __apply_relocate_add

+126 -50
+60 -37
arch/x86/kernel/module.c
··· 129 129 return 0; 130 130 } 131 131 #else /*X86_64*/ 132 - static int __apply_relocate_add(Elf64_Shdr *sechdrs, 132 + static int __write_relocate_add(Elf64_Shdr *sechdrs, 133 133 const char *strtab, 134 134 unsigned int symindex, 135 135 unsigned int relsec, 136 136 struct module *me, 137 - void *(*write)(void *dest, const void *src, size_t len)) 137 + void *(*write)(void *dest, const void *src, size_t len), 138 + bool apply) 138 139 { 139 140 unsigned int i; 140 141 Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; 141 142 Elf64_Sym *sym; 142 143 void *loc; 143 144 u64 val; 145 + u64 zero = 0ULL; 144 146 145 - DEBUGP("Applying relocate section %u to %u\n", 147 + DEBUGP("%s relocate section %u to %u\n", 148 + apply ? "Applying" : "Clearing", 146 149 relsec, sechdrs[relsec].sh_info); 147 150 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 151 + size_t size; 152 + 148 153 /* This is where to make the change */ 149 154 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 150 155 + rel[i].r_offset; ··· 167 162 168 163 switch (ELF64_R_TYPE(rel[i].r_info)) { 169 164 case R_X86_64_NONE: 170 - break; 165 + continue; /* nothing to write */ 171 166 case R_X86_64_64: 172 - if (*(u64 *)loc != 0) 173 - goto invalid_relocation; 174 - write(loc, &val, 8); 167 + size = 8; 175 168 break; 176 169 case R_X86_64_32: 177 - if (*(u32 *)loc != 0) 178 - goto invalid_relocation; 179 - write(loc, &val, 4); 180 - if (val != *(u32 *)loc) 170 + if (val != *(u32 *)&val) 181 171 goto overflow; 172 + size = 4; 182 173 break; 183 174 case R_X86_64_32S: 184 - if (*(s32 *)loc != 0) 185 - goto invalid_relocation; 186 - write(loc, &val, 4); 187 - if ((s64)val != *(s32 *)loc) 175 + if ((s64)val != *(s32 *)&val) 188 176 goto overflow; 177 + size = 4; 189 178 break; 190 179 case R_X86_64_PC32: 191 180 case R_X86_64_PLT32: 192 - if (*(u32 *)loc != 0) 193 - goto invalid_relocation; 194 181 val -= (u64)loc; 195 - write(loc, &val, 4); 196 - #if 0 197 - if ((s64)val != *(s32 *)loc) 198 - goto overflow; 199 - #endif 182 + size = 4; 200 183 break; 201 184 case R_X86_64_PC64: 202 - if (*(u64 *)loc != 0) 203 - goto invalid_relocation; 204 185 val -= (u64)loc; 205 - write(loc, &val, 8); 186 + size = 8; 206 187 break; 207 188 default: 208 189 pr_err("%s: Unknown rela relocation: %llu\n", 209 190 me->name, ELF64_R_TYPE(rel[i].r_info)); 210 191 return -ENOEXEC; 211 192 } 193 + 194 + if (apply) { 195 + if (memcmp(loc, &zero, size)) { 196 + pr_err("x86/modules: Invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", 197 + (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 198 + return -ENOEXEC; 199 + } 200 + write(loc, &val, size); 201 + } else { 202 + if (memcmp(loc, &val, size)) { 203 + pr_warn("x86/modules: Invalid relocation target, existing value does not match expected value for type %d, loc %p, val %Lx\n", 204 + (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 205 + return -ENOEXEC; 206 + } 207 + write(loc, &zero, size); 208 + } 212 209 } 213 210 return 0; 214 - 215 - invalid_relocation: 216 - pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", 217 - (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 218 - return -ENOEXEC; 219 211 220 212 overflow: 221 213 pr_err("overflow in relocation type %d val %Lx\n", ··· 222 220 return -ENOEXEC; 223 221 } 224 222 225 - int apply_relocate_add(Elf64_Shdr *sechdrs, 226 - const char *strtab, 227 - unsigned int symindex, 228 - unsigned int relsec, 229 - struct module *me) 223 + static int write_relocate_add(Elf64_Shdr *sechdrs, 224 + const char *strtab, 225 + unsigned int symindex, 226 + unsigned int relsec, 227 + struct module *me, 228 + bool apply) 230 229 { 231 230 int ret; 232 231 bool early = me->state == MODULE_STATE_UNFORMED; ··· 238 235 mutex_lock(&text_mutex); 239 236 } 240 237 241 - ret = __apply_relocate_add(sechdrs, strtab, symindex, relsec, me, 242 - write); 238 + ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me, 239 + write, apply); 243 240 244 241 if (!early) { 245 242 text_poke_sync(); ··· 248 245 249 246 return ret; 250 247 } 248 + 249 + int apply_relocate_add(Elf64_Shdr *sechdrs, 250 + const char *strtab, 251 + unsigned int symindex, 252 + unsigned int relsec, 253 + struct module *me) 254 + { 255 + return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true); 256 + } 257 + 258 + #ifdef CONFIG_LIVEPATCH 259 + void clear_relocate_add(Elf64_Shdr *sechdrs, 260 + const char *strtab, 261 + unsigned int symindex, 262 + unsigned int relsec, 263 + struct module *me) 264 + { 265 + write_relocate_add(sechdrs, strtab, symindex, relsec, me, false); 266 + } 267 + #endif 251 268 252 269 #endif 253 270
+17
include/linux/moduleloader.h
··· 75 75 unsigned int symindex, 76 76 unsigned int relsec, 77 77 struct module *mod); 78 + #ifdef CONFIG_LIVEPATCH 79 + /* 80 + * Some architectures (namely x86_64 and ppc64) perform sanity checks when 81 + * applying relocations. If a patched module gets unloaded and then later 82 + * reloaded (and re-patched), klp re-applies relocations to the replacement 83 + * function(s). Any leftover relocations from the previous loading of the 84 + * patched module might trigger the sanity checks. 85 + * 86 + * To prevent that, when unloading a patched module, clear out any relocations 87 + * that might trigger arch-specific sanity checks on a future module reload. 88 + */ 89 + void clear_relocate_add(Elf_Shdr *sechdrs, 90 + const char *strtab, 91 + unsigned int symindex, 92 + unsigned int relsec, 93 + struct module *me); 94 + #endif 78 95 #else 79 96 static inline int apply_relocate_add(Elf_Shdr *sechdrs, 80 97 const char *strtab,
+49 -13
kernel/livepatch/core.c
··· 260 260 return 0; 261 261 } 262 262 263 + void __weak clear_relocate_add(Elf_Shdr *sechdrs, 264 + const char *strtab, 265 + unsigned int symindex, 266 + unsigned int relsec, 267 + struct module *me) 268 + { 269 + } 270 + 263 271 /* 264 272 * At a high-level, there are two types of klp relocation sections: those which 265 273 * reference symbols which live in vmlinux; and those which reference symbols ··· 291 283 * the to-be-patched module to be loaded and patched sometime *after* the 292 284 * klp module is loaded. 293 285 */ 294 - int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, 295 - const char *shstrtab, const char *strtab, 296 - unsigned int symndx, unsigned int secndx, 297 - const char *objname) 286 + static int klp_write_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, 287 + const char *shstrtab, const char *strtab, 288 + unsigned int symndx, unsigned int secndx, 289 + const char *objname, bool apply) 298 290 { 299 291 int cnt, ret; 300 292 char sec_objname[MODULE_NAME_LEN]; ··· 316 308 if (strcmp(objname ? objname : "vmlinux", sec_objname)) 317 309 return 0; 318 310 319 - ret = klp_resolve_symbols(sechdrs, strtab, symndx, sec, sec_objname); 320 - if (ret) 321 - return ret; 311 + if (apply) { 312 + ret = klp_resolve_symbols(sechdrs, strtab, symndx, 313 + sec, sec_objname); 314 + if (ret) 315 + return ret; 322 316 323 - return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod); 317 + return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod); 318 + } 319 + 320 + clear_relocate_add(sechdrs, strtab, symndx, secndx, pmod); 321 + return 0; 322 + } 323 + 324 + int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, 325 + const char *shstrtab, const char *strtab, 326 + unsigned int symndx, unsigned int secndx, 327 + const char *objname) 328 + { 329 + return klp_write_section_relocs(pmod, sechdrs, shstrtab, strtab, symndx, 330 + secndx, objname, true); 324 331 } 325 332 326 333 /* ··· 784 761 func->old_sympos ? func->old_sympos : 1); 785 762 } 786 763 787 - static int klp_apply_object_relocs(struct klp_patch *patch, 788 - struct klp_object *obj) 764 + static int klp_write_object_relocs(struct klp_patch *patch, 765 + struct klp_object *obj, 766 + bool apply) 789 767 { 790 768 int i, ret; 791 769 struct klp_modinfo *info = patch->mod->klp_info; ··· 797 773 if (!(sec->sh_flags & SHF_RELA_LIVEPATCH)) 798 774 continue; 799 775 800 - ret = klp_apply_section_relocs(patch->mod, info->sechdrs, 776 + ret = klp_write_section_relocs(patch->mod, info->sechdrs, 801 777 info->secstrings, 802 778 patch->mod->core_kallsyms.strtab, 803 - info->symndx, i, obj->name); 779 + info->symndx, i, obj->name, apply); 804 780 if (ret) 805 781 return ret; 806 782 } 807 783 808 784 return 0; 785 + } 786 + 787 + static int klp_apply_object_relocs(struct klp_patch *patch, 788 + struct klp_object *obj) 789 + { 790 + return klp_write_object_relocs(patch, obj, true); 791 + } 792 + 793 + static void klp_clear_object_relocs(struct klp_patch *patch, 794 + struct klp_object *obj) 795 + { 796 + klp_write_object_relocs(patch, obj, false); 809 797 } 810 798 811 799 /* parts of the initialization that is done only when the object is loaded */ ··· 1207 1171 klp_unpatch_object(obj); 1208 1172 1209 1173 klp_post_unpatch_callback(obj); 1210 - 1174 + klp_clear_object_relocs(patch, obj); 1211 1175 klp_free_object_loaded(obj); 1212 1176 break; 1213 1177 }