livepatch.h 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/*
 * livepatch.h - Kernel Live Patching Core
 *
 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
 * Copyright (C) 2014 SUSE
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _LINUX_LIVEPATCH_H_
#define _LINUX_LIVEPATCH_H_

#include <linux/module.h>
#include <linux/ftrace.h>

#if IS_ENABLED(CONFIG_LIVE_PATCHING)

#include <asm/livepatch.h>

enum klp_state {
	KLP_DISABLED,
	KLP_ENABLED
};

/**
 * struct klp_func - function structure for live patching
 * @old_name:	name of the function to be patched
 * @new_func:	pointer to the patched function code
 * @old_addr:	a hint conveying at what address the old function
 *		can be found (optional, vmlinux patches only)
 * @kobj:	kobject for sysfs resources
 * @fops:	ftrace operations structure
 * @state:	tracks function-level patch application state
 */
struct klp_func {
	/* external */
	const char *old_name;
	void *new_func;
	/*
	 * The old_addr field is optional and can be used to resolve
	 * duplicate symbol names in the vmlinux object.  If this
	 * information is not present, the symbol is located by name
	 * with kallsyms. If the name is not unique and old_addr is
	 * not provided, the patch application fails as there is no
	 * way to resolve the ambiguity.
	 */
	unsigned long old_addr;

	/* internal */
	struct kobject kobj;
	struct ftrace_ops *fops;
	enum klp_state state;
};

/**
 * struct klp_reloc - relocation structure for live patching
 * @loc:	address where the relocation will be written
 * @val:	address of the referenced symbol (optional,
 *		vmlinux	patches only)
 * @type:	ELF relocation type
 * @name:	name of the referenced symbol (for lookup/verification)
 * @addend:	offset from the referenced symbol
 * @external:	symbol is either exported or within the live patch module itself
 */
struct klp_reloc {
	unsigned long loc;
	unsigned long val;
	unsigned long type;
	const char *name;
	int addend;
	int external;
};

/**
 * struct klp_object - kernel object structure for live patching
 * @name:	module name (or NULL for vmlinux)
 * @relocs:	relocation entries to be applied at load time
 * @funcs:	function entries for functions to be patched in the object
 * @kobj:	kobject for sysfs resources
 * @mod:	kernel module associated with the patched object
 * 		(NULL for vmlinux)
 * @state:	tracks object-level patch application state
 */
struct klp_object {
	/* external */
	const char *name;
	struct klp_reloc *relocs;
	struct klp_func *funcs;

	/* internal */
	struct kobject *kobj;
	struct module *mod;
	enum klp_state state;
};

/**
 * struct klp_patch - patch structure for live patching
 * @mod:	reference to the live patch module
 * @objs:	object entries for kernel objects to be patched
 * @list:	list node for global list of registered patches
 * @kobj:	kobject for sysfs resources
 * @state:	tracks patch-level application state
 */
struct klp_patch {
	/* external */
	struct module *mod;
	struct klp_object *objs;

	/* internal */
	struct list_head list;
	struct kobject kobj;
	enum klp_state state;
};

extern int klp_register_patch(struct klp_patch *);
extern int klp_unregister_patch(struct klp_patch *);
extern int klp_enable_patch(struct klp_patch *);
extern int klp_disable_patch(struct klp_patch *);

#endif /* CONFIG_LIVE_PATCHING */

#endif /* _LINUX_LIVEPATCH_H_ */