1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // error-inject.c: Function-level error injection table
3*4882a593Smuzhiyun #include <linux/error-injection.h>
4*4882a593Smuzhiyun #include <linux/debugfs.h>
5*4882a593Smuzhiyun #include <linux/kallsyms.h>
6*4882a593Smuzhiyun #include <linux/kprobes.h>
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/mutex.h>
9*4882a593Smuzhiyun #include <linux/list.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun /* Whitelist of symbols that can be overridden for error injection. */
13*4882a593Smuzhiyun static LIST_HEAD(error_injection_list);
14*4882a593Smuzhiyun static DEFINE_MUTEX(ei_mutex);
15*4882a593Smuzhiyun struct ei_entry {
16*4882a593Smuzhiyun struct list_head list;
17*4882a593Smuzhiyun unsigned long start_addr;
18*4882a593Smuzhiyun unsigned long end_addr;
19*4882a593Smuzhiyun int etype;
20*4882a593Smuzhiyun void *priv;
21*4882a593Smuzhiyun };
22*4882a593Smuzhiyun
within_error_injection_list(unsigned long addr)23*4882a593Smuzhiyun bool within_error_injection_list(unsigned long addr)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun struct ei_entry *ent;
26*4882a593Smuzhiyun bool ret = false;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun mutex_lock(&ei_mutex);
29*4882a593Smuzhiyun list_for_each_entry(ent, &error_injection_list, list) {
30*4882a593Smuzhiyun if (addr >= ent->start_addr && addr < ent->end_addr) {
31*4882a593Smuzhiyun ret = true;
32*4882a593Smuzhiyun break;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun mutex_unlock(&ei_mutex);
36*4882a593Smuzhiyun return ret;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
get_injectable_error_type(unsigned long addr)39*4882a593Smuzhiyun int get_injectable_error_type(unsigned long addr)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun struct ei_entry *ent;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun list_for_each_entry(ent, &error_injection_list, list) {
44*4882a593Smuzhiyun if (addr >= ent->start_addr && addr < ent->end_addr)
45*4882a593Smuzhiyun return ent->etype;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun return EI_ETYPE_NONE;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * Lookup and populate the error_injection_list.
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * For safety reasons we only allow certain functions to be overridden with
54*4882a593Smuzhiyun * bpf_error_injection, so we need to populate the list of the symbols that have
55*4882a593Smuzhiyun * been marked as safe for overriding.
56*4882a593Smuzhiyun */
populate_error_injection_list(struct error_injection_entry * start,struct error_injection_entry * end,void * priv)57*4882a593Smuzhiyun static void populate_error_injection_list(struct error_injection_entry *start,
58*4882a593Smuzhiyun struct error_injection_entry *end,
59*4882a593Smuzhiyun void *priv)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun struct error_injection_entry *iter;
62*4882a593Smuzhiyun struct ei_entry *ent;
63*4882a593Smuzhiyun unsigned long entry, offset = 0, size = 0;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun mutex_lock(&ei_mutex);
66*4882a593Smuzhiyun for (iter = start; iter < end; iter++) {
67*4882a593Smuzhiyun entry = arch_deref_entry_point((void *)iter->addr);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (!kernel_text_address(entry) ||
70*4882a593Smuzhiyun !kallsyms_lookup_size_offset(entry, &size, &offset)) {
71*4882a593Smuzhiyun pr_err("Failed to find error inject entry at %p\n",
72*4882a593Smuzhiyun (void *)entry);
73*4882a593Smuzhiyun continue;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun ent = kmalloc(sizeof(*ent), GFP_KERNEL);
77*4882a593Smuzhiyun if (!ent)
78*4882a593Smuzhiyun break;
79*4882a593Smuzhiyun ent->start_addr = entry;
80*4882a593Smuzhiyun ent->end_addr = entry + size;
81*4882a593Smuzhiyun ent->etype = iter->etype;
82*4882a593Smuzhiyun ent->priv = priv;
83*4882a593Smuzhiyun INIT_LIST_HEAD(&ent->list);
84*4882a593Smuzhiyun list_add_tail(&ent->list, &error_injection_list);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun mutex_unlock(&ei_mutex);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* Markers of the _error_inject_whitelist section */
90*4882a593Smuzhiyun extern struct error_injection_entry __start_error_injection_whitelist[];
91*4882a593Smuzhiyun extern struct error_injection_entry __stop_error_injection_whitelist[];
92*4882a593Smuzhiyun
populate_kernel_ei_list(void)93*4882a593Smuzhiyun static void __init populate_kernel_ei_list(void)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun populate_error_injection_list(__start_error_injection_whitelist,
96*4882a593Smuzhiyun __stop_error_injection_whitelist,
97*4882a593Smuzhiyun NULL);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun #ifdef CONFIG_MODULES
module_load_ei_list(struct module * mod)101*4882a593Smuzhiyun static void module_load_ei_list(struct module *mod)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun if (!mod->num_ei_funcs)
104*4882a593Smuzhiyun return;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun populate_error_injection_list(mod->ei_funcs,
107*4882a593Smuzhiyun mod->ei_funcs + mod->num_ei_funcs, mod);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
module_unload_ei_list(struct module * mod)110*4882a593Smuzhiyun static void module_unload_ei_list(struct module *mod)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun struct ei_entry *ent, *n;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (!mod->num_ei_funcs)
115*4882a593Smuzhiyun return;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun mutex_lock(&ei_mutex);
118*4882a593Smuzhiyun list_for_each_entry_safe(ent, n, &error_injection_list, list) {
119*4882a593Smuzhiyun if (ent->priv == mod) {
120*4882a593Smuzhiyun list_del_init(&ent->list);
121*4882a593Smuzhiyun kfree(ent);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun mutex_unlock(&ei_mutex);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* Module notifier call back, checking error injection table on the module */
ei_module_callback(struct notifier_block * nb,unsigned long val,void * data)128*4882a593Smuzhiyun static int ei_module_callback(struct notifier_block *nb,
129*4882a593Smuzhiyun unsigned long val, void *data)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct module *mod = data;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (val == MODULE_STATE_COMING)
134*4882a593Smuzhiyun module_load_ei_list(mod);
135*4882a593Smuzhiyun else if (val == MODULE_STATE_GOING)
136*4882a593Smuzhiyun module_unload_ei_list(mod);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return NOTIFY_DONE;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun static struct notifier_block ei_module_nb = {
142*4882a593Smuzhiyun .notifier_call = ei_module_callback,
143*4882a593Smuzhiyun .priority = 0
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
module_ei_init(void)146*4882a593Smuzhiyun static __init int module_ei_init(void)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun return register_module_notifier(&ei_module_nb);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun #else /* !CONFIG_MODULES */
151*4882a593Smuzhiyun #define module_ei_init() (0)
152*4882a593Smuzhiyun #endif
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun * error_injection/whitelist -- shows which functions can be overridden for
156*4882a593Smuzhiyun * error injection.
157*4882a593Smuzhiyun */
ei_seq_start(struct seq_file * m,loff_t * pos)158*4882a593Smuzhiyun static void *ei_seq_start(struct seq_file *m, loff_t *pos)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun mutex_lock(&ei_mutex);
161*4882a593Smuzhiyun return seq_list_start(&error_injection_list, *pos);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
ei_seq_stop(struct seq_file * m,void * v)164*4882a593Smuzhiyun static void ei_seq_stop(struct seq_file *m, void *v)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun mutex_unlock(&ei_mutex);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
ei_seq_next(struct seq_file * m,void * v,loff_t * pos)169*4882a593Smuzhiyun static void *ei_seq_next(struct seq_file *m, void *v, loff_t *pos)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun return seq_list_next(v, &error_injection_list, pos);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
error_type_string(int etype)174*4882a593Smuzhiyun static const char *error_type_string(int etype)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun switch (etype) {
177*4882a593Smuzhiyun case EI_ETYPE_NULL:
178*4882a593Smuzhiyun return "NULL";
179*4882a593Smuzhiyun case EI_ETYPE_ERRNO:
180*4882a593Smuzhiyun return "ERRNO";
181*4882a593Smuzhiyun case EI_ETYPE_ERRNO_NULL:
182*4882a593Smuzhiyun return "ERRNO_NULL";
183*4882a593Smuzhiyun default:
184*4882a593Smuzhiyun return "(unknown)";
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
ei_seq_show(struct seq_file * m,void * v)188*4882a593Smuzhiyun static int ei_seq_show(struct seq_file *m, void *v)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun struct ei_entry *ent = list_entry(v, struct ei_entry, list);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun seq_printf(m, "%ps\t%s\n", (void *)ent->start_addr,
193*4882a593Smuzhiyun error_type_string(ent->etype));
194*4882a593Smuzhiyun return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun static const struct seq_operations ei_seq_ops = {
198*4882a593Smuzhiyun .start = ei_seq_start,
199*4882a593Smuzhiyun .next = ei_seq_next,
200*4882a593Smuzhiyun .stop = ei_seq_stop,
201*4882a593Smuzhiyun .show = ei_seq_show,
202*4882a593Smuzhiyun };
203*4882a593Smuzhiyun
ei_open(struct inode * inode,struct file * filp)204*4882a593Smuzhiyun static int ei_open(struct inode *inode, struct file *filp)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun return seq_open(filp, &ei_seq_ops);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun static const struct file_operations debugfs_ei_ops = {
210*4882a593Smuzhiyun .open = ei_open,
211*4882a593Smuzhiyun .read = seq_read,
212*4882a593Smuzhiyun .llseek = seq_lseek,
213*4882a593Smuzhiyun .release = seq_release,
214*4882a593Smuzhiyun };
215*4882a593Smuzhiyun
ei_debugfs_init(void)216*4882a593Smuzhiyun static int __init ei_debugfs_init(void)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun struct dentry *dir, *file;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun dir = debugfs_create_dir("error_injection", NULL);
221*4882a593Smuzhiyun if (!dir)
222*4882a593Smuzhiyun return -ENOMEM;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun file = debugfs_create_file("list", 0444, dir, NULL, &debugfs_ei_ops);
225*4882a593Smuzhiyun if (!file) {
226*4882a593Smuzhiyun debugfs_remove(dir);
227*4882a593Smuzhiyun return -ENOMEM;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return 0;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
init_error_injection(void)233*4882a593Smuzhiyun static int __init init_error_injection(void)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun populate_kernel_ei_list();
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (!module_ei_init())
238*4882a593Smuzhiyun ei_debugfs_init();
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun return 0;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun late_initcall(init_error_injection);
243