aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-01-16 22:42:14 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-16 22:42:14 -0500
commit7018d1b3f20fb4308ed9bc577160cb8ffb79b62a (patch)
treeb61a17c694d3cdc3490b190c35104b936bcc6638 /lib
parente7e70fa6784b48a811fdd4253c41fc7195300570 (diff)
parente8a9d9683c8a62f917c19e57f1618363fb9ed04e (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2018-01-17 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Add initial BPF map offloading for nfp driver. Currently only programs were supported so far w/o being able to access maps. Offloaded programs are right now only allowed to perform map lookups, and control path is responsible for populating the maps. BPF core infrastructure along with nfp implementation is provided, from Jakub. 2) Various follow-ups to Josef's BPF error injections. More specifically that includes: properly check whether the error injectable event is on function entry or not, remove the percpu bpf_kprobe_override and rather compare instruction pointer with original one, separate error-injection from kprobes since it's not limited to it, add injectable error types in order to specify what is the expected type of failure, and last but not least also support the kernel's fault injection framework, all from Masami. 3) Various misc improvements and cleanups to the libbpf Makefile. That is, fix permissions when installing BPF header files, remove unused variables and functions, and also install the libbpf.h header, from Jesper. 4) When offloading to nfp JIT and the BPF insn is unsupported in the JIT, then reject right at verification time. Also fix libbpf with regards to ELF section name matching by properly treating the program type as prefix. Both from Quentin. 5) Add -DPACKAGE to bpftool when including bfd.h for the disassembler. This is needed, for example, when building libfd from source as bpftool doesn't supply a config.h for bfd.h. Fix from Jiong. 6) xdp_convert_ctx_access() is simplified since it doesn't need to set target size during verification, from Jesper. 7) Let bpftool properly recognize BPF_PROG_TYPE_CGROUP_DEVICE program types, from Roman. 8) Various functions in BPF cpumap were not declared static, from Wei. 9) Fix a double semicolon in BPF samples, from Luis. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug14
-rw-r--r--lib/Makefile1
-rw-r--r--lib/error-inject.c242
3 files changed, 257 insertions, 0 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 9d5b78aad4c5..890d4766cef3 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1500,6 +1500,10 @@ config FAULT_INJECTION
1500 Provide fault-injection framework. 1500 Provide fault-injection framework.
1501 For more details, see Documentation/fault-injection/. 1501 For more details, see Documentation/fault-injection/.
1502 1502
1503config FUNCTION_ERROR_INJECTION
1504 def_bool y
1505 depends on HAVE_FUNCTION_ERROR_INJECTION && KPROBES
1506
1503config FAILSLAB 1507config FAILSLAB
1504 bool "Fault-injection capability for kmalloc" 1508 bool "Fault-injection capability for kmalloc"
1505 depends on FAULT_INJECTION 1509 depends on FAULT_INJECTION
@@ -1547,6 +1551,16 @@ config FAIL_FUTEX
1547 help 1551 help
1548 Provide fault-injection capability for futexes. 1552 Provide fault-injection capability for futexes.
1549 1553
1554config FAIL_FUNCTION
1555 bool "Fault-injection capability for functions"
1556 depends on FAULT_INJECTION_DEBUG_FS && FUNCTION_ERROR_INJECTION
1557 help
1558 Provide function-based fault-injection capability.
1559 This will allow you to override a specific function with a return
1560 with given return value. As a result, function caller will see
1561 an error value and have to handle it. This is useful to test the
1562 error handling in various subsystems.
1563
1550config FAULT_INJECTION_DEBUG_FS 1564config FAULT_INJECTION_DEBUG_FS
1551 bool "Debugfs entries for fault-injection capabilities" 1565 bool "Debugfs entries for fault-injection capabilities"
1552 depends on FAULT_INJECTION && SYSFS && DEBUG_FS 1566 depends on FAULT_INJECTION && SYSFS && DEBUG_FS
diff --git a/lib/Makefile b/lib/Makefile
index a6c8529dd9b2..75ec13778cd8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_NETDEV_NOTIFIER_ERROR_INJECT) += netdev-notifier-error-inject.o
149obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o 149obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o
150obj-$(CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT) += \ 150obj-$(CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT) += \
151 of-reconfig-notifier-error-inject.o 151 of-reconfig-notifier-error-inject.o
152obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
152 153
153lib-$(CONFIG_GENERIC_BUG) += bug.o 154lib-$(CONFIG_GENERIC_BUG) += bug.o
154 155
diff --git a/lib/error-inject.c b/lib/error-inject.c
new file mode 100644
index 000000000000..c0d4600f4896
--- /dev/null
+++ b/lib/error-inject.c
@@ -0,0 +1,242 @@
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
12/* Whitelist of symbols that can be overridden for error injection. */
13static LIST_HEAD(error_injection_list);
14static DEFINE_MUTEX(ei_mutex);
15struct ei_entry {
16 struct list_head list;
17 unsigned long start_addr;
18 unsigned long end_addr;
19 int etype;
20 void *priv;
21};
22
23bool within_error_injection_list(unsigned long addr)
24{
25 struct ei_entry *ent;
26 bool ret = false;
27
28 mutex_lock(&ei_mutex);
29 list_for_each_entry(ent, &error_injection_list, list) {
30 if (addr >= ent->start_addr && addr < ent->end_addr) {
31 ret = true;
32 break;
33 }
34 }
35 mutex_unlock(&ei_mutex);
36 return ret;
37}
38
39int get_injectable_error_type(unsigned long addr)
40{
41 struct ei_entry *ent;
42
43 list_for_each_entry(ent, &error_injection_list, list) {
44 if (addr >= ent->start_addr && addr < ent->end_addr)
45 return ent->etype;
46 }
47 return EI_ETYPE_NONE;
48}
49
50/*
51 * Lookup and populate the error_injection_list.
52 *
53 * For safety reasons we only allow certain functions to be overridden with
54 * bpf_error_injection, so we need to populate the list of the symbols that have
55 * been marked as safe for overriding.
56 */
57static void populate_error_injection_list(struct error_injection_entry *start,
58 struct error_injection_entry *end,
59 void *priv)
60{
61 struct error_injection_entry *iter;
62 struct ei_entry *ent;
63 unsigned long entry, offset = 0, size = 0;
64
65 mutex_lock(&ei_mutex);
66 for (iter = start; iter < end; iter++) {
67 entry = arch_deref_entry_point((void *)iter->addr);
68
69 if (!kernel_text_address(entry) ||
70 !kallsyms_lookup_size_offset(entry, &size, &offset)) {
71 pr_err("Failed to find error inject entry at %p\n",
72 (void *)entry);
73 continue;
74 }
75
76 ent = kmalloc(sizeof(*ent), GFP_KERNEL);
77 if (!ent)
78 break;
79 ent->start_addr = entry;
80 ent->end_addr = entry + size;
81 ent->etype = iter->etype;
82 ent->priv = priv;
83 INIT_LIST_HEAD(&ent->list);
84 list_add_tail(&ent->list, &error_injection_list);
85 }
86 mutex_unlock(&ei_mutex);
87}
88
89/* Markers of the _error_inject_whitelist section */
90extern struct error_injection_entry __start_error_injection_whitelist[];
91extern struct error_injection_entry __stop_error_injection_whitelist[];
92
93static void __init populate_kernel_ei_list(void)
94{
95 populate_error_injection_list(__start_error_injection_whitelist,
96 __stop_error_injection_whitelist,
97 NULL);
98}
99
100#ifdef CONFIG_MODULES
101static void module_load_ei_list(struct module *mod)
102{
103 if (!mod->num_ei_funcs)
104 return;
105
106 populate_error_injection_list(mod->ei_funcs,
107 mod->ei_funcs + mod->num_ei_funcs, mod);
108}
109
110static void module_unload_ei_list(struct module *mod)
111{
112 struct ei_entry *ent, *n;
113
114 if (!mod->num_ei_funcs)
115 return;
116
117 mutex_lock(&ei_mutex);
118 list_for_each_entry_safe(ent, n, &error_injection_list, list) {
119 if (ent->priv == mod) {
120 list_del_init(&ent->list);
121 kfree(ent);
122 }
123 }
124 mutex_unlock(&ei_mutex);
125}
126
127/* Module notifier call back, checking error injection table on the module */
128static int ei_module_callback(struct notifier_block *nb,
129 unsigned long val, void *data)
130{
131 struct module *mod = data;
132
133 if (val == MODULE_STATE_COMING)
134 module_load_ei_list(mod);
135 else if (val == MODULE_STATE_GOING)
136 module_unload_ei_list(mod);
137
138 return NOTIFY_DONE;
139}
140
141static struct notifier_block ei_module_nb = {
142 .notifier_call = ei_module_callback,
143 .priority = 0
144};
145
146static __init int module_ei_init(void)
147{
148 return register_module_notifier(&ei_module_nb);
149}
150#else /* !CONFIG_MODULES */
151#define module_ei_init() (0)
152#endif
153
154/*
155 * error_injection/whitelist -- shows which functions can be overridden for
156 * error injection.
157 */
158static void *ei_seq_start(struct seq_file *m, loff_t *pos)
159{
160 mutex_lock(&ei_mutex);
161 return seq_list_start(&error_injection_list, *pos);
162}
163
164static void ei_seq_stop(struct seq_file *m, void *v)
165{
166 mutex_unlock(&ei_mutex);
167}
168
169static void *ei_seq_next(struct seq_file *m, void *v, loff_t *pos)
170{
171 return seq_list_next(v, &error_injection_list, pos);
172}
173
174static const char *error_type_string(int etype)
175{
176 switch (etype) {
177 case EI_ETYPE_NULL:
178 return "NULL";
179 case EI_ETYPE_ERRNO:
180 return "ERRNO";
181 case EI_ETYPE_ERRNO_NULL:
182 return "ERRNO_NULL";
183 default:
184 return "(unknown)";
185 }
186}
187
188static int ei_seq_show(struct seq_file *m, void *v)
189{
190 struct ei_entry *ent = list_entry(v, struct ei_entry, list);
191
192 seq_printf(m, "%pf\t%s\n", (void *)ent->start_addr,
193 error_type_string(ent->etype));
194 return 0;
195}
196
197static const struct seq_operations ei_seq_ops = {
198 .start = ei_seq_start,
199 .next = ei_seq_next,
200 .stop = ei_seq_stop,
201 .show = ei_seq_show,
202};
203
204static int ei_open(struct inode *inode, struct file *filp)
205{
206 return seq_open(filp, &ei_seq_ops);
207}
208
209static const struct file_operations debugfs_ei_ops = {
210 .open = ei_open,
211 .read = seq_read,
212 .llseek = seq_lseek,
213 .release = seq_release,
214};
215
216static int __init ei_debugfs_init(void)
217{
218 struct dentry *dir, *file;
219
220 dir = debugfs_create_dir("error_injection", NULL);
221 if (!dir)
222 return -ENOMEM;
223
224 file = debugfs_create_file("list", 0444, dir, NULL, &debugfs_ei_ops);
225 if (!file) {
226 debugfs_remove(dir);
227 return -ENOMEM;
228 }
229
230 return 0;
231}
232
233static int __init init_error_injection(void)
234{
235 populate_kernel_ei_list();
236
237 if (!module_ei_init())
238 ei_debugfs_init();
239
240 return 0;
241}
242late_initcall(init_error_injection);