xref: /linux/lib/error-inject.c (revision 663faf9f7beeaca4ad0176bb96c776eed9dad0c5)
1540adea3SMasami Hiramatsu // SPDX-License-Identifier: GPL-2.0
2540adea3SMasami Hiramatsu // error-inject.c: Function-level error injection table
3540adea3SMasami Hiramatsu #include <linux/error-injection.h>
4540adea3SMasami Hiramatsu #include <linux/debugfs.h>
5540adea3SMasami Hiramatsu #include <linux/kallsyms.h>
6540adea3SMasami Hiramatsu #include <linux/kprobes.h>
7540adea3SMasami Hiramatsu #include <linux/module.h>
8540adea3SMasami Hiramatsu #include <linux/mutex.h>
9540adea3SMasami Hiramatsu #include <linux/list.h>
10540adea3SMasami Hiramatsu #include <linux/slab.h>
11540adea3SMasami Hiramatsu 
12540adea3SMasami Hiramatsu /* Whitelist of symbols that can be overridden for error injection. */
13540adea3SMasami Hiramatsu static LIST_HEAD(error_injection_list);
14540adea3SMasami Hiramatsu static DEFINE_MUTEX(ei_mutex);
15540adea3SMasami Hiramatsu struct ei_entry {
16540adea3SMasami Hiramatsu 	struct list_head list;
17540adea3SMasami Hiramatsu 	unsigned long start_addr;
18540adea3SMasami Hiramatsu 	unsigned long end_addr;
19*663faf9fSMasami Hiramatsu 	int etype;
20540adea3SMasami Hiramatsu 	void *priv;
21540adea3SMasami Hiramatsu };
22540adea3SMasami Hiramatsu 
23540adea3SMasami Hiramatsu bool within_error_injection_list(unsigned long addr)
24540adea3SMasami Hiramatsu {
25540adea3SMasami Hiramatsu 	struct ei_entry *ent;
26540adea3SMasami Hiramatsu 	bool ret = false;
27540adea3SMasami Hiramatsu 
28540adea3SMasami Hiramatsu 	mutex_lock(&ei_mutex);
29540adea3SMasami Hiramatsu 	list_for_each_entry(ent, &error_injection_list, list) {
30540adea3SMasami Hiramatsu 		if (addr >= ent->start_addr && addr < ent->end_addr) {
31540adea3SMasami Hiramatsu 			ret = true;
32540adea3SMasami Hiramatsu 			break;
33540adea3SMasami Hiramatsu 		}
34540adea3SMasami Hiramatsu 	}
35540adea3SMasami Hiramatsu 	mutex_unlock(&ei_mutex);
36540adea3SMasami Hiramatsu 	return ret;
37540adea3SMasami Hiramatsu }
38540adea3SMasami Hiramatsu 
39*663faf9fSMasami Hiramatsu int get_injectable_error_type(unsigned long addr)
40*663faf9fSMasami Hiramatsu {
41*663faf9fSMasami Hiramatsu 	struct ei_entry *ent;
42*663faf9fSMasami Hiramatsu 
43*663faf9fSMasami Hiramatsu 	list_for_each_entry(ent, &error_injection_list, list) {
44*663faf9fSMasami Hiramatsu 		if (addr >= ent->start_addr && addr < ent->end_addr)
45*663faf9fSMasami Hiramatsu 			return ent->etype;
46*663faf9fSMasami Hiramatsu 	}
47*663faf9fSMasami Hiramatsu 	return EI_ETYPE_NONE;
48*663faf9fSMasami Hiramatsu }
49*663faf9fSMasami Hiramatsu 
50540adea3SMasami Hiramatsu /*
51540adea3SMasami Hiramatsu  * Lookup and populate the error_injection_list.
52540adea3SMasami Hiramatsu  *
53540adea3SMasami Hiramatsu  * For safety reasons we only allow certain functions to be overridden with
54540adea3SMasami Hiramatsu  * bpf_error_injection, so we need to populate the list of the symbols that have
55540adea3SMasami Hiramatsu  * been marked as safe for overriding.
56540adea3SMasami Hiramatsu  */
57*663faf9fSMasami Hiramatsu static void populate_error_injection_list(struct error_injection_entry *start,
58*663faf9fSMasami Hiramatsu 					  struct error_injection_entry *end,
59*663faf9fSMasami Hiramatsu 					  void *priv)
60540adea3SMasami Hiramatsu {
61*663faf9fSMasami Hiramatsu 	struct error_injection_entry *iter;
62540adea3SMasami Hiramatsu 	struct ei_entry *ent;
63540adea3SMasami Hiramatsu 	unsigned long entry, offset = 0, size = 0;
64540adea3SMasami Hiramatsu 
65540adea3SMasami Hiramatsu 	mutex_lock(&ei_mutex);
66540adea3SMasami Hiramatsu 	for (iter = start; iter < end; iter++) {
67*663faf9fSMasami Hiramatsu 		entry = arch_deref_entry_point((void *)iter->addr);
68540adea3SMasami Hiramatsu 
69540adea3SMasami Hiramatsu 		if (!kernel_text_address(entry) ||
70540adea3SMasami Hiramatsu 		    !kallsyms_lookup_size_offset(entry, &size, &offset)) {
71540adea3SMasami Hiramatsu 			pr_err("Failed to find error inject entry at %p\n",
72540adea3SMasami Hiramatsu 				(void *)entry);
73540adea3SMasami Hiramatsu 			continue;
74540adea3SMasami Hiramatsu 		}
75540adea3SMasami Hiramatsu 
76540adea3SMasami Hiramatsu 		ent = kmalloc(sizeof(*ent), GFP_KERNEL);
77540adea3SMasami Hiramatsu 		if (!ent)
78540adea3SMasami Hiramatsu 			break;
79540adea3SMasami Hiramatsu 		ent->start_addr = entry;
80540adea3SMasami Hiramatsu 		ent->end_addr = entry + size;
81*663faf9fSMasami Hiramatsu 		ent->etype = iter->etype;
82540adea3SMasami Hiramatsu 		ent->priv = priv;
83540adea3SMasami Hiramatsu 		INIT_LIST_HEAD(&ent->list);
84540adea3SMasami Hiramatsu 		list_add_tail(&ent->list, &error_injection_list);
85540adea3SMasami Hiramatsu 	}
86540adea3SMasami Hiramatsu 	mutex_unlock(&ei_mutex);
87540adea3SMasami Hiramatsu }
88540adea3SMasami Hiramatsu 
89540adea3SMasami Hiramatsu /* Markers of the _error_inject_whitelist section */
90*663faf9fSMasami Hiramatsu extern struct error_injection_entry __start_error_injection_whitelist[];
91*663faf9fSMasami Hiramatsu extern struct error_injection_entry __stop_error_injection_whitelist[];
92540adea3SMasami Hiramatsu 
93540adea3SMasami Hiramatsu static void __init populate_kernel_ei_list(void)
94540adea3SMasami Hiramatsu {
95540adea3SMasami Hiramatsu 	populate_error_injection_list(__start_error_injection_whitelist,
96540adea3SMasami Hiramatsu 				      __stop_error_injection_whitelist,
97540adea3SMasami Hiramatsu 				      NULL);
98540adea3SMasami Hiramatsu }
99540adea3SMasami Hiramatsu 
100540adea3SMasami Hiramatsu #ifdef CONFIG_MODULES
101540adea3SMasami Hiramatsu static void module_load_ei_list(struct module *mod)
102540adea3SMasami Hiramatsu {
103540adea3SMasami Hiramatsu 	if (!mod->num_ei_funcs)
104540adea3SMasami Hiramatsu 		return;
105540adea3SMasami Hiramatsu 
106540adea3SMasami Hiramatsu 	populate_error_injection_list(mod->ei_funcs,
107540adea3SMasami Hiramatsu 				      mod->ei_funcs + mod->num_ei_funcs, mod);
108540adea3SMasami Hiramatsu }
109540adea3SMasami Hiramatsu 
110540adea3SMasami Hiramatsu static void module_unload_ei_list(struct module *mod)
111540adea3SMasami Hiramatsu {
112540adea3SMasami Hiramatsu 	struct ei_entry *ent, *n;
113540adea3SMasami Hiramatsu 
114540adea3SMasami Hiramatsu 	if (!mod->num_ei_funcs)
115540adea3SMasami Hiramatsu 		return;
116540adea3SMasami Hiramatsu 
117540adea3SMasami Hiramatsu 	mutex_lock(&ei_mutex);
118540adea3SMasami Hiramatsu 	list_for_each_entry_safe(ent, n, &error_injection_list, list) {
119540adea3SMasami Hiramatsu 		if (ent->priv == mod) {
120540adea3SMasami Hiramatsu 			list_del_init(&ent->list);
121540adea3SMasami Hiramatsu 			kfree(ent);
122540adea3SMasami Hiramatsu 		}
123540adea3SMasami Hiramatsu 	}
124540adea3SMasami Hiramatsu 	mutex_unlock(&ei_mutex);
125540adea3SMasami Hiramatsu }
126540adea3SMasami Hiramatsu 
127540adea3SMasami Hiramatsu /* Module notifier call back, checking error injection table on the module */
128540adea3SMasami Hiramatsu static int ei_module_callback(struct notifier_block *nb,
129540adea3SMasami Hiramatsu 			      unsigned long val, void *data)
130540adea3SMasami Hiramatsu {
131540adea3SMasami Hiramatsu 	struct module *mod = data;
132540adea3SMasami Hiramatsu 
133540adea3SMasami Hiramatsu 	if (val == MODULE_STATE_COMING)
134540adea3SMasami Hiramatsu 		module_load_ei_list(mod);
135540adea3SMasami Hiramatsu 	else if (val == MODULE_STATE_GOING)
136540adea3SMasami Hiramatsu 		module_unload_ei_list(mod);
137540adea3SMasami Hiramatsu 
138540adea3SMasami Hiramatsu 	return NOTIFY_DONE;
139540adea3SMasami Hiramatsu }
140540adea3SMasami Hiramatsu 
141540adea3SMasami Hiramatsu static struct notifier_block ei_module_nb = {
142540adea3SMasami Hiramatsu 	.notifier_call = ei_module_callback,
143540adea3SMasami Hiramatsu 	.priority = 0
144540adea3SMasami Hiramatsu };
145540adea3SMasami Hiramatsu 
146540adea3SMasami Hiramatsu static __init int module_ei_init(void)
147540adea3SMasami Hiramatsu {
148540adea3SMasami Hiramatsu 	return register_module_notifier(&ei_module_nb);
149540adea3SMasami Hiramatsu }
150540adea3SMasami Hiramatsu #else /* !CONFIG_MODULES */
151540adea3SMasami Hiramatsu #define module_ei_init()	(0)
152540adea3SMasami Hiramatsu #endif
153540adea3SMasami Hiramatsu 
154540adea3SMasami Hiramatsu /*
155540adea3SMasami Hiramatsu  * error_injection/whitelist -- shows which functions can be overridden for
156540adea3SMasami Hiramatsu  * error injection.
157540adea3SMasami Hiramatsu  */
158540adea3SMasami Hiramatsu static void *ei_seq_start(struct seq_file *m, loff_t *pos)
159540adea3SMasami Hiramatsu {
160540adea3SMasami Hiramatsu 	mutex_lock(&ei_mutex);
161540adea3SMasami Hiramatsu 	return seq_list_start(&error_injection_list, *pos);
162540adea3SMasami Hiramatsu }
163540adea3SMasami Hiramatsu 
164540adea3SMasami Hiramatsu static void ei_seq_stop(struct seq_file *m, void *v)
165540adea3SMasami Hiramatsu {
166540adea3SMasami Hiramatsu 	mutex_unlock(&ei_mutex);
167540adea3SMasami Hiramatsu }
168540adea3SMasami Hiramatsu 
169540adea3SMasami Hiramatsu static void *ei_seq_next(struct seq_file *m, void *v, loff_t *pos)
170540adea3SMasami Hiramatsu {
171540adea3SMasami Hiramatsu 	return seq_list_next(v, &error_injection_list, pos);
172540adea3SMasami Hiramatsu }
173540adea3SMasami Hiramatsu 
174*663faf9fSMasami Hiramatsu static const char *error_type_string(int etype)
175*663faf9fSMasami Hiramatsu {
176*663faf9fSMasami Hiramatsu 	switch (etype) {
177*663faf9fSMasami Hiramatsu 	case EI_ETYPE_NULL:
178*663faf9fSMasami Hiramatsu 		return "NULL";
179*663faf9fSMasami Hiramatsu 	case EI_ETYPE_ERRNO:
180*663faf9fSMasami Hiramatsu 		return "ERRNO";
181*663faf9fSMasami Hiramatsu 	case EI_ETYPE_ERRNO_NULL:
182*663faf9fSMasami Hiramatsu 		return "ERRNO_NULL";
183*663faf9fSMasami Hiramatsu 	default:
184*663faf9fSMasami Hiramatsu 		return "(unknown)";
185*663faf9fSMasami Hiramatsu 	}
186*663faf9fSMasami Hiramatsu }
187*663faf9fSMasami Hiramatsu 
188540adea3SMasami Hiramatsu static int ei_seq_show(struct seq_file *m, void *v)
189540adea3SMasami Hiramatsu {
190540adea3SMasami Hiramatsu 	struct ei_entry *ent = list_entry(v, struct ei_entry, list);
191540adea3SMasami Hiramatsu 
192*663faf9fSMasami Hiramatsu 	seq_printf(m, "%pf\t%s\n", (void *)ent->start_addr,
193*663faf9fSMasami Hiramatsu 		   error_type_string(ent->etype));
194540adea3SMasami Hiramatsu 	return 0;
195540adea3SMasami Hiramatsu }
196540adea3SMasami Hiramatsu 
197540adea3SMasami Hiramatsu static const struct seq_operations ei_seq_ops = {
198540adea3SMasami Hiramatsu 	.start = ei_seq_start,
199540adea3SMasami Hiramatsu 	.next  = ei_seq_next,
200540adea3SMasami Hiramatsu 	.stop  = ei_seq_stop,
201540adea3SMasami Hiramatsu 	.show  = ei_seq_show,
202540adea3SMasami Hiramatsu };
203540adea3SMasami Hiramatsu 
204540adea3SMasami Hiramatsu static int ei_open(struct inode *inode, struct file *filp)
205540adea3SMasami Hiramatsu {
206540adea3SMasami Hiramatsu 	return seq_open(filp, &ei_seq_ops);
207540adea3SMasami Hiramatsu }
208540adea3SMasami Hiramatsu 
209540adea3SMasami Hiramatsu static const struct file_operations debugfs_ei_ops = {
210540adea3SMasami Hiramatsu 	.open           = ei_open,
211540adea3SMasami Hiramatsu 	.read           = seq_read,
212540adea3SMasami Hiramatsu 	.llseek         = seq_lseek,
213540adea3SMasami Hiramatsu 	.release        = seq_release,
214540adea3SMasami Hiramatsu };
215540adea3SMasami Hiramatsu 
216540adea3SMasami Hiramatsu static int __init ei_debugfs_init(void)
217540adea3SMasami Hiramatsu {
218540adea3SMasami Hiramatsu 	struct dentry *dir, *file;
219540adea3SMasami Hiramatsu 
220540adea3SMasami Hiramatsu 	dir = debugfs_create_dir("error_injection", NULL);
221540adea3SMasami Hiramatsu 	if (!dir)
222540adea3SMasami Hiramatsu 		return -ENOMEM;
223540adea3SMasami Hiramatsu 
224540adea3SMasami Hiramatsu 	file = debugfs_create_file("list", 0444, dir, NULL, &debugfs_ei_ops);
225540adea3SMasami Hiramatsu 	if (!file) {
226540adea3SMasami Hiramatsu 		debugfs_remove(dir);
227540adea3SMasami Hiramatsu 		return -ENOMEM;
228540adea3SMasami Hiramatsu 	}
229540adea3SMasami Hiramatsu 
230540adea3SMasami Hiramatsu 	return 0;
231540adea3SMasami Hiramatsu }
232540adea3SMasami Hiramatsu 
233540adea3SMasami Hiramatsu static int __init init_error_injection(void)
234540adea3SMasami Hiramatsu {
235540adea3SMasami Hiramatsu 	populate_kernel_ei_list();
236540adea3SMasami Hiramatsu 
237540adea3SMasami Hiramatsu 	if (!module_ei_init())
238540adea3SMasami Hiramatsu 		ei_debugfs_init();
239540adea3SMasami Hiramatsu 
240540adea3SMasami Hiramatsu 	return 0;
241540adea3SMasami Hiramatsu }
242540adea3SMasami Hiramatsu late_initcall(init_error_injection);
243