aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/test_btf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/bpf/test_btf.c')
-rw-r--r--tools/testing/selftests/bpf/test_btf.c332
1 files changed, 329 insertions, 3 deletions
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index e0eeee5c8c04..8fd3a16fea4d 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5,6 +5,7 @@
5#include <linux/btf.h> 5#include <linux/btf.h>
6#include <linux/err.h> 6#include <linux/err.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/filter.h>
8#include <bpf/bpf.h> 9#include <bpf/bpf.h>
9#include <sys/resource.h> 10#include <sys/resource.h>
10#include <libelf.h> 11#include <libelf.h>
@@ -22,9 +23,13 @@
22#include "bpf_rlimit.h" 23#include "bpf_rlimit.h"
23#include "bpf_util.h" 24#include "bpf_util.h"
24 25
26#define MAX_INSNS 512
27#define MAX_SUBPROGS 16
28
25static uint32_t pass_cnt; 29static uint32_t pass_cnt;
26static uint32_t error_cnt; 30static uint32_t error_cnt;
27static uint32_t skip_cnt; 31static uint32_t skip_cnt;
32static bool jit_enabled;
28 33
29#define CHECK(condition, format...) ({ \ 34#define CHECK(condition, format...) ({ \
30 int __ret = !!(condition); \ 35 int __ret = !!(condition); \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
60 return err; 65 return err;
61} 66}
62 67
68static bool is_jit_enabled(void)
69{
70 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
71 bool enabled = false;
72 int sysctl_fd;
73
74 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
75 if (sysctl_fd != -1) {
76 char tmpc;
77
78 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
79 enabled = (tmpc != '0');
80 close(sysctl_fd);
81 }
82
83 return enabled;
84}
85
63#define BTF_INFO_ENC(kind, root, vlen) \ 86#define BTF_INFO_ENC(kind, root, vlen) \
64 ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) 87 ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
65 88
@@ -115,6 +138,7 @@ static struct args {
115 bool get_info_test; 138 bool get_info_test;
116 bool pprint_test; 139 bool pprint_test;
117 bool always_log; 140 bool always_log;
141 bool func_type_test;
118} args; 142} args;
119 143
120static char btf_log_buf[BTF_LOG_BUF_SIZE]; 144static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -2947,16 +2971,310 @@ static int test_pprint(void)
2947 return err; 2971 return err;
2948} 2972}
2949 2973
2974static struct btf_func_type_test {
2975 const char *descr;
2976 const char *str_sec;
2977 __u32 raw_types[MAX_NR_RAW_TYPES];
2978 __u32 str_sec_size;
2979 struct bpf_insn insns[MAX_INSNS];
2980 __u32 prog_type;
2981 __u32 func_info[MAX_SUBPROGS][2];
2982 __u32 func_info_rec_size;
2983 __u32 func_info_cnt;
2984 bool expected_prog_load_failure;
2985} func_type_test[] = {
2986{
2987 .descr = "func_type (main func + one sub)",
2988 .raw_types = {
2989 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
2990 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
2991 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
2992 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
2993 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
2994 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
2995 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
2996 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
2997 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
2998 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
2999 BTF_END_RAW,
3000 },
3001 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3002 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3003 .insns = {
3004 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3005 BPF_MOV64_IMM(BPF_REG_0, 1),
3006 BPF_EXIT_INSN(),
3007 BPF_MOV64_IMM(BPF_REG_0, 2),
3008 BPF_EXIT_INSN(),
3009 },
3010 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3011 .func_info = { {0, 5}, {3, 6} },
3012 .func_info_rec_size = 8,
3013 .func_info_cnt = 2,
3014},
3015
3016{
3017 .descr = "func_type (Incorrect func_info_rec_size)",
3018 .raw_types = {
3019 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3020 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3021 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3022 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3023 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3024 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3025 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3026 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3027 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3028 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3029 BTF_END_RAW,
3030 },
3031 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3032 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3033 .insns = {
3034 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3035 BPF_MOV64_IMM(BPF_REG_0, 1),
3036 BPF_EXIT_INSN(),
3037 BPF_MOV64_IMM(BPF_REG_0, 2),
3038 BPF_EXIT_INSN(),
3039 },
3040 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3041 .func_info = { {0, 5}, {3, 6} },
3042 .func_info_rec_size = 4,
3043 .func_info_cnt = 2,
3044 .expected_prog_load_failure = true,
3045},
3046
3047{
3048 .descr = "func_type (Incorrect func_info_cnt)",
3049 .raw_types = {
3050 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3051 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3052 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3053 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3054 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3055 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3056 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3057 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3058 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3059 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3060 BTF_END_RAW,
3061 },
3062 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3063 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3064 .insns = {
3065 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3066 BPF_MOV64_IMM(BPF_REG_0, 1),
3067 BPF_EXIT_INSN(),
3068 BPF_MOV64_IMM(BPF_REG_0, 2),
3069 BPF_EXIT_INSN(),
3070 },
3071 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3072 .func_info = { {0, 5}, {3, 6} },
3073 .func_info_rec_size = 8,
3074 .func_info_cnt = 1,
3075 .expected_prog_load_failure = true,
3076},
3077
3078{
3079 .descr = "func_type (Incorrect bpf_func_info.insn_offset)",
3080 .raw_types = {
3081 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3082 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3083 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3084 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3085 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3086 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3087 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3088 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3089 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3090 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3091 BTF_END_RAW,
3092 },
3093 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3094 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3095 .insns = {
3096 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3097 BPF_MOV64_IMM(BPF_REG_0, 1),
3098 BPF_EXIT_INSN(),
3099 BPF_MOV64_IMM(BPF_REG_0, 2),
3100 BPF_EXIT_INSN(),
3101 },
3102 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3103 .func_info = { {0, 5}, {2, 6} },
3104 .func_info_rec_size = 8,
3105 .func_info_cnt = 2,
3106 .expected_prog_load_failure = true,
3107},
3108
3109};
3110
3111static size_t probe_prog_length(const struct bpf_insn *fp)
3112{
3113 size_t len;
3114
3115 for (len = MAX_INSNS - 1; len > 0; --len)
3116 if (fp[len].code != 0 || fp[len].imm != 0)
3117 break;
3118 return len + 1;
3119}
3120
3121static int do_test_func_type(int test_num)
3122{
3123 const struct btf_func_type_test *test = &func_type_test[test_num];
3124 unsigned int raw_btf_size, info_len, rec_size;
3125 int i, btf_fd = -1, prog_fd = -1, err = 0;
3126 struct bpf_load_program_attr attr = {};
3127 void *raw_btf, *func_info = NULL;
3128 struct bpf_prog_info info = {};
3129 struct bpf_func_info *finfo;
3130
3131 fprintf(stderr, "%s......", test->descr);
3132 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
3133 test->str_sec, test->str_sec_size,
3134 &raw_btf_size);
3135
3136 if (!raw_btf)
3137 return -1;
3138
3139 *btf_log_buf = '\0';
3140 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
3141 btf_log_buf, BTF_LOG_BUF_SIZE,
3142 args.always_log);
3143 free(raw_btf);
3144
3145 if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
3146 err = -1;
3147 goto done;
3148 }
3149
3150 if (*btf_log_buf && args.always_log)
3151 fprintf(stderr, "\n%s", btf_log_buf);
3152
3153 attr.prog_type = test->prog_type;
3154 attr.insns = test->insns;
3155 attr.insns_cnt = probe_prog_length(attr.insns);
3156 attr.license = "GPL";
3157 attr.prog_btf_fd = btf_fd;
3158 attr.func_info_rec_size = test->func_info_rec_size;
3159 attr.func_info_cnt = test->func_info_cnt;
3160 attr.func_info = test->func_info;
3161
3162 *btf_log_buf = '\0';
3163 prog_fd = bpf_load_program_xattr(&attr, btf_log_buf,
3164 BTF_LOG_BUF_SIZE);
3165 if (test->expected_prog_load_failure && prog_fd == -1) {
3166 err = 0;
3167 goto done;
3168 }
3169 if (CHECK(prog_fd == -1, "invalid prog_id errno:%d", errno)) {
3170 fprintf(stderr, "%s\n", btf_log_buf);
3171 err = -1;
3172 goto done;
3173 }
3174 if (!jit_enabled) {
3175 skip_cnt++;
3176 fprintf(stderr, "SKIPPED, please enable sysctl bpf_jit_enable\n");
3177 err = 0;
3178 goto done;
3179 }
3180
3181 /* get necessary lens */
3182 info_len = sizeof(struct bpf_prog_info);
3183 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3184 if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
3185 fprintf(stderr, "%s\n", btf_log_buf);
3186 err = -1;
3187 goto done;
3188 }
3189 if (CHECK(info.func_info_cnt != 2,
3190 "incorrect info.func_info_cnt (1st) %d\n",
3191 info.func_info_cnt)) {
3192 err = -1;
3193 goto done;
3194 }
3195 rec_size = info.func_info_rec_size;
3196 if (CHECK(rec_size < 4,
3197 "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
3198 err = -1;
3199 goto done;
3200 }
3201
3202 func_info = malloc(info.func_info_cnt * rec_size);
3203 if (CHECK(!func_info, "out of memeory")) {
3204 err = -1;
3205 goto done;
3206 }
3207
3208 /* reset info to only retrieve func_info related data */
3209 memset(&info, 0, sizeof(info));
3210 info.func_info_cnt = 2;
3211 info.func_info_rec_size = rec_size;
3212 info.func_info = ptr_to_u64(func_info);
3213 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3214 if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
3215 fprintf(stderr, "%s\n", btf_log_buf);
3216 err = -1;
3217 goto done;
3218 }
3219 if (CHECK(info.func_info_cnt != 2,
3220 "incorrect info.func_info_cnt (2nd) %d\n",
3221 info.func_info_cnt)) {
3222 err = -1;
3223 goto done;
3224 }
3225 if (CHECK(info.func_info_rec_size != rec_size,
3226 "incorrect info.func_info_rec_size (2nd) %d\n",
3227 info.func_info_rec_size)) {
3228 err = -1;
3229 goto done;
3230 }
3231
3232 finfo = func_info;
3233 for (i = 0; i < 2; i++) {
3234 if (CHECK(finfo->type_id != test->func_info[i][1],
3235 "incorrect func_type %u expected %u",
3236 finfo->type_id, test->func_info[i][1])) {
3237 err = -1;
3238 goto done;
3239 }
3240 finfo = (void *)finfo + rec_size;
3241 }
3242
3243done:
3244 if (*btf_log_buf && (err || args.always_log))
3245 fprintf(stderr, "\n%s", btf_log_buf);
3246
3247 if (btf_fd != -1)
3248 close(btf_fd);
3249 if (prog_fd != -1)
3250 close(prog_fd);
3251 free(func_info);
3252 return err;
3253}
3254
3255static int test_func_type(void)
3256{
3257 unsigned int i;
3258 int err = 0;
3259
3260 for (i = 0; i < ARRAY_SIZE(func_type_test); i++)
3261 err |= count_result(do_test_func_type(i));
3262
3263 return err;
3264}
3265
2950static void usage(const char *cmd) 3266static void usage(const char *cmd)
2951{ 3267{
2952 fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] | [-g test_num (1 - %zu)] | [-f test_num (1 - %zu)] | [-p]]\n", 3268 fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] |"
3269 " [-g test_num (1 - %zu)] |"
3270 " [-f test_num (1 - %zu)] | [-p] | [-k] ]\n",
2953 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests), 3271 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
2954 ARRAY_SIZE(file_tests)); 3272 ARRAY_SIZE(file_tests));
2955} 3273}
2956 3274
2957static int parse_args(int argc, char **argv) 3275static int parse_args(int argc, char **argv)
2958{ 3276{
2959 const char *optstr = "lpf:r:g:"; 3277 const char *optstr = "lpkf:r:g:";
2960 int opt; 3278 int opt;
2961 3279
2962 while ((opt = getopt(argc, argv, optstr)) != -1) { 3280 while ((opt = getopt(argc, argv, optstr)) != -1) {
@@ -2979,6 +3297,9 @@ static int parse_args(int argc, char **argv)
2979 case 'p': 3297 case 'p':
2980 args.pprint_test = true; 3298 args.pprint_test = true;
2981 break; 3299 break;
3300 case 'k':
3301 args.func_type_test = true;
3302 break;
2982 case 'h': 3303 case 'h':
2983 usage(argv[0]); 3304 usage(argv[0]);
2984 exit(0); 3305 exit(0);
@@ -3032,6 +3353,8 @@ int main(int argc, char **argv)
3032 if (args.always_log) 3353 if (args.always_log)
3033 libbpf_set_print(__base_pr, __base_pr, __base_pr); 3354 libbpf_set_print(__base_pr, __base_pr, __base_pr);
3034 3355
3356 jit_enabled = is_jit_enabled();
3357
3035 if (args.raw_test) 3358 if (args.raw_test)
3036 err |= test_raw(); 3359 err |= test_raw();
3037 3360
@@ -3044,8 +3367,11 @@ int main(int argc, char **argv)
3044 if (args.pprint_test) 3367 if (args.pprint_test)
3045 err |= test_pprint(); 3368 err |= test_pprint();
3046 3369
3370 if (args.func_type_test)
3371 err |= test_func_type();
3372
3047 if (args.raw_test || args.get_info_test || args.file_test || 3373 if (args.raw_test || args.get_info_test || args.file_test ||
3048 args.pprint_test) 3374 args.pprint_test || args.func_type_test)
3049 goto done; 3375 goto done;
3050 3376
3051 err |= test_raw(); 3377 err |= test_raw();