mirror of
https://github.com/dynup/kpatch
synced 2025-01-08 22:29:34 +00:00
livepatch-patch-hook: ensure compatibility with kernels < 4.7 and >= 4.7
Use dynrelas when kernel version is < 4.7 and klp relas otherwise.
This commit is contained in:
parent
0cc693ba36
commit
355996e366
@ -35,6 +35,10 @@
|
||||
#define UTS_UBUNTU_RELEASE_ABI 0
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
|
||||
#define NEED_KLP_RELOCS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* There are quite a few similar structures at play in this file:
|
||||
* - livepatch.h structs prefixed with klp_*
|
||||
@ -83,7 +87,9 @@ static struct patch_object *patch_alloc_new_object(const char *name)
|
||||
if (!object)
|
||||
return NULL;
|
||||
INIT_LIST_HEAD(&object->funcs);
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
INIT_LIST_HEAD(&object->relocs);
|
||||
#endif
|
||||
if (strcmp(name, "vmlinux"))
|
||||
object->name = name;
|
||||
list_add(&object->list, &patch_objects);
|
||||
@ -123,6 +129,7 @@ static int patch_add_func_to_object(struct kpatch_patch_func *kfunc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
|
||||
{
|
||||
struct patch_reloc *reloc;
|
||||
@ -143,11 +150,14 @@ static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
|
||||
object->relocs_nr++;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void patch_free_scaffold(void) {
|
||||
struct patch_func *func, *safefunc;
|
||||
struct patch_reloc *reloc, *safereloc;
|
||||
struct patch_object *object, *safeobject;
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
struct patch_reloc *reloc, *safereloc;
|
||||
#endif
|
||||
|
||||
list_for_each_entry_safe(object, safeobject, &patch_objects, list) {
|
||||
list_for_each_entry_safe(func, safefunc,
|
||||
@ -155,11 +165,13 @@ static void patch_free_scaffold(void) {
|
||||
list_del(&func->list);
|
||||
kfree(func);
|
||||
}
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
list_for_each_entry_safe(reloc, safereloc,
|
||||
&object->relocs, list) {
|
||||
list_del(&reloc->list);
|
||||
kfree(reloc);
|
||||
}
|
||||
#endif
|
||||
list_del(&object->list);
|
||||
kfree(object);
|
||||
}
|
||||
@ -173,8 +185,10 @@ static void patch_free_livepatch(struct klp_patch *patch)
|
||||
for (object = patch->objs; object && object->funcs; object++) {
|
||||
if (object->funcs)
|
||||
kfree(object->funcs);
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
if (object->relocs)
|
||||
kfree(object->relocs);
|
||||
#endif
|
||||
}
|
||||
if (patch->objs)
|
||||
kfree(patch->objs);
|
||||
@ -183,19 +197,23 @@ static void patch_free_livepatch(struct klp_patch *patch)
|
||||
}
|
||||
|
||||
extern struct kpatch_patch_func __kpatch_funcs[], __kpatch_funcs_end[];
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
extern struct kpatch_patch_dynrela __kpatch_dynrelas[], __kpatch_dynrelas_end[];
|
||||
#endif
|
||||
|
||||
static int __init patch_init(void)
|
||||
{
|
||||
struct kpatch_patch_func *kfunc;
|
||||
struct kpatch_patch_dynrela *kdynrela;
|
||||
struct klp_object *lobjects, *lobject;
|
||||
struct klp_func *lfuncs, *lfunc;
|
||||
struct klp_reloc *lrelocs, *lreloc;
|
||||
struct patch_object *object;
|
||||
struct patch_func *func;
|
||||
struct patch_reloc *reloc;
|
||||
int ret = 0, i, j;
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
struct kpatch_patch_dynrela *kdynrela;
|
||||
struct patch_reloc *reloc;
|
||||
struct klp_reloc *lrelocs, *lreloc;
|
||||
#endif
|
||||
|
||||
/* organize functions and relocs by object in scaffold */
|
||||
for (kfunc = __kpatch_funcs;
|
||||
@ -206,6 +224,7 @@ static int __init patch_init(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
for (kdynrela = __kpatch_dynrelas;
|
||||
kdynrela != __kpatch_dynrelas_end;
|
||||
kdynrela++) {
|
||||
@ -213,6 +232,7 @@ static int __init patch_init(void)
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* past this point, only possible return code is -ENOMEM */
|
||||
ret = -ENOMEM;
|
||||
@ -254,6 +274,7 @@ static int __init patch_init(void)
|
||||
j++;
|
||||
}
|
||||
|
||||
#ifdef NEED_KLP_RELOCS
|
||||
lrelocs = kzalloc(sizeof(struct klp_reloc) *
|
||||
(object->relocs_nr+1), GFP_KERNEL);
|
||||
if (!lrelocs)
|
||||
@ -270,13 +291,14 @@ static int __init patch_init(void)
|
||||
lreloc->sympos = reloc->kdynrela->sympos;
|
||||
#else
|
||||
lreloc->val = reloc->kdynrela->src;
|
||||
#endif
|
||||
#endif /* 4.5.0 */
|
||||
lreloc->type = reloc->kdynrela->type;
|
||||
lreloc->name = reloc->kdynrela->name;
|
||||
lreloc->addend = reloc->kdynrela->addend;
|
||||
lreloc->external = reloc->kdynrela->external;
|
||||
j++;
|
||||
}
|
||||
#endif /* 4.7.0 */
|
||||
|
||||
i++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user