0001
0002
0003
0004 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0005
0006 #include <linux/module.h>
0007 #include <linux/kernel.h>
0008 #include <linux/livepatch.h>
0009
0010 static int pre_patch_ret;
0011 module_param(pre_patch_ret, int, 0644);
0012 MODULE_PARM_DESC(pre_patch_ret, "pre_patch_ret (default=0)");
0013
0014 static const char *const module_state[] = {
0015 [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state",
0016 [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init",
0017 [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away",
0018 [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up",
0019 };
0020
0021 static void callback_info(const char *callback, struct klp_object *obj)
0022 {
0023 if (obj->mod)
0024 pr_info("%s: %s -> %s\n", callback, obj->mod->name,
0025 module_state[obj->mod->state]);
0026 else
0027 pr_info("%s: vmlinux\n", callback);
0028 }
0029
0030
0031 static int pre_patch_callback(struct klp_object *obj)
0032 {
0033 callback_info(__func__, obj);
0034 return pre_patch_ret;
0035 }
0036
0037
0038 static void post_patch_callback(struct klp_object *obj)
0039 {
0040 callback_info(__func__, obj);
0041 }
0042
0043
0044 static void pre_unpatch_callback(struct klp_object *obj)
0045 {
0046 callback_info(__func__, obj);
0047 }
0048
0049
0050 static void post_unpatch_callback(struct klp_object *obj)
0051 {
0052 callback_info(__func__, obj);
0053 }
0054
0055 static void patched_work_func(struct work_struct *work)
0056 {
0057 pr_info("%s\n", __func__);
0058 }
0059
0060 static struct klp_func no_funcs[] = {
0061 {}
0062 };
0063
0064 static struct klp_func busymod_funcs[] = {
0065 {
0066 .old_name = "busymod_work_func",
0067 .new_func = patched_work_func,
0068 }, {}
0069 };
0070
0071 static struct klp_object objs[] = {
0072 {
0073 .name = NULL,
0074 .funcs = no_funcs,
0075 .callbacks = {
0076 .pre_patch = pre_patch_callback,
0077 .post_patch = post_patch_callback,
0078 .pre_unpatch = pre_unpatch_callback,
0079 .post_unpatch = post_unpatch_callback,
0080 },
0081 }, {
0082 .name = "test_klp_callbacks_mod",
0083 .funcs = no_funcs,
0084 .callbacks = {
0085 .pre_patch = pre_patch_callback,
0086 .post_patch = post_patch_callback,
0087 .pre_unpatch = pre_unpatch_callback,
0088 .post_unpatch = post_unpatch_callback,
0089 },
0090 }, {
0091 .name = "test_klp_callbacks_busy",
0092 .funcs = busymod_funcs,
0093 .callbacks = {
0094 .pre_patch = pre_patch_callback,
0095 .post_patch = post_patch_callback,
0096 .pre_unpatch = pre_unpatch_callback,
0097 .post_unpatch = post_unpatch_callback,
0098 },
0099 }, { }
0100 };
0101
0102 static struct klp_patch patch = {
0103 .mod = THIS_MODULE,
0104 .objs = objs,
0105 };
0106
0107 static int test_klp_callbacks_demo_init(void)
0108 {
0109 return klp_enable_patch(&patch);
0110 }
0111
0112 static void test_klp_callbacks_demo_exit(void)
0113 {
0114 }
0115
0116 module_init(test_klp_callbacks_demo_init);
0117 module_exit(test_klp_callbacks_demo_exit);
0118 MODULE_LICENSE("GPL");
0119 MODULE_INFO(livepatch, "Y");
0120 MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
0121 MODULE_DESCRIPTION("Livepatch test: livepatch demo");