0001
0002
0003 #include <linux/error-injection.h>
0004 #include <linux/debugfs.h>
0005 #include <linux/kallsyms.h>
0006 #include <linux/kprobes.h>
0007 #include <linux/module.h>
0008 #include <linux/mutex.h>
0009 #include <linux/list.h>
0010 #include <linux/slab.h>
0011 #include <asm/sections.h>
0012
0013
0014 static LIST_HEAD(error_injection_list);
0015 static DEFINE_MUTEX(ei_mutex);
0016 struct ei_entry {
0017 struct list_head list;
0018 unsigned long start_addr;
0019 unsigned long end_addr;
0020 int etype;
0021 void *priv;
0022 };
0023
0024 bool within_error_injection_list(unsigned long addr)
0025 {
0026 struct ei_entry *ent;
0027 bool ret = false;
0028
0029 mutex_lock(&ei_mutex);
0030 list_for_each_entry(ent, &error_injection_list, list) {
0031 if (addr >= ent->start_addr && addr < ent->end_addr) {
0032 ret = true;
0033 break;
0034 }
0035 }
0036 mutex_unlock(&ei_mutex);
0037 return ret;
0038 }
0039
0040 int get_injectable_error_type(unsigned long addr)
0041 {
0042 struct ei_entry *ent;
0043 int ei_type = EI_ETYPE_NONE;
0044
0045 mutex_lock(&ei_mutex);
0046 list_for_each_entry(ent, &error_injection_list, list) {
0047 if (addr >= ent->start_addr && addr < ent->end_addr) {
0048 ei_type = ent->etype;
0049 break;
0050 }
0051 }
0052 mutex_unlock(&ei_mutex);
0053
0054 return ei_type;
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064 static void populate_error_injection_list(struct error_injection_entry *start,
0065 struct error_injection_entry *end,
0066 void *priv)
0067 {
0068 struct error_injection_entry *iter;
0069 struct ei_entry *ent;
0070 unsigned long entry, offset = 0, size = 0;
0071
0072 mutex_lock(&ei_mutex);
0073 for (iter = start; iter < end; iter++) {
0074 entry = (unsigned long)dereference_symbol_descriptor((void *)iter->addr);
0075
0076 if (!kernel_text_address(entry) ||
0077 !kallsyms_lookup_size_offset(entry, &size, &offset)) {
0078 pr_err("Failed to find error inject entry at %p\n",
0079 (void *)entry);
0080 continue;
0081 }
0082
0083 ent = kmalloc(sizeof(*ent), GFP_KERNEL);
0084 if (!ent)
0085 break;
0086 ent->start_addr = entry;
0087 ent->end_addr = entry + size;
0088 ent->etype = iter->etype;
0089 ent->priv = priv;
0090 INIT_LIST_HEAD(&ent->list);
0091 list_add_tail(&ent->list, &error_injection_list);
0092 }
0093 mutex_unlock(&ei_mutex);
0094 }
0095
0096
0097 extern struct error_injection_entry __start_error_injection_whitelist[];
0098 extern struct error_injection_entry __stop_error_injection_whitelist[];
0099
0100 static void __init populate_kernel_ei_list(void)
0101 {
0102 populate_error_injection_list(__start_error_injection_whitelist,
0103 __stop_error_injection_whitelist,
0104 NULL);
0105 }
0106
0107 #ifdef CONFIG_MODULES
0108 static void module_load_ei_list(struct module *mod)
0109 {
0110 if (!mod->num_ei_funcs)
0111 return;
0112
0113 populate_error_injection_list(mod->ei_funcs,
0114 mod->ei_funcs + mod->num_ei_funcs, mod);
0115 }
0116
0117 static void module_unload_ei_list(struct module *mod)
0118 {
0119 struct ei_entry *ent, *n;
0120
0121 if (!mod->num_ei_funcs)
0122 return;
0123
0124 mutex_lock(&ei_mutex);
0125 list_for_each_entry_safe(ent, n, &error_injection_list, list) {
0126 if (ent->priv == mod) {
0127 list_del_init(&ent->list);
0128 kfree(ent);
0129 }
0130 }
0131 mutex_unlock(&ei_mutex);
0132 }
0133
0134
0135 static int ei_module_callback(struct notifier_block *nb,
0136 unsigned long val, void *data)
0137 {
0138 struct module *mod = data;
0139
0140 if (val == MODULE_STATE_COMING)
0141 module_load_ei_list(mod);
0142 else if (val == MODULE_STATE_GOING)
0143 module_unload_ei_list(mod);
0144
0145 return NOTIFY_DONE;
0146 }
0147
0148 static struct notifier_block ei_module_nb = {
0149 .notifier_call = ei_module_callback,
0150 .priority = 0
0151 };
0152
0153 static __init int module_ei_init(void)
0154 {
0155 return register_module_notifier(&ei_module_nb);
0156 }
0157 #else
0158 #define module_ei_init() (0)
0159 #endif
0160
0161
0162
0163
0164
0165 static void *ei_seq_start(struct seq_file *m, loff_t *pos)
0166 {
0167 mutex_lock(&ei_mutex);
0168 return seq_list_start(&error_injection_list, *pos);
0169 }
0170
0171 static void ei_seq_stop(struct seq_file *m, void *v)
0172 {
0173 mutex_unlock(&ei_mutex);
0174 }
0175
0176 static void *ei_seq_next(struct seq_file *m, void *v, loff_t *pos)
0177 {
0178 return seq_list_next(v, &error_injection_list, pos);
0179 }
0180
0181 static const char *error_type_string(int etype)
0182 {
0183 switch (etype) {
0184 case EI_ETYPE_NULL:
0185 return "NULL";
0186 case EI_ETYPE_ERRNO:
0187 return "ERRNO";
0188 case EI_ETYPE_ERRNO_NULL:
0189 return "ERRNO_NULL";
0190 case EI_ETYPE_TRUE:
0191 return "TRUE";
0192 default:
0193 return "(unknown)";
0194 }
0195 }
0196
0197 static int ei_seq_show(struct seq_file *m, void *v)
0198 {
0199 struct ei_entry *ent = list_entry(v, struct ei_entry, list);
0200
0201 seq_printf(m, "%ps\t%s\n", (void *)ent->start_addr,
0202 error_type_string(ent->etype));
0203 return 0;
0204 }
0205
0206 static const struct seq_operations ei_sops = {
0207 .start = ei_seq_start,
0208 .next = ei_seq_next,
0209 .stop = ei_seq_stop,
0210 .show = ei_seq_show,
0211 };
0212
0213 DEFINE_SEQ_ATTRIBUTE(ei);
0214
0215 static int __init ei_debugfs_init(void)
0216 {
0217 struct dentry *dir, *file;
0218
0219 dir = debugfs_create_dir("error_injection", NULL);
0220 if (!dir)
0221 return -ENOMEM;
0222
0223 file = debugfs_create_file("list", 0444, dir, NULL, &ei_fops);
0224 if (!file) {
0225 debugfs_remove(dir);
0226 return -ENOMEM;
0227 }
0228
0229 return 0;
0230 }
0231
0232 static int __init init_error_injection(void)
0233 {
0234 populate_kernel_ei_list();
0235
0236 if (!module_ei_init())
0237 ei_debugfs_init();
0238
0239 return 0;
0240 }
0241 late_initcall(init_error_injection);