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