diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index 2863ab1183210edcf8bf8fbf271ed0d6f4b42c30..f6ec6086a15f5bd095efe9c142fa6ba28352ad06 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -90,6 +90,12 @@ struct klp_func { struct klp_object; +#ifdef CONFIG_LIVEPATCH_WO_FTRACE +struct klp_hook { + void (*hook)(void); +}; +#endif + /** * struct klp_callbacks - pre/post live-(un)patch callback structure * @pre_patch: executed before code patching @@ -126,6 +132,10 @@ struct klp_object { /* external */ const char *name; struct klp_func *funcs; +#ifdef CONFIG_LIVEPATCH_WO_FTRACE + struct klp_hook *hooks_load; + struct klp_hook *hooks_unload; +#endif struct klp_callbacks callbacks; /* internal */ diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 1fdb688475e9dc7ff078a3c88577487e4c024bd0..aac5fe5b037cc55ee1944eaf4f6b29f7bcae1c9f 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -1056,6 +1056,34 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj) return ret; } +#ifdef CONFIG_LIVEPATCH_WO_FTRACE +static inline int klp_load_hook(struct klp_object *obj) +{ + struct klp_hook *hook; + + if (!obj->hooks_load) + return 0; + + for (hook = obj->hooks_load; hook->hook; hook++) + (*hook->hook)(); + + return 0; +} + +static inline int klp_unload_hook(struct klp_object *obj) +{ + struct klp_hook *hook; + + if (!obj->hooks_unload) + return 0; + + for (hook = obj->hooks_unload; hook->hook; hook++) + (*hook->hook)(); + + return 0; +} +#endif + static int klp_init_patch(struct klp_patch *patch) { struct klp_object *obj; @@ -1087,6 +1115,11 @@ static int klp_init_patch(struct klp_patch *patch) goto free; } +#ifdef CONFIG_LIVEPATCH_WO_FTRACE + klp_for_each_object(patch, obj) + klp_load_hook(obj); +#endif + list_add_tail(&patch->list, &klp_patches); mutex_unlock(&klp_mutex); @@ -1115,6 +1148,9 @@ static int klp_init_patch(struct klp_patch *patch) int klp_unregister_patch(struct klp_patch *patch) { int ret; +#ifdef CONFIG_LIVEPATCH_WO_FTRACE + struct klp_object *obj; +#endif mutex_lock(&klp_mutex); @@ -1130,6 +1166,11 @@ int klp_unregister_patch(struct klp_patch *patch) klp_free_patch(patch); +#ifdef CONFIG_LIVEPATCH_WO_FTRACE + klp_for_each_object(patch, obj) + klp_unload_hook(obj); +#endif + mutex_unlock(&klp_mutex); kobject_put(&patch->kobj);