Merge tag 'livepatching-for-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / kernel / livepatch / core.c
index c973ed9..4bd2d5e 100644 (file)
@@ -260,6 +260,14 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
        return 0;
 }
 
+void __weak clear_relocate_add(Elf_Shdr *sechdrs,
+                  const char *strtab,
+                  unsigned int symindex,
+                  unsigned int relsec,
+                  struct module *me)
+{
+}
+
 /*
  * At a high-level, there are two types of klp relocation sections: those which
  * reference symbols which live in vmlinux; and those which reference symbols
@@ -283,10 +291,10 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
  *    the to-be-patched module to be loaded and patched sometime *after* the
  *    klp module is loaded.
  */
-int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
-                            const char *shstrtab, const char *strtab,
-                            unsigned int symndx, unsigned int secndx,
-                            const char *objname)
+static int klp_write_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
+                                   const char *shstrtab, const char *strtab,
+                                   unsigned int symndx, unsigned int secndx,
+                                   const char *objname, bool apply)
 {
        int cnt, ret;
        char sec_objname[MODULE_NAME_LEN];
@@ -308,11 +316,26 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
        if (strcmp(objname ? objname : "vmlinux", sec_objname))
                return 0;
 
-       ret = klp_resolve_symbols(sechdrs, strtab, symndx, sec, sec_objname);
-       if (ret)
-               return ret;
+       if (apply) {
+               ret = klp_resolve_symbols(sechdrs, strtab, symndx,
+                                         sec, sec_objname);
+               if (ret)
+                       return ret;
+
+               return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod);
+       }
+
+       clear_relocate_add(sechdrs, strtab, symndx, secndx, pmod);
+       return 0;
+}
 
-       return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod);
+int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
+                            const char *shstrtab, const char *strtab,
+                            unsigned int symndx, unsigned int secndx,
+                            const char *objname)
+{
+       return klp_write_section_relocs(pmod, sechdrs, shstrtab, strtab, symndx,
+                                       secndx, objname, true);
 }
 
 /*
@@ -761,8 +784,9 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
                           func->old_sympos ? func->old_sympos : 1);
 }
 
-static int klp_apply_object_relocs(struct klp_patch *patch,
-                                  struct klp_object *obj)
+static int klp_write_object_relocs(struct klp_patch *patch,
+                                  struct klp_object *obj,
+                                  bool apply)
 {
        int i, ret;
        struct klp_modinfo *info = patch->mod->klp_info;
@@ -773,10 +797,10 @@ static int klp_apply_object_relocs(struct klp_patch *patch,
                if (!(sec->sh_flags & SHF_RELA_LIVEPATCH))
                        continue;
 
-               ret = klp_apply_section_relocs(patch->mod, info->sechdrs,
+               ret = klp_write_section_relocs(patch->mod, info->sechdrs,
                                               info->secstrings,
                                               patch->mod->core_kallsyms.strtab,
-                                              info->symndx, i, obj->name);
+                                              info->symndx, i, obj->name, apply);
                if (ret)
                        return ret;
        }
@@ -784,6 +808,18 @@ static int klp_apply_object_relocs(struct klp_patch *patch,
        return 0;
 }
 
+static int klp_apply_object_relocs(struct klp_patch *patch,
+                                  struct klp_object *obj)
+{
+       return klp_write_object_relocs(patch, obj, true);
+}
+
+static void klp_clear_object_relocs(struct klp_patch *patch,
+                                   struct klp_object *obj)
+{
+       klp_write_object_relocs(patch, obj, false);
+}
+
 /* parts of the initialization that is done only when the object is loaded */
 static int klp_init_object_loaded(struct klp_patch *patch,
                                  struct klp_object *obj)
@@ -1171,7 +1207,7 @@ static void klp_cleanup_module_patches_limited(struct module *mod,
                        klp_unpatch_object(obj);
 
                        klp_post_unpatch_callback(obj);
-
+                       klp_clear_object_relocs(patch, obj);
                        klp_free_object_loaded(obj);
                        break;
                }