0001
0002
0003 #include <linux/btf.h>
0004 #include <linux/btf_ids.h>
0005 #include <linux/error-injection.h>
0006 #include <linux/init.h>
0007 #include <linux/module.h>
0008 #include <linux/percpu-defs.h>
0009 #include <linux/sysfs.h>
0010 #include <linux/tracepoint.h>
0011 #include "bpf_testmod.h"
0012
0013 #define CREATE_TRACE_POINTS
0014 #include "bpf_testmod-events.h"
0015
0016 typedef int (*func_proto_typedef)(long);
0017 typedef int (*func_proto_typedef_nested1)(func_proto_typedef);
0018 typedef int (*func_proto_typedef_nested2)(func_proto_typedef_nested1);
0019
0020 DEFINE_PER_CPU(int, bpf_testmod_ksym_percpu) = 123;
0021
0022 noinline void
0023 bpf_testmod_test_mod_kfunc(int i)
0024 {
0025 *(int *)this_cpu_ptr(&bpf_testmod_ksym_percpu) = i;
0026 }
0027
0028 struct bpf_testmod_btf_type_tag_1 {
0029 int a;
0030 };
0031
0032 struct bpf_testmod_btf_type_tag_2 {
0033 struct bpf_testmod_btf_type_tag_1 __user *p;
0034 };
0035
0036 struct bpf_testmod_btf_type_tag_3 {
0037 struct bpf_testmod_btf_type_tag_1 __percpu *p;
0038 };
0039
0040 noinline int
0041 bpf_testmod_test_btf_type_tag_user_1(struct bpf_testmod_btf_type_tag_1 __user *arg) {
0042 BTF_TYPE_EMIT(func_proto_typedef);
0043 BTF_TYPE_EMIT(func_proto_typedef_nested1);
0044 BTF_TYPE_EMIT(func_proto_typedef_nested2);
0045 return arg->a;
0046 }
0047
0048 noinline int
0049 bpf_testmod_test_btf_type_tag_user_2(struct bpf_testmod_btf_type_tag_2 *arg) {
0050 return arg->p->a;
0051 }
0052
0053 noinline int
0054 bpf_testmod_test_btf_type_tag_percpu_1(struct bpf_testmod_btf_type_tag_1 __percpu *arg) {
0055 return arg->a;
0056 }
0057
0058 noinline int
0059 bpf_testmod_test_btf_type_tag_percpu_2(struct bpf_testmod_btf_type_tag_3 *arg) {
0060 return arg->p->a;
0061 }
0062
0063 noinline int bpf_testmod_loop_test(int n)
0064 {
0065 int i, sum = 0;
0066
0067
0068
0069
0070 for (i = 0; i < n; i++)
0071 sum += i;
0072 return sum;
0073 }
0074
0075 __weak noinline struct file *bpf_testmod_return_ptr(int arg)
0076 {
0077 static struct file f = {};
0078
0079 switch (arg) {
0080 case 1: return (void *)EINVAL;
0081 case 2: return (void *)0xcafe4a11;
0082 case 3: return (void *)-EINVAL;
0083 case 4: return (void *)(1ull << 60);
0084 case 5: return (void *)~(1ull << 30);
0085 case 6: return &f;
0086 case 7: return (void *)((long)&f | 1);
0087 default: return NULL;
0088 }
0089 }
0090
0091 noinline ssize_t
0092 bpf_testmod_test_read(struct file *file, struct kobject *kobj,
0093 struct bin_attribute *bin_attr,
0094 char *buf, loff_t off, size_t len)
0095 {
0096 struct bpf_testmod_test_read_ctx ctx = {
0097 .buf = buf,
0098 .off = off,
0099 .len = len,
0100 };
0101 int i = 1;
0102
0103 while (bpf_testmod_return_ptr(i))
0104 i++;
0105
0106
0107
0108
0109 if (bpf_testmod_loop_test(101) > 100)
0110 trace_bpf_testmod_test_read(current, &ctx);
0111
0112
0113 if (len == 64) {
0114 struct bpf_testmod_test_writable_ctx writable = {
0115 .val = 1024,
0116 };
0117 trace_bpf_testmod_test_writable_bare(&writable);
0118 if (writable.early_ret)
0119 return snprintf(buf, len, "%d\n", writable.val);
0120 }
0121
0122 return -EIO;
0123 }
0124 EXPORT_SYMBOL(bpf_testmod_test_read);
0125 ALLOW_ERROR_INJECTION(bpf_testmod_test_read, ERRNO);
0126
0127 noinline ssize_t
0128 bpf_testmod_test_write(struct file *file, struct kobject *kobj,
0129 struct bin_attribute *bin_attr,
0130 char *buf, loff_t off, size_t len)
0131 {
0132 struct bpf_testmod_test_write_ctx ctx = {
0133 .buf = buf,
0134 .off = off,
0135 .len = len,
0136 };
0137
0138 trace_bpf_testmod_test_write_bare(current, &ctx);
0139
0140 return -EIO;
0141 }
0142 EXPORT_SYMBOL(bpf_testmod_test_write);
0143 ALLOW_ERROR_INJECTION(bpf_testmod_test_write, ERRNO);
0144
0145 static struct bin_attribute bin_attr_bpf_testmod_file __ro_after_init = {
0146 .attr = { .name = "bpf_testmod", .mode = 0666, },
0147 .read = bpf_testmod_test_read,
0148 .write = bpf_testmod_test_write,
0149 };
0150
0151 BTF_SET8_START(bpf_testmod_check_kfunc_ids)
0152 BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
0153 BTF_SET8_END(bpf_testmod_check_kfunc_ids)
0154
0155 static const struct btf_kfunc_id_set bpf_testmod_kfunc_set = {
0156 .owner = THIS_MODULE,
0157 .set = &bpf_testmod_check_kfunc_ids,
0158 };
0159
0160 extern int bpf_fentry_test1(int a);
0161
0162 static int bpf_testmod_init(void)
0163 {
0164 int ret;
0165
0166 ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_testmod_kfunc_set);
0167 if (ret < 0)
0168 return ret;
0169 if (bpf_fentry_test1(0) < 0)
0170 return -EINVAL;
0171 return sysfs_create_bin_file(kernel_kobj, &bin_attr_bpf_testmod_file);
0172 }
0173
0174 static void bpf_testmod_exit(void)
0175 {
0176 return sysfs_remove_bin_file(kernel_kobj, &bin_attr_bpf_testmod_file);
0177 }
0178
0179 module_init(bpf_testmod_init);
0180 module_exit(bpf_testmod_exit);
0181
0182 MODULE_AUTHOR("Andrii Nakryiko");
0183 MODULE_DESCRIPTION("BPF selftests module");
0184 MODULE_LICENSE("Dual BSD/GPL");