// SPDX-License-Identifier: GPL-2.0-or-later/* * core.c - Kernel Live Patching Core * * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com> * Copyright (C) 2014 SUSE */#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt#include<linux/module.h>#include<linux/kernel.h>#include<linux/mutex.h>#include<linux/slab.h>#include<linux/list.h>#include<linux/kallsyms.h>#include<linux/livepatch.h>#include<linux/elf.h>#include<linux/moduleloader.h>#include<linux/completion.h>#include<linux/memory.h>#include<linux/rcupdate.h>#include<asm/cacheflush.h>#include"core.h"#include"patch.h"#include"state.h"#include"transition.h"/* * klp_mutex is a coarse lock which serializes access to klp data. All * accesses to klp-related variables and structures must have mutex protection, * except within the following functions which carefully avoid the need for it: * * - klp_ftrace_handler() * - klp_update_patch_state() * - __klp_sched_try_switch() */DEFINE_MUTEX(klp_mutex);/* * Actively used patches: enabled or in transition. Note that replaced * or disabled patches are not listed even though the related kernel * module still can be loaded. */LIST_HEAD(klp_patches);staticstructkobject*klp_root_kobj;staticboolklp_is_module(structklp_object*obj){returnobj->name;}/* sets obj->mod if object is not vmlinux and module is found */staticvoidklp_find_object_module(structklp_object*obj){structmodule*mod;if(!klp_is_module(obj))return;guard(rcu)();/* * We do not want to block removal of patched modules and therefore * we do not take a reference here. The patches are removed by * klp_module_going() instead. */mod=find_module(obj->name);/* * Do not mess work of klp_module_coming() and klp_module_going(). * Note that the patch might still be needed before klp_module_going() * is called. Module functions can be called even in the GOING state * until mod->exit() finishes. This is especially important for * patches that modify semantic of the functions. */if(mod&&mod->klp_alive)obj->mod=mod;}staticboolklp_initialized(void){return!!klp_root_kobj;}staticstructklp_func*klp_find_func(structklp_object*obj,structklp_func*old_func){structklp_func*func;klp_for_each_func(obj,func){if((strcmp(old_func->old_name,func->old_name)