2323
2424#include "disasm.h"
2525
26+ static const struct bpf_verifier_ops * const bpf_verifier_ops [] = {
27+ #define BPF_PROG_TYPE (_id , _name ) \
28+ [_id ] = & _name ## _verifier_ops ,
29+ #define BPF_MAP_TYPE (_id , _ops )
30+ #include < linux /bpf_types .h >
31+ #undef BPF_PROG_TYPE
32+ #undef BPF_MAP_TYPE
33+ };
34+
2635/* bpf_check() is a static code analyzer that walks eBPF program
2736 * instruction by instruction and updates register/stack state.
2837 * All paths of conditional branches are analyzed until 'bpf_exit' insn.
@@ -813,36 +822,6 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
813822 return err ;
814823}
815824
816- static bool analyzer_is_valid_access (struct bpf_verifier_env * env , int off ,
817- struct bpf_insn_access_aux * info )
818- {
819- switch (env -> prog -> type ) {
820- case BPF_PROG_TYPE_XDP :
821- switch (off ) {
822- case offsetof(struct xdp_buff , data ):
823- info -> reg_type = PTR_TO_PACKET ;
824- return true;
825- case offsetof(struct xdp_buff , data_end ):
826- info -> reg_type = PTR_TO_PACKET_END ;
827- return true;
828- }
829- return false;
830- case BPF_PROG_TYPE_SCHED_CLS :
831- switch (off ) {
832- case offsetof(struct sk_buff , data ):
833- info -> reg_type = PTR_TO_PACKET ;
834- return true;
835- case offsetof(struct sk_buff , cb ) +
836- offsetof(struct bpf_skb_data_end , data_end ):
837- info -> reg_type = PTR_TO_PACKET_END ;
838- return true;
839- }
840- return false;
841- default :
842- return false;
843- }
844- }
845-
846825/* check access to 'struct bpf_context' fields. Supports fixed offsets only */
847826static int check_ctx_access (struct bpf_verifier_env * env , int insn_idx , int off , int size ,
848827 enum bpf_access_type t , enum bpf_reg_type * reg_type )
@@ -851,23 +830,21 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
851830 .reg_type = * reg_type ,
852831 };
853832
854- if (env -> analyzer_ops ) {
855- if (analyzer_is_valid_access (env , off , & info )) {
856- * reg_type = info .reg_type ;
857- return 0 ;
858- }
859- } else if (env -> prog -> aux -> ops -> is_valid_access &&
860- env -> prog -> aux -> ops -> is_valid_access (off , size , t , & info )) {
833+ if (env -> ops -> is_valid_access &&
834+ env -> ops -> is_valid_access (off , size , t , & info )) {
861835 /* A non zero info.ctx_field_size indicates that this field is a
862836 * candidate for later verifier transformation to load the whole
863837 * field and then apply a mask when accessed with a narrower
864838 * access than actual ctx access size. A zero info.ctx_field_size
865839 * will only allow for whole field access and rejects any other
866840 * type of narrower access.
867841 */
868- env -> insn_aux_data [insn_idx ].ctx_field_size = info .ctx_field_size ;
869842 * reg_type = info .reg_type ;
870843
844+ if (env -> analyzer_ops )
845+ return 0 ;
846+
847+ env -> insn_aux_data [insn_idx ].ctx_field_size = info .ctx_field_size ;
871848 /* remember the offset of last byte accessed in ctx */
872849 if (env -> prog -> aux -> max_ctx_offset < off + size )
873850 env -> prog -> aux -> max_ctx_offset = off + size ;
@@ -1565,8 +1542,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
15651542 return - EINVAL ;
15661543 }
15671544
1568- if (env -> prog -> aux -> ops -> get_func_proto )
1569- fn = env -> prog -> aux -> ops -> get_func_proto (func_id );
1545+ if (env -> ops -> get_func_proto )
1546+ fn = env -> ops -> get_func_proto (func_id );
15701547
15711548 if (!fn ) {
15721549 verbose (env , "unknown func %s#%d\n" , func_id_name (func_id ),
@@ -4035,7 +4012,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
40354012 */
40364013static int convert_ctx_accesses (struct bpf_verifier_env * env )
40374014{
4038- const struct bpf_verifier_ops * ops = env -> prog -> aux -> ops ;
4015+ const struct bpf_verifier_ops * ops = env -> ops ;
40394016 int i , cnt , size , ctx_field_size , delta = 0 ;
40404017 const int insn_cnt = env -> prog -> len ;
40414018 struct bpf_insn insn_buf [16 ], * insn ;
@@ -4236,7 +4213,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
42364213 insn = new_prog -> insnsi + i + delta ;
42374214 }
42384215patch_call_imm :
4239- fn = prog -> aux -> ops -> get_func_proto (insn -> imm );
4216+ fn = env -> ops -> get_func_proto (insn -> imm );
42404217 /* all functions that have prototype and verifier allowed
42414218 * programs to call them, must be real in-kernel functions
42424219 */
@@ -4294,6 +4271,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
42944271 if (!env -> insn_aux_data )
42954272 goto err_free_env ;
42964273 env -> prog = * prog ;
4274+ env -> ops = bpf_verifier_ops [env -> prog -> type ];
42974275
42984276 /* grab the mutex to protect few globals used by verifier */
42994277 mutex_lock (& bpf_verifier_lock );
@@ -4390,12 +4368,21 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
43904368 return ret ;
43914369}
43924370
4371+ static const struct bpf_verifier_ops * const bpf_analyzer_ops [] = {
4372+ [BPF_PROG_TYPE_XDP ] = & xdp_analyzer_ops ,
4373+ [BPF_PROG_TYPE_SCHED_CLS ] = & tc_cls_act_analyzer_ops ,
4374+ };
4375+
43934376int bpf_analyzer (struct bpf_prog * prog , const struct bpf_ext_analyzer_ops * ops ,
43944377 void * priv )
43954378{
43964379 struct bpf_verifier_env * env ;
43974380 int ret ;
43984381
4382+ if (prog -> type >= ARRAY_SIZE (bpf_analyzer_ops ) ||
4383+ !bpf_analyzer_ops [prog -> type ])
4384+ return - EOPNOTSUPP ;
4385+
43994386 env = kzalloc (sizeof (struct bpf_verifier_env ), GFP_KERNEL );
44004387 if (!env )
44014388 return - ENOMEM ;
@@ -4406,6 +4393,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
44064393 if (!env -> insn_aux_data )
44074394 goto err_free_env ;
44084395 env -> prog = prog ;
4396+ env -> ops = bpf_analyzer_ops [env -> prog -> type ];
44094397 env -> analyzer_ops = ops ;
44104398 env -> analyzer_priv = priv ;
44114399
0 commit comments