brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 57a4253 Raw
163 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2019 SUSE3 4#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt5 6#include <linux/slab.h>7#include <linux/module.h>8#include <linux/kernel.h>9#include <linux/printk.h>10#include <linux/livepatch.h>11 12#define CONSOLE_LOGLEVEL_STATE 113/* Version 1 does not support migration. */14#define CONSOLE_LOGLEVEL_STATE_VERSION 115 16static const char *const module_state[] = {17	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",18	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",19	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",20	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",21};22 23static void callback_info(const char *callback, struct klp_object *obj)24{25	if (obj->mod)26		pr_info("%s: %s -> %s\n", callback, obj->mod->name,27			module_state[obj->mod->state]);28	else29		pr_info("%s: vmlinux\n", callback);30}31 32static struct klp_patch patch;33 34static int allocate_loglevel_state(void)35{36	struct klp_state *loglevel_state;37 38	loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE);39	if (!loglevel_state)40		return -EINVAL;41 42	loglevel_state->data = kzalloc(sizeof(console_loglevel), GFP_KERNEL);43	if (!loglevel_state->data)44		return -ENOMEM;45 46	pr_info("%s: allocating space to store console_loglevel\n",47		__func__);48	return 0;49}50 51static void fix_console_loglevel(void)52{53	struct klp_state *loglevel_state;54 55	loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE);56	if (!loglevel_state)57		return;58 59	pr_info("%s: fixing console_loglevel\n", __func__);60	*(int *)loglevel_state->data = console_loglevel;61	console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;62}63 64static void restore_console_loglevel(void)65{66	struct klp_state *loglevel_state;67 68	loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE);69	if (!loglevel_state)70		return;71 72	pr_info("%s: restoring console_loglevel\n", __func__);73	console_loglevel = *(int *)loglevel_state->data;74}75 76static void free_loglevel_state(void)77{78	struct klp_state *loglevel_state;79 80	loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE);81	if (!loglevel_state)82		return;83 84	pr_info("%s: freeing space for the stored console_loglevel\n",85		__func__);86	kfree(loglevel_state->data);87}88 89/* Executed on object patching (ie, patch enablement) */90static int pre_patch_callback(struct klp_object *obj)91{92	callback_info(__func__, obj);93	return allocate_loglevel_state();94}95 96/* Executed on object unpatching (ie, patch disablement) */97static void post_patch_callback(struct klp_object *obj)98{99	callback_info(__func__, obj);100	fix_console_loglevel();101}102 103/* Executed on object unpatching (ie, patch disablement) */104static void pre_unpatch_callback(struct klp_object *obj)105{106	callback_info(__func__, obj);107	restore_console_loglevel();108}109 110/* Executed on object unpatching (ie, patch disablement) */111static void post_unpatch_callback(struct klp_object *obj)112{113	callback_info(__func__, obj);114	free_loglevel_state();115}116 117static struct klp_func no_funcs[] = {118	{}119};120 121static struct klp_object objs[] = {122	{123		.name = NULL,	/* vmlinux */124		.funcs = no_funcs,125		.callbacks = {126			.pre_patch = pre_patch_callback,127			.post_patch = post_patch_callback,128			.pre_unpatch = pre_unpatch_callback,129			.post_unpatch = post_unpatch_callback,130		},131	}, { }132};133 134static struct klp_state states[] = {135	{136		.id = CONSOLE_LOGLEVEL_STATE,137		.version = CONSOLE_LOGLEVEL_STATE_VERSION,138	}, { }139};140 141static struct klp_patch patch = {142	.mod = THIS_MODULE,143	.objs = objs,144	.states = states,145	.replace = true,146};147 148static int test_klp_callbacks_demo_init(void)149{150	return klp_enable_patch(&patch);151}152 153static void test_klp_callbacks_demo_exit(void)154{155}156 157module_init(test_klp_callbacks_demo_init);158module_exit(test_klp_callbacks_demo_exit);159MODULE_LICENSE("GPL");160MODULE_INFO(livepatch, "Y");161MODULE_AUTHOR("Petr Mladek <pmladek@suse.com>");162MODULE_DESCRIPTION("Livepatch test: system state modification");163