5
5
#include <linux/btf.h>
6
6
#include <linux/err.h>
7
7
#include <linux/kernel.h>
8
+ #include <linux/filter.h>
8
9
#include <bpf/bpf.h>
9
10
#include <sys/resource.h>
10
11
#include <libelf.h>
22
23
#include "bpf_rlimit.h"
23
24
#include "bpf_util.h"
24
25
26
+ #define MAX_INSNS 512
27
+ #define MAX_SUBPROGS 16
28
+
25
29
static uint32_t pass_cnt ;
26
30
static uint32_t error_cnt ;
27
31
static uint32_t skip_cnt ;
32
+ static bool jit_enabled ;
28
33
29
34
#define CHECK (condition , format ...) ({ \
30
35
int __ret = !!(condition); \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
60
65
return err ;
61
66
}
62
67
68
+ static 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
86
#define BTF_INFO_ENC (kind , root , vlen ) \
64
87
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
65
88
@@ -115,6 +138,7 @@ static struct args {
115
138
bool get_info_test ;
116
139
bool pprint_test ;
117
140
bool always_log ;
141
+ bool func_type_test ;
118
142
} args ;
119
143
120
144
static char btf_log_buf [BTF_LOG_BUF_SIZE ];
@@ -2947,16 +2971,310 @@ static int test_pprint(void)
2947
2971
return err ;
2948
2972
}
2949
2973
2974
+ static 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
+
3111
+ static 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
+
3121
+ static 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
+
3243
+ done :
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
+
3255
+ static 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
+
2950
3266
static 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
3271
cmd , ARRAY_SIZE (raw_tests ), ARRAY_SIZE (get_info_tests ),
2954
3272
ARRAY_SIZE (file_tests ));
2955
3273
}
2956
3274
2957
3275
static int parse_args (int argc , char * * argv )
2958
3276
{
2959
- const char * optstr = "lpf :r:g:" ;
3277
+ const char * optstr = "lpkf :r:g:" ;
2960
3278
int opt ;
2961
3279
2962
3280
while ((opt = getopt (argc , argv , optstr )) != -1 ) {
@@ -2979,6 +3297,9 @@ static int parse_args(int argc, char **argv)
2979
3297
case 'p' :
2980
3298
args .pprint_test = true;
2981
3299
break ;
3300
+ case 'k' :
3301
+ args .func_type_test = true;
3302
+ break ;
2982
3303
case 'h' :
2983
3304
usage (argv [0 ]);
2984
3305
exit (0 );
@@ -3032,6 +3353,8 @@ int main(int argc, char **argv)
3032
3353
if (args .always_log )
3033
3354
libbpf_set_print (__base_pr , __base_pr , __base_pr );
3034
3355
3356
+ jit_enabled = is_jit_enabled ();
3357
+
3035
3358
if (args .raw_test )
3036
3359
err |= test_raw ();
3037
3360
@@ -3044,8 +3367,11 @@ int main(int argc, char **argv)
3044
3367
if (args .pprint_test )
3045
3368
err |= test_pprint ();
3046
3369
3370
+ if (args .func_type_test )
3371
+ err |= test_func_type ();
3372
+
3047
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
3375
goto done ;
3050
3376
3051
3377
err |= test_raw ();
0 commit comments