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