aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/test_btf.c
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2018-11-19 18:29:15 -0500
committerAlexei Starovoitov <ast@kernel.org>2018-11-20 13:54:39 -0500
commit4798c4ba3ba94e4da37b2557dfda04f80a94e8d5 (patch)
tree71603a1651b624d9f7386576053cd2dc9480c8ec /tools/testing/selftests/bpf/test_btf.c
parent7e0d0fb5522a388700ceff723af98c47ffa8a0a9 (diff)
tools/bpf: extends test_btf to test load/retrieve func_type info
A two function bpf program is loaded with btf and func_info. After successful prog load, the bpf_get_info syscall is called to retrieve prog info to ensure the types returned from the kernel matches the types passed to the kernel from the user space. Several negative tests are also added to test loading/retriving of func_type info. Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
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();