Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020 Facebook */
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     /* the primary goal of this test is to test LBR. Create a lot of
0068      * branches in the function, so we can catch it easily.
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;      /* user addr */
0081     case 2: return (void *)0xcafe4a11;  /* user addr */
0082     case 3: return (void *)-EINVAL;     /* canonical, but invalid */
0083     case 4: return (void *)(1ull << 60);    /* non-canonical and invalid */
0084     case 5: return (void *)~(1ull << 30);   /* trigger extable */
0085     case 6: return &f;          /* valid addr */
0086     case 7: return (void *)((long)&f | 1);  /* kernel tricks */
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     /* This is always true. Use the check to make sure the compiler
0107      * doesn't remove bpf_testmod_loop_test.
0108      */
0109     if (bpf_testmod_loop_test(101) > 100)
0110         trace_bpf_testmod_test_read(current, &ctx);
0111 
0112     /* Magic number to enable writable tp */
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; /* always fail */
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; /* always fail */
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");