cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_klp_state.c (3907B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2019 SUSE
      3
      4#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      5
      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 1
     13/* Version 1 does not support migration. */
     14#define CONSOLE_LOGLEVEL_STATE_VERSION 1
     15
     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	else
     29		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");