11573Srgrimes// SPDX-License-Identifier: GPL-2.0 2205099Sdelphij// Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com> 3187700Sdelphij 41573Srgrimes#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 51573Srgrimes 61573Srgrimes#include <linux/module.h> 71573Srgrimes#include <linux/kernel.h> 81573Srgrimes#include <linux/livepatch.h> 91573Srgrimes 101573Srgrimesstatic int replace; 111573Srgrimesmodule_param(replace, int, 0644); 121573SrgrimesMODULE_PARM_DESC(replace, "replace (default=0)"); 131573Srgrimes 14187700Sdelphijstatic const char *const module_state[] = { 151573Srgrimes [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", 161573Srgrimes [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", 17187700Sdelphij [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", 181573Srgrimes [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", 191573Srgrimes}; 201573Srgrimes 211573Srgrimesstatic void callback_info(const char *callback, struct klp_object *obj) 221573Srgrimes{ 231573Srgrimes if (obj->mod) 241573Srgrimes pr_info("%s: %s -> %s\n", callback, obj->mod->name, 251573Srgrimes module_state[obj->mod->state]); 261573Srgrimes else 2786170Sobrien pr_info("%s: vmlinux\n", callback); 2886170Sobrien} 291573Srgrimes 30187700Sdelphij/* Executed on object patching (ie, patch enablement) */ 31187700Sdelphijstatic int pre_patch_callback(struct klp_object *obj) 321573Srgrimes{ 331573Srgrimes callback_info(__func__, obj); 34187700Sdelphij return 0; 35187700Sdelphij} 36187700Sdelphij 37187700Sdelphij/* Executed on object unpatching (ie, patch disablement) */ 38187700Sdelphijstatic void post_patch_callback(struct klp_object *obj) 39187700Sdelphij{ 40187700Sdelphij callback_info(__func__, obj); 41187700Sdelphij} 42187700Sdelphij 43187700Sdelphij/* Executed on object unpatching (ie, patch disablement) */ 44187700Sdelphijstatic void pre_unpatch_callback(struct klp_object *obj) 45187700Sdelphij{ 46205099Sdelphij callback_info(__func__, obj); 47187700Sdelphij} 48205099Sdelphij 49205099Sdelphij/* Executed on object unpatching (ie, patch disablement) */ 50205099Sdelphijstatic void post_unpatch_callback(struct klp_object *obj) 51205099Sdelphij{ 52187700Sdelphij callback_info(__func__, obj); 53205099Sdelphij} 54205099Sdelphij 55205099Sdelphijstatic struct klp_func no_funcs[] = { 56205099Sdelphij { } 57187700Sdelphij}; 58187700Sdelphij 59187700Sdelphijstatic struct klp_object objs[] = { 60187700Sdelphij { 61187700Sdelphij .name = NULL, /* vmlinux */ 62187700Sdelphij .funcs = no_funcs, 63187700Sdelphij .callbacks = { 64187700Sdelphij .pre_patch = pre_patch_callback, 65187700Sdelphij .post_patch = post_patch_callback, 66187700Sdelphij .pre_unpatch = pre_unpatch_callback, 67187700Sdelphij .post_unpatch = post_unpatch_callback, 68187700Sdelphij }, 69187700Sdelphij }, { } 70187700Sdelphij}; 71187700Sdelphij 72187700Sdelphijstatic struct klp_patch patch = { 73187700Sdelphij .mod = THIS_MODULE, 74187700Sdelphij .objs = objs, 75187700Sdelphij /* set .replace in the init function below for demo purposes */ 76187700Sdelphij}; 77187700Sdelphij 78187700Sdelphijstatic int test_klp_callbacks_demo2_init(void) 79187700Sdelphij{ 80187700Sdelphij patch.replace = replace; 81187700Sdelphij return klp_enable_patch(&patch); 821573Srgrimes} 83187700Sdelphij 841573Srgrimesstatic void test_klp_callbacks_demo2_exit(void) 85187700Sdelphij{ 86187700Sdelphij} 87205099Sdelphij 881573Srgrimesmodule_init(test_klp_callbacks_demo2_init); 89205099Sdelphijmodule_exit(test_klp_callbacks_demo2_exit); 90205099SdelphijMODULE_LICENSE("GPL"); 91205099SdelphijMODULE_INFO(livepatch, "Y"); 92205099SdelphijMODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>"); 93205099SdelphijMODULE_DESCRIPTION("Livepatch test: livepatch demo2"); 94205099Sdelphij