LCOV - code coverage report
Current view: top level - lib/bpf - bpf_validate.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 776 868 89.4 %
Date: 2026-08-01 17:54:00 Functions: 55 59 93.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 560 765 73.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <stdlib.h>
       7                 :            : #include <string.h>
       8                 :            : #include <errno.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <inttypes.h>
      11                 :            : 
      12                 :            : #include <rte_bpf_validate_debug.h>
      13                 :            : #include <rte_common.h>
      14                 :            : 
      15                 :            : #include "bpf_impl.h"
      16                 :            : #include "bpf_validate.h"
      17                 :            : #include "bpf_validate_debug.h"
      18                 :            : #include "bpf_value_set.h"
      19                 :            : 
      20                 :            : #define BPF_ARG_PTR_STACK RTE_BPF_ARG_RESERVED
      21                 :            : 
      22                 :            : /* type containing no values (AKA "bottom", "never" etc)  */
      23                 :            : #define BPF_ARG_UNINHABITED ((enum rte_bpf_arg_type)(RTE_BPF_ARG_UNDEF - 1))
      24                 :            : 
      25                 :            : struct bpf_reg_val {
      26                 :            :         struct rte_bpf_arg v;
      27                 :            :         uint64_t mask;
      28                 :            :         struct {
      29                 :            :                 int64_t min;
      30                 :            :                 int64_t max;
      31                 :            :         } s;
      32                 :            :         struct {
      33                 :            :                 uint64_t min;
      34                 :            :                 uint64_t max;
      35                 :            :         } u;
      36                 :            : };
      37                 :            : 
      38                 :            : struct bpf_eval_state {
      39                 :            :         SLIST_ENTRY(bpf_eval_state) next; /* for @safe list traversal */
      40                 :            :         struct bpf_reg_val rv[EBPF_REG_NUM];
      41                 :            :         struct bpf_reg_val sv[MAX_BPF_STACK_SIZE / sizeof(uint64_t)];
      42                 :            :         /* flag set for branches determined to be dynamically unreachable */
      43                 :            :         bool unreachable;
      44                 :            : };
      45                 :            : 
      46                 :            : SLIST_HEAD(bpf_evst_head, bpf_eval_state);
      47                 :            : 
      48                 :            : /* possible instruction node colour */
      49                 :            : enum {
      50                 :            :         WHITE,
      51                 :            :         GREY,
      52                 :            :         BLACK,
      53                 :            :         MAX_NODE_COLOUR
      54                 :            : };
      55                 :            : 
      56                 :            : /* possible edge types */
      57                 :            : enum {
      58                 :            :         UNKNOWN_EDGE,
      59                 :            :         TREE_EDGE,
      60                 :            :         BACK_EDGE,
      61                 :            :         CROSS_EDGE,
      62                 :            :         MAX_EDGE_TYPE
      63                 :            : };
      64                 :            : 
      65                 :            : #define MAX_EDGES       2
      66                 :            : 
      67                 :            : /* max number of 'safe' evaluated states to track per node */
      68                 :            : #define NODE_EVST_MAX   32
      69                 :            : 
      70                 :            : struct inst_node {
      71                 :            :         uint8_t colour;
      72                 :            :         uint8_t nb_edge:4;
      73                 :            :         uint8_t cur_edge:4;
      74                 :            :         uint8_t edge_type[MAX_EDGES];
      75                 :            :         uint32_t edge_dest[MAX_EDGES];
      76                 :            :         struct inst_node *prev_node;
      77                 :            :         struct {
      78                 :            :                 struct bpf_eval_state *cur;   /* save/restore for jcc targets */
      79                 :            :                 struct bpf_eval_state *start;
      80                 :            :                 struct bpf_evst_head safe;    /* safe states for track/prune */
      81                 :            :                 uint32_t nb_safe;
      82                 :            :         } evst;
      83                 :            : };
      84                 :            : 
      85                 :            : struct evst_pool {
      86                 :            :         uint32_t num;
      87                 :            :         uint32_t cur;
      88                 :            :         struct bpf_eval_state *ent;
      89                 :            : };
      90                 :            : 
      91                 :            : struct bpf_verifier {
      92                 :            :         const struct rte_bpf_prm_ex *prm;
      93                 :            :         struct inst_node *in;
      94                 :            :         uint64_t stack_sz;
      95                 :            :         uint32_t nb_nodes;
      96                 :            :         uint32_t nb_jcc_nodes;
      97                 :            :         uint32_t nb_ldmb_nodes;
      98                 :            :         uint32_t node_colour[MAX_NODE_COLOUR];
      99                 :            :         uint32_t edge_type[MAX_EDGE_TYPE];
     100                 :            :         struct bpf_eval_state *evst;
     101                 :            :         struct inst_node *evin;
     102                 :            :         struct evst_pool evst_sr_pool; /* for evst save/restore */
     103                 :            :         struct evst_pool evst_tp_pool; /* for evst track/prune */
     104                 :            :         struct rte_bpf_validate_debug *debug;
     105                 :            : };
     106                 :            : 
     107                 :            : struct bpf_ins_check {
     108                 :            :         struct {
     109                 :            :                 uint16_t dreg;
     110                 :            :                 uint16_t sreg;
     111                 :            :         } mask;
     112                 :            :         struct {
     113                 :            :                 uint16_t min;
     114                 :            :                 uint16_t max;
     115                 :            :         } off;
     116                 :            :         struct {
     117                 :            :                 uint32_t min;
     118                 :            :                 uint32_t max;
     119                 :            :         } imm;
     120                 :            :         const char * (*check)(const struct ebpf_insn *);
     121                 :            :         const char * (*eval)(struct bpf_verifier *, const struct ebpf_insn *);
     122                 :            : };
     123                 :            : 
     124                 :            : #define ALL_REGS        RTE_LEN2MASK(EBPF_REG_NUM, uint16_t)
     125                 :            : #define WRT_REGS        RTE_LEN2MASK(EBPF_REG_10, uint16_t)
     126                 :            : #define ZERO_REG        RTE_LEN2MASK(EBPF_REG_1, uint16_t)
     127                 :            : 
     128                 :            : /* For LD_IND R6 is an implicit CTX register. */
     129                 :            : #define IND_SRC_REGS    (WRT_REGS ^ 1 << EBPF_REG_6)
     130                 :            : 
     131                 :            : /*
     132                 :            :  * Debugging internal interface and helpers.
     133                 :            :  */
     134                 :            : 
     135                 :            : static bool
     136                 :     408199 : reg_val_range_is_valid(const struct bpf_reg_val *rv)
     137                 :            : {
     138         [ +  + ]:     408199 :         if (rv->v.type == RTE_BPF_ARG_UNDEF)
     139                 :            :                 return true;
     140                 :            : 
     141         [ +  - ]:      41805 :         if (rv->s.min > rv->s.max)
     142                 :            :                 return false;
     143                 :            : 
     144         [ +  - ]:      41805 :         if (rv->u.min > rv->u.max)
     145                 :            :                 return false;
     146                 :            : 
     147                 :            :         /* If one of the ranges does not change sign, the other should match. */
     148   [ +  +  +  + ]:      41805 :         if (rv->s.min >= 0 || rv->s.max < 0 ||
     149   [ +  +  +  + ]:       5150 :                         rv->u.min > INT64_MAX || rv->u.max <= INT64_MAX)
     150         [ +  + ]:      78634 :                 return rv->u.min == (uint64_t)rv->s.min &&
     151         [ +  + ]:      34989 :                         rv->u.max == (uint64_t)rv->s.max;
     152                 :            : 
     153                 :            :         return true;
     154                 :            : }
     155                 :            : 
     156                 :            : int
     157                 :      10343 : __rte_bpf_validate_state_is_valid(const struct bpf_verifier *verifier)
     158                 :            : {
     159                 :      10343 :         const struct bpf_eval_state *const st = verifier->evst;
     160                 :            : 
     161         [ +  + ]:      79838 :         for (int reg = 0; reg != RTE_DIM(st->rv); ++reg)
     162         [ +  + ]:      74655 :                 if (!reg_val_range_is_valid(st->rv + reg))
     163                 :            :                         return false;
     164                 :            : 
     165         [ +  + ]:     336895 :         for (int var = 0; var != RTE_DIM(st->sv); ++var)
     166         [ +  - ]:     331712 :                 if (!reg_val_range_is_valid(st->sv + var))
     167                 :            :                         return false;
     168                 :            : 
     169                 :            :         return true;
     170                 :            : }
     171                 :            : 
     172                 :            : int
     173                 :         96 : __rte_bpf_validate_can_access(const struct bpf_verifier *verifier,
     174                 :            :         const struct ebpf_insn *access, uint64_t off64)
     175                 :            : {
     176                 :         96 :         const struct bpf_eval_state *const st = verifier->evst;
     177                 :            :         const struct bpf_reg_val *rv;
     178                 :            :         /* Set of accessed byte offsets relative to memory area base. */
     179                 :            :         struct value_set access_set;
     180                 :            :         uint32_t opsz;
     181                 :            : 
     182         [ +  - ]:         96 :         if (st->unreachable)
     183                 :            :                 return -ENOENT;
     184                 :            : 
     185   [ +  -  -  - ]:         96 :         switch (BPF_CLASS(access->code)) {
     186                 :         96 :         case BPF_LDX:
     187                 :         96 :                 rv = &st->rv[access->src_reg];
     188         [ +  - ]:         96 :                 if (rv->v.type == BPF_ARG_PTR_STACK)
     189                 :            :                         /* Not supporting stack access queries yet. */
     190                 :            :                         return -ENOTSUP;
     191                 :            :                 break;
     192                 :          0 :         case BPF_ST:
     193                 :          0 :                 rv = &st->rv[access->dst_reg];
     194                 :          0 :                 break;
     195                 :          0 :         case BPF_STX:
     196                 :          0 :                 rv = &st->rv[access->dst_reg];
     197         [ #  # ]:          0 :                 if (st->rv[access->src_reg].v.type == RTE_BPF_ARG_UNDEF)
     198                 :            :                         return false;
     199                 :            :                 break;
     200                 :            :         default:
     201                 :            :                 return -ENOTSUP;
     202                 :            :         }
     203                 :            : 
     204   [ +  -  +  - ]:         96 :         if (!RTE_BPF_ARG_PTR_TYPE(rv->v.type) || rv->v.size == 0)
     205                 :            :                 return false;
     206                 :            : 
     207                 :         96 :         access_set = value_set_from_pair(rv->s.min, rv->s.max, rv->u.min, rv->u.max);
     208                 :         96 :         value_set_translate(&access_set, off64);
     209         [ -  + ]:         96 :         opsz = bpf_size(BPF_SIZE(access->code));
     210                 :         96 :         value_set_add_contiguous(&access_set, 0, opsz - 1);
     211                 :            : 
     212                 :         96 :         return value_set_is_covered_by_contiguous(&access_set, 0, rv->v.size - 1);
     213                 :            : }
     214                 :            : 
     215                 :            : /* Return true if instruction `code` is supported by `may_jump`. */
     216                 :            : static bool
     217                 :      14608 : may_jump_code_is_supported(uint8_t code)
     218                 :            : {
     219         [ +  - ]:      14608 :         if (BPF_CLASS(code) != BPF_JMP)
     220                 :            :                 return false;
     221                 :            : 
     222         [ -  + ]:      14608 :         switch (BPF_OP(code)) {
     223                 :            :         case BPF_JEQ:
     224                 :            :         case BPF_JGT:
     225                 :            :         case BPF_JGE:
     226                 :            :         case EBPF_JNE:
     227                 :            :         case EBPF_JSGT:
     228                 :            :         case EBPF_JSGE:
     229                 :            :         case EBPF_JLT:
     230                 :            :         case EBPF_JLE:
     231                 :            :         case EBPF_JSLT:
     232                 :            :         case EBPF_JSLE:
     233                 :            :                 return true;
     234                 :          0 :         default:
     235                 :          0 :                 return false;
     236                 :            :         }
     237                 :            : }
     238                 :            : 
     239                 :            : /* Return true if instruction `code` corresponds to a signed comparison. */
     240                 :            : static bool
     241                 :            : may_jump_code_is_signed(uint8_t code)
     242                 :            : {
     243                 :      14608 :         switch (BPF_OP(code)) {
     244                 :            :         case EBPF_JSGT:
     245                 :            :         case EBPF_JSGE:
     246                 :            :         case EBPF_JSLT:
     247                 :            :         case EBPF_JSLE:
     248                 :            :                 return true;
     249                 :            :         default:
     250                 :            :                 return false;
     251                 :            :         }
     252                 :            : }
     253                 :            : 
     254                 :            : /* Return true the specified jump condition _may_ be true. */
     255                 :            : static bool
     256                 :      29216 : may_jump(uint8_t code, const struct value_set *origin,
     257                 :            :         const struct value_set *dst_set, const struct value_set *src_set)
     258                 :            : {
     259   [ +  +  +  +  :      29216 :         switch (BPF_OP(code)) {
                +  +  - ]
     260                 :       7304 :         case BPF_JEQ:
     261                 :       7304 :                 return value_sets_intersect(dst_set, src_set);
     262                 :       7304 :         case EBPF_JNE:
     263   [ +  +  -  + ]:       9276 :                 return !(value_set_is_singleton(dst_set) &&
     264                 :       1972 :                         value_sets_equal(dst_set, src_set));
     265                 :       3652 :         case BPF_JGT:
     266                 :            :         case EBPF_JSGT:
     267                 :       3652 :                 return !value_sets_based_less_or_equal(origin, dst_set, src_set);
     268                 :       3652 :         case BPF_JGE:
     269                 :            :         case EBPF_JSGE:
     270                 :       3652 :                 return !value_sets_based_less(origin, dst_set, src_set);
     271                 :       3652 :         case EBPF_JLT:
     272                 :            :         case EBPF_JSLT:
     273                 :       3652 :                 return !value_sets_based_less_or_equal(origin, src_set, dst_set);
     274                 :       3652 :         case EBPF_JSLE:
     275                 :            :         case EBPF_JLE:
     276                 :       3652 :                 return !value_sets_based_less(origin, src_set, dst_set);
     277                 :            :         }
     278                 :            :         /* may_jump_code_is_supported should have caught this */
     279                 :            :         RTE_ASSERT(false);
     280                 :            :         return false;
     281                 :            : }
     282                 :            : 
     283                 :            : /* Return instruction code for jump condition complement (negated result). */
     284                 :            : static uint8_t
     285                 :      14608 : may_jump_code_complement(uint8_t code)
     286                 :            : {
     287   [ +  +  +  +  :      14608 :         switch (BPF_OP(code)) {
                   +  - ]
     288                 :       7304 :         case BPF_JEQ:
     289                 :            :         case EBPF_JNE:
     290                 :       7304 :                 return code ^ BPF_JEQ ^ EBPF_JNE;
     291                 :       1832 :         case BPF_JGT:
     292                 :            :         case EBPF_JLE:
     293                 :       1832 :                 return code ^ BPF_JGT ^ EBPF_JLE;
     294                 :       1832 :         case BPF_JGE:
     295                 :            :         case EBPF_JLT:
     296                 :       1832 :                 return code ^ BPF_JGE ^ EBPF_JLT;
     297                 :       1820 :         case EBPF_JSGT:
     298                 :            :         case EBPF_JSLE:
     299                 :       1820 :                 return code ^ EBPF_JSGT ^ EBPF_JSLE;
     300                 :       1820 :         case EBPF_JSGE:
     301                 :            :         case EBPF_JSLT:
     302                 :       1820 :                 return code ^ EBPF_JSGE ^ EBPF_JSLT;
     303                 :            :         }
     304                 :            :         /* may_jump_code_is_supported should have caught this */
     305                 :            :         RTE_ASSERT(false);
     306                 :            :         return 0;
     307                 :            : }
     308                 :            : 
     309                 :            : int
     310                 :      14608 : __rte_bpf_validate_may_jump(const struct bpf_verifier *verifier,
     311                 :            :         const struct ebpf_insn *jump, uint64_t imm64)
     312                 :            : {
     313                 :      14608 :         const struct bpf_eval_state *const st = verifier->evst;
     314                 :            :         const struct bpf_reg_val *rd, *rs;
     315                 :            :         struct value_set dst_set, src_set, origin;
     316                 :            :         int result;
     317                 :            : 
     318         [ +  - ]:      14608 :         if (!may_jump_code_is_supported(jump->code))
     319                 :            :                 return -ENOTSUP;
     320                 :            : 
     321         [ +  - ]:      14608 :         if (st->unreachable)
     322                 :            :                 /* Set no bits since neither false nor true is possible. */
     323                 :            :                 return 0;
     324                 :            : 
     325                 :      14608 :         rd = &st->rv[jump->dst_reg];
     326         [ +  - ]:      14608 :         dst_set = (rd->v.type == RTE_BPF_ARG_UNDEF) ? value_set_full :
     327                 :      14608 :                 value_set_from_pair(rd->s.min, rd->s.max, rd->u.min, rd->u.max);
     328                 :            : 
     329         [ +  + ]:      14608 :         rs = BPF_SRC(jump->code) == BPF_X ? &st->rv[jump->src_reg] : NULL;
     330                 :      14560 :         src_set = rs == NULL ? value_set_singleton((int64_t)jump->imm) :
     331         [ +  - ]:         48 :                 rs->v.type == RTE_BPF_ARG_UNDEF ? value_set_full :
     332                 :         48 :                 value_set_from_pair(rs->s.min, rs->s.max, rs->u.min, rs->u.max);
     333                 :            : 
     334                 :      14608 :         value_set_translate(&src_set, imm64);
     335                 :            : 
     336   [ +  +  +  - ]:      14608 :         if (RTE_BPF_ARG_PTR_TYPE(rd->v.type) &&
     337         [ +  - ]:         48 :                         (rs != NULL && RTE_BPF_ARG_PTR_TYPE(rs->v.type)) &&
     338         [ +  - ]:         48 :                         rd->v.size == rs->v.size) {
     339                 :            :                 /*
     340                 :            :                  * Both sides are pointers with the same memory area size.
     341                 :            :                  * Until tracking of memory areas is implemented we will consider them
     342                 :            :                  * pointing to the same memory area just because of this.
     343                 :            :                  * In this case our value sets represent offsets from the memory area base,
     344                 :            :                  * which is some unknown distance from the scalar zero (NULL).
     345                 :            :                  * We know however that the memory area cannot cross zero address.
     346                 :            :                  * Thus range of origin relative to memory base starts with 1 byte gap
     347                 :            :                  * after the memory area and ends just before it.
     348                 :            :                  */
     349                 :         48 :                 origin = value_set_contiguous(rd->v.size + 1, -1);
     350                 :            :         } else {
     351                 :            :                 /* Scalar value of a pointer depends on the memory area base address. */
     352         [ -  + ]:      14560 :                 if (RTE_BPF_ARG_PTR_TYPE(rd->v.type))
     353                 :          0 :                         value_set_add_contiguous(&dst_set, 1, UINT64_MAX - rd->v.size);
     354   [ -  +  -  - ]:      14560 :                 if (rs != NULL && RTE_BPF_ARG_PTR_TYPE(rs->v.type))
     355                 :          0 :                         value_set_add_contiguous(&dst_set, 1, UINT64_MAX - rs->v.size);
     356                 :      14560 :                 origin = value_set_singleton(0);
     357                 :            :         }
     358                 :            : 
     359         [ +  + ]:      14608 :         if (may_jump_code_is_signed(jump->code))
     360                 :            :                 /* Shift origin to the minimal value for signed comparisons. */
     361                 :       3640 :                 value_set_translate(&origin, INT64_MIN);
     362                 :            : 
     363                 :            :         result = 0;
     364                 :            : 
     365         [ +  + ]:      14608 :         if (may_jump(jump->code, &origin, &dst_set, &src_set))
     366                 :            :                 result |= RTE_BPF_VALIDATE_DEBUG_MAY_BE_TRUE;
     367                 :            : 
     368         [ +  + ]:      14608 :         if (may_jump(may_jump_code_complement(jump->code), &origin, &dst_set, &src_set))
     369                 :      12636 :                 result |= RTE_BPF_VALIDATE_DEBUG_MAY_BE_FALSE;
     370                 :            : 
     371                 :            :         return result;
     372                 :            : }
     373                 :            : 
     374                 :            : /* Like snprintf, but advances (except for overflow) ptr and reduces szleft. */
     375                 :            : __rte_format_printf(3, 4)
     376                 :            : static int
     377                 :        680 : buf_printf(char **ptr, ssize_t *szleft, const char *format, ...)
     378                 :            : {
     379                 :            :         va_list args;
     380                 :            :         int rc;
     381                 :            : 
     382                 :        680 :         va_start(args, format);
     383         [ +  - ]:        680 :         rc = vsnprintf(*ptr, RTE_MAX(0, *szleft), format, args);
     384                 :        680 :         va_end(args);
     385                 :            : 
     386         [ +  - ]:        680 :         if (rc > 0) {
     387                 :        680 :                 *szleft -= rc;
     388         [ +  - ]:        680 :                 if (*szleft > 0)
     389                 :        680 :                         *ptr += rc;
     390                 :            :         }
     391                 :            : 
     392                 :        680 :         return rc;
     393                 :            : }
     394                 :            : 
     395                 :            : static int
     396                 :       1832 : format_memory_area(char **ptr, ssize_t *szleft, const struct bpf_reg_val *rv)
     397                 :            : {
     398   [ +  -  -  -  :       1832 :         switch (rv->v.type) {
                      + ]
     399                 :            :         case RTE_BPF_ARG_RAW:
     400                 :            :                 return 0;
     401                 :         12 :         case RTE_BPF_ARG_PTR:
     402                 :         12 :                 return buf_printf(ptr, szleft, "%%buffer<%zu> + ",
     403                 :         12 :                         (size_t)rv->v.size);
     404                 :          0 :         case RTE_BPF_ARG_PTR_MBUF:
     405                 :          0 :                 return buf_printf(ptr, szleft, "%%mbuf<%zu, %zu> + ",
     406                 :          0 :                         (size_t)rv->v.size, (size_t)rv->v.buf_size);
     407                 :          0 :         case BPF_ARG_PTR_STACK:
     408                 :          0 :                 return buf_printf(ptr, szleft, "%%stack + ");
     409                 :          0 :         default:
     410                 :          0 :                 return -ENOTSUP;
     411                 :            :         }
     412                 :            : }
     413                 :            : 
     414                 :            : /* Format min..max interval using validate-debug API and updating ptr and szleft. */
     415                 :            : static int
     416                 :       2166 : buf_print_interval(char **ptr, ssize_t *szleft, char format, uint64_t min, uint64_t max)
     417                 :            : {
     418                 :            :         int rc;
     419                 :            : 
     420                 :       2166 :         rc = rte_bpf_validate_debug_format_interval(*ptr, RTE_MAX(0, *szleft),
     421                 :            :                 format, min, max);
     422                 :            : 
     423         [ +  - ]:       2166 :         if (rc > 0) {
     424                 :       2166 :                 *szleft -= rc;
     425         [ +  - ]:       2166 :                 if (*szleft > 0)
     426                 :       2166 :                         *ptr += rc;
     427                 :            :         }
     428                 :            : 
     429                 :       2166 :         return rc;
     430                 :            : }
     431                 :            : 
     432                 :            : /* Format rv roughly as "<signed-range> INTERSECT <unsigned-hex-range>" */
     433                 :            : static int
     434                 :       1832 : format_register_range(char **ptr, ssize_t *szleft, const struct bpf_reg_val *rv)
     435                 :            : {
     436                 :            :         int rc;
     437                 :            :         uint64_t expected_unsigned_min, expected_unsigned_max;
     438                 :       1832 :         const bool valid = reg_val_range_is_valid(rv);
     439                 :            : 
     440                 :            :         /* Print signed unless trivial. */
     441   [ +  +  +  +  :       1832 :         if (!valid || rv->s.min != INT64_MIN || rv->s.max != INT64_MAX) {
                   +  + ]
     442                 :       1770 :                 rc = buf_print_interval(ptr, szleft, 'd', rv->s.min, rv->s.max);
     443         [ +  - ]:       1770 :                 if (rc < 0)
     444                 :            :                         return rc;
     445                 :            : 
     446         [ +  + ]:       1770 :                 if (valid) {
     447                 :            :                         /* Skip printing unsigned if it has expected values. */
     448   [ +  +  +  + ]:       1436 :                         if (rv->s.min >= 0 || rv->s.max < 0) {
     449                 :       1414 :                                 expected_unsigned_min = (uint64_t)rv->s.min;
     450                 :       1414 :                                 expected_unsigned_max = (uint64_t)rv->s.max;
     451                 :            :                         } else {
     452                 :            :                                 expected_unsigned_min = 0;
     453                 :            :                                 expected_unsigned_max = UINT64_MAX;
     454                 :            :                         }
     455                 :            : 
     456         [ +  - ]:       1436 :                         if (rv->u.min == expected_unsigned_min &&
     457         [ -  + ]:       1436 :                                         rv->u.max == expected_unsigned_max)
     458                 :            :                                 return 0;
     459                 :            :                 }
     460                 :            : 
     461                 :        334 :                 rc = buf_printf(ptr, szleft, " INTERSECT ");
     462         [ +  - ]:        334 :                 if (rc < 0)
     463                 :            :                         return rc;
     464                 :            :         }
     465                 :            : 
     466                 :        396 :         rc = buf_print_interval(ptr, szleft, 'x', rv->u.min, rv->u.max);
     467         [ +  - ]:        396 :         if (rc < 0)
     468                 :            :                 return rc;
     469                 :            : 
     470         [ +  + ]:        396 :         if (!valid) {
     471                 :        334 :                 rc = buf_printf(ptr, szleft, " (!)");
     472                 :            :                 if (rc < 0)
     473                 :            :                         return rc;
     474                 :            :         }
     475                 :            : 
     476                 :            :         return 0;
     477                 :            : }
     478                 :            : 
     479                 :            : /* Format rv roughly as "<memory-object> + <offsets-range>" */
     480                 :            : static int
     481                 :       1833 : format_reg_val(char *buffer, size_t bufsz, const struct bpf_reg_val *rv)
     482                 :            : {
     483                 :       1833 :         char *ptr = buffer;
     484                 :       1833 :         ssize_t szleft = bufsz;
     485                 :            :         int rc;
     486                 :            : 
     487         [ +  + ]:       1833 :         if (rv->v.type == RTE_BPF_ARG_UNDEF)
     488                 :          1 :                 return snprintf(buffer, bufsz, "%%undefined");
     489                 :            : 
     490                 :            :         /* Print data area info, if any. */
     491                 :       1832 :         rc = format_memory_area(&ptr, &szleft, rv);
     492         [ +  - ]:       1832 :         if (rc < 0)
     493                 :            :                 return rc;
     494                 :            : 
     495                 :       1832 :         rc = format_register_range(&ptr, &szleft, rv);
     496         [ +  - ]:       1832 :         if (rc < 0)
     497                 :            :                 return rc;
     498                 :            : 
     499                 :            :         /* At least one snprintf was called and added terminating zero. */
     500                 :            :         RTE_ASSERT(szleft < (ssize_t)bufsz);
     501                 :       1832 :         --szleft;
     502                 :            : 
     503                 :       1832 :         return bufsz - szleft;
     504                 :            : }
     505                 :            : 
     506                 :            : int
     507                 :       1833 : __rte_bpf_validate_format_register_info(const struct bpf_verifier *verifier,
     508                 :            :         char *buffer, size_t bufsz, uint8_t reg)
     509                 :            : {
     510         [ +  - ]:       1833 :         if (reg >= EBPF_REG_NUM)
     511                 :            :                 return -EINVAL;
     512                 :            : 
     513                 :       1833 :         return format_reg_val(buffer, bufsz, &verifier->evst->rv[reg]);
     514                 :            : }
     515                 :            : 
     516                 :            : int
     517                 :          0 : __rte_bpf_validate_format_frame_info(const struct bpf_verifier *verifier,
     518                 :            :         char *buffer, size_t bufsz, int32_t offset)
     519                 :            : {
     520         [ #  # ]:          0 :         if (offset % sizeof(uint64_t) != 0)
     521                 :            :                 return -EINVAL;
     522                 :            : 
     523         [ #  # ]:          0 :         if (offset >= 0 || offset < -MAX_BPF_STACK_SIZE)
     524                 :            :                 return -ERANGE;
     525                 :            : 
     526                 :          0 :         offset = (MAX_BPF_STACK_SIZE + offset) / sizeof(uint64_t);
     527                 :            : 
     528                 :          0 :         return format_reg_val(buffer, bufsz, &verifier->evst->sv[offset]);
     529                 :            : }
     530                 :            : 
     531                 :            : int32_t
     532                 :          0 : __rte_bpf_validate_get_frame_size(const struct bpf_verifier *verifier)
     533                 :            : {
     534         [ #  # ]:          0 :         if (verifier->stack_sz > INT32_MAX)
     535                 :            :                 return -ERANGE;
     536                 :            : 
     537                 :          0 :         return verifier->stack_sz;
     538                 :            : }
     539                 :            : 
     540                 :            : 
     541                 :            : /*
     542                 :            :  * check and evaluate functions for particular instruction types.
     543                 :            :  */
     544                 :            : 
     545                 :            : static const char *
     546                 :          8 : check_alu_bele(const struct ebpf_insn *ins)
     547                 :            : {
     548   [ +  +  -  + ]:          8 :         if (ins->imm != 16 && ins->imm != 32 && ins->imm != 64)
     549                 :          0 :                 return "invalid imm field";
     550                 :            :         return NULL;
     551                 :            : }
     552                 :            : 
     553                 :            : static const char *
     554                 :       3271 : eval_exit(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
     555                 :            : {
     556                 :            :         RTE_SET_USED(ins);
     557         [ +  + ]:       3271 :         if (bvf->evst->rv[EBPF_REG_0].v.type == RTE_BPF_ARG_UNDEF)
     558                 :          1 :                 return "undefined return value";
     559                 :            :         return NULL;
     560                 :            : }
     561                 :            : 
     562                 :            : /* setup max possible with this mask bounds */
     563                 :            : static void
     564                 :            : eval_umax_bound(struct bpf_reg_val *rv, uint64_t mask)
     565                 :            : {
     566                 :       1434 :         rv->u.max = mask;
     567                 :       1434 :         rv->u.min = 0;
     568                 :         84 : }
     569                 :            : 
     570                 :            : static void
     571                 :            : eval_smax_bound(struct bpf_reg_val *rv, uint64_t mask)
     572                 :            : {
     573                 :       4295 :         rv->s.max = mask >> 1;
     574                 :       4295 :         rv->s.min = rv->s.max ^ UINT64_MAX;
     575                 :        687 : }
     576                 :            : 
     577                 :            : static void
     578                 :            : eval_max_bound(struct bpf_reg_val *rv, uint64_t mask)
     579                 :            : {
     580                 :            :         eval_umax_bound(rv, mask);
     581                 :            :         eval_smax_bound(rv, mask);
     582                 :        116 : }
     583                 :            : 
     584                 :            : static void
     585                 :            : eval_fill_max_bound(struct bpf_reg_val *rv, uint64_t mask)
     586                 :            : {
     587                 :            :         eval_max_bound(rv, mask);
     588                 :        646 :         rv->v.type = RTE_BPF_ARG_RAW;
     589                 :        646 :         rv->mask = mask;
     590                 :        104 : }
     591                 :            : 
     592                 :            : static void
     593                 :            : eval_fill_imm64(struct bpf_reg_val *rv, uint64_t mask, uint64_t val)
     594                 :            : {
     595                 :       5803 :         rv->mask = mask;
     596                 :       5813 :         rv->s.min = val;
     597                 :       5803 :         rv->s.max = val;
     598                 :       5803 :         rv->u.min = val;
     599                 :       5803 :         rv->u.max = val;
     600                 :          1 : }
     601                 :            : 
     602                 :            : static void
     603                 :            : eval_fill_imm(struct bpf_reg_val *rv, uint64_t mask, int32_t imm)
     604                 :            : {
     605                 :            :         uint64_t v;
     606                 :            : 
     607                 :       5332 :         v = (uint64_t)imm & mask;
     608                 :            : 
     609                 :          0 :         rv->v.type = RTE_BPF_ARG_RAW;
     610                 :            :         eval_fill_imm64(rv, mask, v);
     611                 :        115 : }
     612                 :            : 
     613                 :            : static const char *
     614                 :        365 : eval_ld_imm64(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
     615                 :            : {
     616                 :            :         uint32_t i;
     617                 :            :         uint64_t val;
     618                 :            :         struct bpf_reg_val *rd;
     619                 :            : 
     620                 :        365 :         val = (uint32_t)ins[0].imm | (uint64_t)(uint32_t)ins[1].imm << 32;
     621                 :            : 
     622                 :        365 :         rd = bvf->evst->rv + ins->dst_reg;
     623                 :        365 :         rd->v.type = RTE_BPF_ARG_RAW;
     624                 :            :         eval_fill_imm64(rd, UINT64_MAX, val);
     625                 :            : 
     626         [ -  + ]:        365 :         for (i = 0; i != bvf->prm->nb_xsym; i++) {
     627                 :            : 
     628                 :            :                 /* load of external variable */
     629         [ #  # ]:          0 :                 if (bvf->prm->xsym[i].type == RTE_BPF_XTYPE_VAR &&
     630         [ #  # ]:          0 :                                 (uintptr_t)bvf->prm->xsym[i].var.val == val) {
     631                 :          0 :                         rd->v = bvf->prm->xsym[i].var.desc;
     632                 :            :                         eval_fill_imm64(rd, UINT64_MAX, 0);
     633                 :            :                         break;
     634                 :            :                 }
     635                 :            :         }
     636                 :            : 
     637                 :        365 :         return NULL;
     638                 :            : }
     639                 :            : 
     640                 :            : static void
     641                 :            : eval_apply_mask(struct bpf_reg_val *rv, uint64_t mask)
     642                 :            : {
     643                 :            :         struct bpf_reg_val rt;
     644                 :            : 
     645                 :       2829 :         rt.u.min = rv->u.min & mask;
     646                 :       2829 :         rt.u.max = rv->u.max & mask;
     647   [ +  +  -  +  :       2828 :         if (rt.u.min != rv->u.min || rt.u.max != rv->u.max) {
          +  -  -  +  +  
             +  +  -  +  
                      + ]
     648                 :         13 :                 rv->u.max = RTE_MAX(rt.u.max, mask);
     649                 :         76 :                 rv->u.min = 0;
     650                 :            :         }
     651                 :            : 
     652                 :            :         eval_smax_bound(&rt, mask);
     653                 :       2829 :         rv->s.max = RTE_MIN(rt.s.max, rv->s.max);
     654                 :       2829 :         rv->s.min = RTE_MAX(rt.s.min, rv->s.min);
     655                 :            : 
     656                 :       2750 :         rv->mask = mask;
     657                 :        496 : }
     658                 :            : 
     659                 :            : static void
     660                 :        854 : eval_add(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, uint64_t msk)
     661                 :            : {
     662                 :            :         struct bpf_reg_val rs_buf;
     663                 :            :         struct bpf_reg_val rv;
     664                 :            : 
     665         [ +  + ]:        854 :         if (RTE_BPF_ARG_PTR_TYPE(rs->v.type) != 0) {
     666         [ +  + ]:          8 :                 if (RTE_BPF_ARG_PTR_TYPE(rd->v.type) != 0) {
     667                 :            :                         /* treat sum of pointers as sum of two unknown scalars */
     668                 :            :                         eval_fill_max_bound(&rs_buf, msk);
     669                 :          1 :                         *rd = rs_buf;
     670                 :            :                         rs = &rs_buf;
     671                 :            :                 } else
     672                 :            :                         /* scalar + pointer is a pointer of the same type */
     673                 :          7 :                         rd->v = rs->v;
     674                 :            :         }
     675                 :            : 
     676                 :        854 :         rv.u.min = (rd->u.min + rs->u.min) & msk;
     677                 :        854 :         rv.u.max = (rd->u.max + rs->u.max) & msk;
     678                 :        854 :         rv.s.min = ((uint64_t)rd->s.min + (uint64_t)rs->s.min) & msk;
     679                 :        854 :         rv.s.max = ((uint64_t)rd->s.max + (uint64_t)rs->s.max) & msk;
     680                 :            : 
     681                 :            :         /*
     682                 :            :          * if at least one of the operands is not constant,
     683                 :            :          * then check for overflow
     684                 :            :          */
     685   [ +  +  +  +  :        854 :         if ((rd->u.min != rd->u.max || rs->u.min != rs->u.max) &&
                   +  - ]
     686         [ +  + ]:        102 :                         (rv.u.min < rd->u.min || rv.u.max < rd->u.max))
     687                 :            :                 eval_umax_bound(&rv, msk);
     688                 :            : 
     689   [ +  +  +  +  :        854 :         if ((rd->s.min != rd->s.max || rs->s.min != rs->s.max) &&
                   +  + ]
     690   [ +  +  +  + ]:        102 :                         (((rs->s.min < 0 && rv.s.min > rd->s.min) ||
     691         [ -  + ]:         71 :                         rv.s.min < rd->s.min) ||
     692   [ -  -  +  + ]:         71 :                         ((rs->s.max < 0 && rv.s.max > rd->s.max) ||
     693                 :            :                                 rv.s.max < rd->s.max)))
     694                 :            :                 eval_smax_bound(&rv, msk);
     695                 :            : 
     696                 :        854 :         rd->s = rv.s;
     697                 :        854 :         rd->u = rv.u;
     698                 :        854 : }
     699                 :            : 
     700                 :            : static void
     701                 :         10 : eval_sub(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, uint64_t msk)
     702                 :            : {
     703                 :            :         struct bpf_reg_val rv;
     704                 :            : 
     705                 :         10 :         rv.u.min = (rd->u.min - rs->u.max) & msk;
     706                 :         10 :         rv.u.max = (rd->u.max - rs->u.min) & msk;
     707                 :         10 :         rv.s.min = ((uint64_t)rd->s.min - (uint64_t)rs->s.max) & msk;
     708                 :         10 :         rv.s.max = ((uint64_t)rd->s.max - (uint64_t)rs->s.min) & msk;
     709                 :            : 
     710                 :            :         /*
     711                 :            :          * if at least one of the operands is not constant,
     712                 :            :          * then check for overflow
     713                 :            :          */
     714   [ +  +  -  +  :         10 :         if ((rd->u.min != rd->u.max || rs->u.min != rs->u.max) &&
                   -  + ]
     715         [ #  # ]:          0 :                         (rv.u.min > rd->u.min || rv.u.max > rd->u.max))
     716                 :            :                 eval_umax_bound(&rv, msk);
     717                 :            : 
     718   [ +  +  -  +  :         10 :         if ((rd->s.min != rd->s.max || rs->s.min != rs->s.max) &&
                   -  + ]
     719   [ -  -  +  + ]:          7 :                         (((rs->s.max < 0 && rv.s.min < rd->s.min) ||
     720         [ +  - ]:          1 :                         rv.s.min > rd->s.min) ||
     721   [ -  +  -  - ]:          1 :                         ((rs->s.min < 0 && rv.s.max < rd->s.max) ||
     722                 :            :                         rv.s.max > rd->s.max)))
     723                 :            :                 eval_smax_bound(&rv, msk);
     724                 :            : 
     725                 :         10 :         rd->s = rv.s;
     726                 :         10 :         rd->u = rv.u;
     727                 :         10 : }
     728                 :            : 
     729                 :            : static void
     730                 :         37 : eval_lsh(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     731                 :            :         uint64_t msk)
     732                 :            : {
     733                 :            :         /* check if shift value is less then max result bits */
     734         [ +  + ]:         37 :         if (rs->u.max >= opsz) {
     735                 :            :                 eval_max_bound(rd, msk);
     736                 :          2 :                 return;
     737                 :            :         }
     738                 :            : 
     739                 :            :         /* check for overflow */
     740         [ +  + ]:         35 :         if (rd->u.max > RTE_LEN2MASK(opsz - rs->u.max, uint64_t))
     741                 :            :                 eval_umax_bound(rd, msk);
     742                 :            :         else {
     743                 :          2 :                 rd->u.max <<= rs->u.max;
     744                 :          2 :                 rd->u.min <<= rs->u.min;
     745                 :            :         }
     746                 :            : 
     747                 :            :         /* check that dreg values are and would remain always positive */
     748   [ +  +  +  - ]:         68 :         if ((uint64_t)rd->s.min >> (opsz - 1) != 0 || rd->s.max >=
     749         [ +  + ]:         33 :                         (rs->u.max == opsz - 1 ? 0 :
     750                 :         32 :                                  RTE_LEN2MASK(opsz - rs->u.max - 1, int64_t)))
     751                 :            :                 eval_smax_bound(rd, msk);
     752                 :            :         else {
     753                 :          0 :                 rd->s.max <<= rs->u.max;
     754                 :          0 :                 rd->s.min <<= rs->u.min;
     755                 :            :         }
     756                 :            : }
     757                 :            : 
     758                 :            : static void
     759                 :         16 : eval_rsh(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     760                 :            :         uint64_t msk)
     761                 :            : {
     762                 :            :         /* check if shift value is less then max result bits */
     763         [ +  + ]:         16 :         if (rs->u.max >= opsz) {
     764                 :            :                 eval_max_bound(rd, msk);
     765                 :          1 :                 return;
     766                 :            :         }
     767                 :            : 
     768                 :         15 :         rd->u.max >>= rs->u.min;
     769                 :         15 :         rd->u.min >>= rs->u.max;
     770                 :            : 
     771                 :            :         /* check that dreg values are always positive */
     772         [ +  + ]:         15 :         if ((uint64_t)rd->s.min >> (opsz - 1) != 0)
     773                 :            :                 eval_smax_bound(rd, msk);
     774                 :            :         else {
     775                 :         10 :                 rd->s.max >>= rs->u.min;
     776                 :         10 :                 rd->s.min >>= rs->u.max;
     777                 :            :         }
     778                 :            : }
     779                 :            : 
     780                 :            : static void
     781                 :          2 : eval_arsh(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     782                 :            :         uint64_t msk)
     783                 :            : {
     784                 :            :         uint32_t shv;
     785                 :            : 
     786                 :            :         /* check if shift value is less then max result bits */
     787         [ +  + ]:          2 :         if (rs->u.max >= opsz) {
     788                 :            :                 eval_max_bound(rd, msk);
     789                 :          1 :                 return;
     790                 :            :         }
     791                 :            : 
     792                 :          1 :         rd->u.max = (int64_t)rd->u.max >> rs->u.min;
     793                 :          1 :         rd->u.min = (int64_t)rd->u.min >> rs->u.max;
     794                 :            : 
     795                 :            :         /* if we have 32-bit values - extend them to 64-bit */
     796         [ -  + ]:          1 :         if (opsz == sizeof(uint32_t) * CHAR_BIT) {
     797                 :          0 :                 rd->s.min <<= opsz;
     798                 :          0 :                 rd->s.max <<= opsz;
     799                 :            :                 shv = opsz;
     800                 :            :         } else
     801                 :            :                 shv = 0;
     802                 :            : 
     803         [ +  - ]:          1 :         if (rd->s.min < 0)
     804                 :          1 :                 rd->s.min = (rd->s.min >> (rs->u.min + shv)) & msk;
     805                 :            :         else
     806                 :          0 :                 rd->s.min = (rd->s.min >> (rs->u.max + shv)) & msk;
     807                 :            : 
     808         [ -  + ]:          1 :         if (rd->s.max < 0)
     809                 :          0 :                 rd->s.max = (rd->s.max >> (rs->u.max + shv)) & msk;
     810                 :            :         else
     811                 :          1 :                 rd->s.max = (rd->s.max >> (rs->u.min + shv)) & msk;
     812                 :            : }
     813                 :            : 
     814                 :            : static uint64_t
     815                 :            : eval_umax_bits(uint64_t v, size_t opsz)
     816                 :            : {
     817   [ +  +  +  -  :        198 :         if (v == 0)
          +  -  +  -  +  
                -  +  - ]
     818                 :            :                 return 0;
     819                 :            : 
     820                 :            :         v = rte_clz64(v);
     821                 :        395 :         return RTE_LEN2MASK(opsz - v, uint64_t);
     822                 :            : }
     823                 :            : 
     824                 :            : /* estimate max possible value for (v1 & v2) */
     825                 :            : static uint64_t
     826                 :            : eval_uand_max(uint64_t v1, uint64_t v2, size_t opsz)
     827                 :            : {
     828                 :            :         v1 = eval_umax_bits(v1, opsz);
     829                 :            :         v2 = eval_umax_bits(v2, opsz);
     830                 :        185 :         return (v1 & v2);
     831                 :            : }
     832                 :            : 
     833                 :            : /* estimate max possible value for (v1 | v2) */
     834                 :            : static uint64_t
     835                 :            : eval_uor_max(uint64_t v1, uint64_t v2, size_t opsz)
     836                 :            : {
     837                 :            :         v1 = eval_umax_bits(v1, opsz);
     838                 :            :         v2 = eval_umax_bits(v2, opsz);
     839                 :         13 :         return (v1 | v2);
     840                 :            : }
     841                 :            : 
     842                 :            : static void
     843                 :         93 : eval_and(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     844                 :            :         uint64_t msk)
     845                 :            : {
     846                 :            :         /* both operands are constants */
     847   [ -  +  -  - ]:         93 :         if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) {
     848                 :          0 :                 rd->u.min &= rs->u.min;
     849                 :          0 :                 rd->u.max &= rs->u.max;
     850                 :            :         } else {
     851         [ +  - ]:         93 :                 rd->u.max = eval_uand_max(rd->u.max, rs->u.max, opsz);
     852                 :         93 :                 rd->u.min = 0;
     853                 :            :         }
     854                 :            : 
     855                 :            :         /* both operands are constants */
     856   [ -  +  -  - ]:         93 :         if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) {
     857                 :          0 :                 rd->s.min &= rs->s.min;
     858                 :          0 :                 rd->s.max &= rs->s.max;
     859                 :            :         /* at least one of operand is non-negative */
     860   [ +  +  +  + ]:         93 :         } else if (rd->s.min >= 0 || rs->s.min >= 0) {
     861                 :        184 :                 rd->s.max = eval_uand_max(rd->s.max & (msk >> 1),
     862         [ +  - ]:         92 :                         rs->s.max & (msk >> 1), opsz);
     863                 :         92 :                 rd->s.min = 0;
     864                 :            :         } else
     865                 :            :                 eval_smax_bound(rd, msk);
     866                 :         93 : }
     867                 :            : 
     868                 :            : static void
     869                 :        165 : eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     870                 :            :         uint64_t msk)
     871                 :            : {
     872                 :            :         /* both operands are constants */
     873   [ +  +  +  - ]:        165 :         if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) {
     874                 :        159 :                 rd->u.min |= rs->u.min;
     875                 :        159 :                 rd->u.max |= rs->u.max;
     876                 :            :         } else {
     877         [ +  - ]:          6 :                 rd->u.max = eval_uor_max(rd->u.max, rs->u.max, opsz);
     878                 :          6 :                 rd->u.min = RTE_MAX(rd->u.min, rs->u.min);
     879                 :            :         }
     880                 :            : 
     881                 :            :         /* both operands are constants */
     882   [ +  +  +  - ]:        165 :         if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) {
     883                 :        159 :                 rd->s.min |= rs->s.min;
     884                 :        159 :                 rd->s.max |= rs->s.max;
     885                 :            : 
     886                 :            :         /* both operands are non-negative */
     887   [ +  +  +  + ]:          6 :         } else if (rd->s.min >= 0 && rs->s.min >= 0) {
     888         [ +  - ]:          2 :                 rd->s.max = eval_uor_max(rd->s.max, rs->s.max, opsz);
     889                 :          2 :                 rd->s.min = RTE_MAX(rd->s.min, rs->s.min);
     890                 :            :         } else
     891                 :            :                 eval_smax_bound(rd, msk);
     892                 :        165 : }
     893                 :            : 
     894                 :            : static void
     895                 :        119 : eval_xor(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     896                 :            :         uint64_t msk)
     897                 :            : {
     898                 :            :         /* both operands are constants */
     899   [ +  +  +  - ]:        119 :         if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) {
     900                 :        115 :                 rd->u.min ^= rs->u.min;
     901                 :        115 :                 rd->u.max ^= rs->u.max;
     902                 :            :         } else {
     903         [ +  - ]:          4 :                 rd->u.max = eval_uor_max(rd->u.max, rs->u.max, opsz);
     904                 :          4 :                 rd->u.min = 0;
     905                 :            :         }
     906                 :            : 
     907                 :            :         /* both operands are constants */
     908   [ +  +  +  - ]:        119 :         if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) {
     909                 :        115 :                 rd->s.min ^= rs->s.min;
     910                 :        115 :                 rd->s.max ^= rs->s.max;
     911                 :            : 
     912                 :            :         /* both operands are non-negative */
     913   [ +  +  +  - ]:          4 :         } else if (rd->s.min >= 0 && rs->s.min >= 0) {
     914         [ +  - ]:          1 :                 rd->s.max = eval_uor_max(rd->s.max, rs->s.max, opsz);
     915                 :          1 :                 rd->s.min = 0;
     916                 :            :         } else
     917                 :            :                 eval_smax_bound(rd, msk);
     918                 :        119 : }
     919                 :            : 
     920                 :            : static void
     921                 :         16 : eval_mul(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
     922                 :            :         uint64_t msk)
     923                 :            : {
     924                 :            :         /* both operands are constants */
     925   [ +  +  +  + ]:         16 :         if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) {
     926                 :          1 :                 rd->u.min = (rd->u.min * rs->u.min) & msk;
     927                 :          1 :                 rd->u.max = (rd->u.max * rs->u.max) & msk;
     928                 :            :         /* check for overflow */
     929   [ +  +  +  + ]:         15 :         } else if (rd->u.max <= msk >> opsz / 2 && rs->u.max <= msk >> opsz) {
     930                 :          2 :                 rd->u.max *= rs->u.max;
     931                 :          2 :                 rd->u.min *= rs->u.min;
     932                 :            :         } else
     933                 :            :                 eval_umax_bound(rd, msk);
     934                 :            : 
     935                 :            :         /* both operands are constants */
     936   [ +  +  +  + ]:         16 :         if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) {
     937                 :          1 :                 rd->s.min = ((uint64_t)rd->s.min * (uint64_t)rs->s.min) & msk;
     938                 :          1 :                 rd->s.max = ((uint64_t)rd->s.max * (uint64_t)rs->s.max) & msk;
     939                 :            :         /* check that both operands are positive and no overflow */
     940   [ +  +  +  + ]:         15 :         } else if (rd->s.min >= 0 && rs->s.min >= 0) {
     941                 :         13 :                 rd->s.max *= rs->s.max;
     942                 :         13 :                 rd->s.min *= rs->s.min;
     943                 :            :         } else
     944                 :            :                 eval_smax_bound(rd, msk);
     945                 :         16 : }
     946                 :            : 
     947                 :            : static const char *
     948                 :         47 : eval_divmod(uint32_t op, struct bpf_reg_val *rd, struct bpf_reg_val *rs, uint64_t msk)
     949                 :            : {
     950                 :            :         /* both operands are constants */
     951   [ +  +  +  - ]:         47 :         if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) {
     952         [ +  - ]:         24 :                 if (rs->u.max == 0)
     953                 :            :                         return "division by 0";
     954         [ +  + ]:         24 :                 if (op == BPF_DIV) {
     955                 :         12 :                         rd->u.min /= rs->u.min;
     956                 :         12 :                         rd->u.max /= rs->u.max;
     957                 :            :                 } else {
     958                 :         12 :                         rd->u.min %= rs->u.min;
     959                 :         12 :                         rd->u.max %= rs->u.max;
     960                 :            :                 }
     961                 :            :         } else {
     962         [ +  + ]:         23 :                 if (op == BPF_MOD)
     963                 :         11 :                         rd->u.max = RTE_MIN(rd->u.max, rs->u.max - 1);
     964                 :            :                 else
     965                 :            :                         rd->u.max = rd->u.max;
     966                 :         23 :                 rd->u.min = 0;
     967                 :            :         }
     968                 :            : 
     969   [ +  +  +  + ]:         47 :         if (rd->u.min >= (uint64_t)INT64_MIN || rd->u.max <= (uint64_t)INT64_MAX) {
     970                 :            :                 /*
     971                 :            :                  * All values have the same sign bit, which means range
     972                 :            :                  * contiguous as unsigned is also contiguous as signed,
     973                 :            :                  * so we can just reuse it without any changes.
     974                 :            :                  */
     975                 :         34 :                 rd->s.min = rd->u.min;
     976                 :         34 :                 rd->s.max = rd->u.max;
     977                 :            :         } else
     978                 :            :                 eval_smax_bound(rd, msk);
     979                 :            : 
     980                 :            :         return NULL;
     981                 :            : }
     982                 :            : 
     983                 :            : static void
     984                 :         41 : eval_neg(struct bpf_reg_val *rd, size_t opsz, uint64_t msk)
     985                 :            : {
     986                 :            :         uint64_t ux, uy;
     987                 :            :         int64_t sx, sy;
     988                 :            :         /* additional limits imposed by signed on unsigned and back */
     989                 :            :         struct bpf_reg_val cross_limits = {
     990                 :            :                 .s = { INT64_MIN, INT64_MAX },
     991                 :            :                 .u = { 0, UINT64_MAX },
     992                 :            :         };
     993                 :            : 
     994                 :            :         /* if we have 32-bit values - extend them to 64-bit */
     995         [ +  + ]:         41 :         if (opsz == sizeof(uint32_t) * CHAR_BIT) {
     996                 :          1 :                 rd->u.min = (int32_t)rd->u.min;
     997                 :          1 :                 rd->u.max = (int32_t)rd->u.max;
     998                 :            :         }
     999                 :            : 
    1000         [ +  + ]:         41 :         if (rd->u.min == 0) {
    1001                 :            :                 /* special case: ranges that include 0 and, possibly, 1 */
    1002                 :            : 
    1003                 :            :                 /*
    1004                 :            :                  * Calculate requirements on the signed range of negation.
    1005                 :            :                  * It is only possible when negated range does not cross from
    1006                 :            :                  * INT64_MIN to INT64_MAX, which means our original range does
    1007                 :            :                  * not reach (uint64_t)-INT64_MAX.
    1008                 :            :                  */
    1009         [ +  + ]:         26 :                 if (rd->u.max < (uint64_t)-INT64_MAX) {
    1010                 :          9 :                         cross_limits.s.min = -rd->u.max;
    1011                 :            :                         cross_limits.s.max = -rd->u.min;
    1012                 :            :                 }
    1013                 :            : 
    1014         [ +  + ]:         26 :                 if (rd->u.max != 0)
    1015                 :         24 :                         rd->u.max = UINT64_MAX;
    1016                 :            :         } else {
    1017                 :         15 :                 ux = -rd->u.min & msk;
    1018                 :         15 :                 uy = -rd->u.max & msk;
    1019                 :            : 
    1020                 :         15 :                 rd->u.max = RTE_MAX(ux, uy);
    1021                 :         15 :                 rd->u.min = RTE_MIN(ux, uy);
    1022                 :            :         }
    1023                 :            : 
    1024                 :            :         /* if we have 32-bit values - extend them to 64-bit */
    1025         [ +  + ]:         41 :         if (opsz == sizeof(uint32_t) * CHAR_BIT) {
    1026                 :          1 :                 rd->s.min = (int32_t)rd->s.min;
    1027                 :          1 :                 rd->s.max = (int32_t)rd->s.max;
    1028                 :            :         }
    1029                 :            : 
    1030         [ +  + ]:         41 :         if (rd->s.min == INT64_MIN) {
    1031                 :            :                 /* special case: negation of INT64_MIN is INT64_MIN */
    1032         [ +  + ]:         25 :                 if (rd->s.max <= 0) {
    1033                 :          8 :                         cross_limits.u.min = -(uint64_t)rd->s.max;
    1034                 :            :                         cross_limits.u.max = -(uint64_t)rd->s.min;
    1035                 :            :                 }
    1036         [ +  + ]:         25 :                 if (rd->s.max != INT64_MIN)
    1037                 :         23 :                         rd->s.max = INT64_MAX;
    1038                 :            :         } else {
    1039                 :            :                 /* since max >= min, neither can be INT64_MIN here */
    1040                 :         16 :                 sx = -rd->s.min & msk;
    1041                 :         16 :                 sy = -rd->s.max & msk;
    1042                 :            : 
    1043                 :         16 :                 rd->s.max = RTE_MAX(sx, sy);
    1044                 :         16 :                 rd->s.min = RTE_MIN(sx, sy);
    1045                 :            :         }
    1046                 :            : 
    1047                 :         41 :         rd->s.min = RTE_MAX(rd->s.min, cross_limits.s.min) & msk;
    1048                 :         41 :         rd->s.max = RTE_MIN(rd->s.max, cross_limits.s.max) & msk;
    1049                 :         41 :         rd->u.min = RTE_MAX(rd->u.min, cross_limits.u.min) & msk;
    1050                 :         41 :         rd->u.max = RTE_MIN(rd->u.max, cross_limits.u.max) & msk;
    1051                 :         41 : }
    1052                 :            : 
    1053                 :            : static const char *
    1054                 :        536 : eval_ld_mbuf(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1055                 :            : {
    1056                 :            :         uint32_t i, mode;
    1057                 :            :         struct bpf_reg_val *rv, ri, rs;
    1058                 :            : 
    1059                 :        536 :         mode = BPF_MODE(ins->code);
    1060                 :            : 
    1061                 :            :         /* R6 is an implicit input that must contain pointer to mbuf */
    1062         [ +  - ]:        536 :         if (bvf->evst->rv[EBPF_REG_6].v.type != RTE_BPF_ARG_PTR_MBUF)
    1063                 :            :                 return "invalid type for implicit ctx register";
    1064                 :            : 
    1065         [ +  + ]:        536 :         if (mode == BPF_IND) {
    1066                 :         69 :                 rs = bvf->evst->rv[ins->src_reg];
    1067         [ +  - ]:         69 :                 if (rs.v.type != RTE_BPF_ARG_RAW)
    1068                 :            :                         return "unexpected type for src register";
    1069                 :            : 
    1070                 :         69 :                 eval_fill_imm(&ri, UINT64_MAX, ins->imm);
    1071                 :         69 :                 eval_add(&rs, &ri, UINT64_MAX);
    1072                 :            : 
    1073   [ +  -  +  - ]:         69 :                 if (rs.s.max < 0 || rs.u.min > UINT32_MAX)
    1074                 :            :                         return "mbuf boundary violation";
    1075                 :            :         }
    1076                 :            : 
    1077                 :            :         /* R1-R5 scratch registers */
    1078         [ +  + ]:       3216 :         for (i = EBPF_REG_1; i != EBPF_REG_6; i++)
    1079                 :       2680 :                 bvf->evst->rv[i].v.type = RTE_BPF_ARG_UNDEF;
    1080                 :            : 
    1081                 :            :         /* R0 is an implicit output, contains data fetched from the packet */
    1082                 :            :         rv = bvf->evst->rv + EBPF_REG_0;
    1083         [ +  + ]:        536 :         rv->v.size = bpf_size(BPF_SIZE(ins->code));
    1084                 :        536 :         eval_fill_max_bound(rv, RTE_LEN2MASK(rv->v.size * CHAR_BIT, uint64_t));
    1085                 :            : 
    1086                 :        536 :         return NULL;
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /*
    1090                 :            :  * check that destination and source operand are in defined state.
    1091                 :            :  */
    1092                 :            : static const char *
    1093                 :            : eval_defined(const struct bpf_reg_val *dst, const struct bpf_reg_val *src)
    1094                 :            : {
    1095   [ +  -  +  - ]:       3838 :         if (dst != NULL && dst->v.type == RTE_BPF_ARG_UNDEF)
    1096                 :            :                 return "dest reg value is undefined";
    1097   [ -  +  +  -  :       5655 :         if (src != NULL && src->v.type == RTE_BPF_ARG_UNDEF)
             +  +  -  + ]
    1098                 :            :                 return "src reg value is undefined";
    1099                 :            :         return NULL;
    1100                 :            : }
    1101                 :            : 
    1102                 :            : static const char *
    1103                 :       2333 : eval_alu(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1104                 :            : {
    1105                 :            :         uint64_t msk;
    1106                 :            :         uint32_t op;
    1107                 :            :         size_t opsz, sz;
    1108                 :            :         const char *err;
    1109                 :            :         struct bpf_eval_state *st;
    1110                 :            :         struct bpf_reg_val *rd, rs;
    1111                 :            : 
    1112                 :       2333 :         sz = (BPF_CLASS(ins->code) == BPF_ALU) ?
    1113         [ +  + ]:       2333 :                 sizeof(uint32_t) : sizeof(uint64_t);
    1114                 :       2333 :         opsz = sz * CHAR_BIT;
    1115                 :       2333 :         msk = RTE_LEN2MASK(opsz, uint64_t);
    1116                 :            : 
    1117                 :       2333 :         st = bvf->evst;
    1118                 :       2333 :         rd = st->rv + ins->dst_reg;
    1119                 :            : 
    1120         [ +  + ]:       2333 :         if (BPF_SRC(ins->code) == BPF_X) {
    1121         [ +  + ]:        414 :                 rs = st->rv[ins->src_reg];
    1122                 :            :                 eval_apply_mask(&rs, msk);
    1123                 :            :         } else {
    1124                 :       1919 :                 rs = (struct bpf_reg_val){.v = {.size = sz,},};
    1125                 :       1919 :                 eval_fill_imm(&rs, msk, ins->imm);
    1126                 :            :         }
    1127                 :            : 
    1128                 :            :         eval_apply_mask(rd, msk);
    1129                 :            : 
    1130                 :       2333 :         op = BPF_OP(ins->code);
    1131                 :            : 
    1132                 :            :         /* Allow self-xor as way to zero register */
    1133   [ +  +  +  + ]:       2333 :         if (op == BPF_XOR && BPF_SRC(ins->code) == BPF_X &&
    1134         [ +  + ]:        116 :             ins->src_reg == ins->dst_reg) {
    1135                 :            :                 eval_fill_imm(&rs, UINT64_MAX, 0);
    1136                 :            :                 eval_fill_imm(rd, UINT64_MAX, 0);
    1137                 :            :         }
    1138                 :            : 
    1139   [ +  +  +  + ]:       2374 :         err = eval_defined((op != EBPF_MOV) ? rd : NULL,
    1140                 :            :                            (op != BPF_NEG) ? &rs : NULL);
    1141                 :            :         if (err != NULL)
    1142                 :          0 :                 return err;
    1143                 :            : 
    1144         [ +  + ]:       2333 :         if (op == BPF_ADD)
    1145                 :         59 :                 eval_add(rd, &rs, msk);
    1146                 :            :         else if (op == BPF_SUB)
    1147                 :         10 :                 eval_sub(rd, &rs, msk);
    1148                 :            :         else if (op == BPF_LSH)
    1149                 :         37 :                 eval_lsh(rd, &rs, opsz, msk);
    1150                 :            :         else if (op == BPF_RSH)
    1151                 :         16 :                 eval_rsh(rd, &rs, opsz, msk);
    1152                 :            :         else if (op == EBPF_ARSH)
    1153                 :          2 :                 eval_arsh(rd, &rs, opsz, msk);
    1154                 :            :         else if (op == BPF_AND)
    1155                 :         93 :                 eval_and(rd, &rs, opsz, msk);
    1156                 :            :         else if (op == BPF_OR)
    1157                 :        165 :                 eval_or(rd, &rs, opsz, msk);
    1158                 :            :         else if (op == BPF_XOR)
    1159                 :        119 :                 eval_xor(rd, &rs, opsz, msk);
    1160                 :            :         else if (op == BPF_MUL)
    1161                 :         16 :                 eval_mul(rd, &rs, opsz, msk);
    1162                 :            :         else if (op == BPF_DIV || op == BPF_MOD)
    1163                 :         47 :                 err = eval_divmod(op, rd, &rs, msk);
    1164                 :            :         else if (op == BPF_NEG)
    1165                 :         41 :                 eval_neg(rd, opsz, msk);
    1166                 :            :         else if (op == EBPF_MOV)
    1167                 :       1728 :                 *rd = rs;
    1168                 :            :         else
    1169                 :            :                 eval_max_bound(rd, msk);
    1170                 :            : 
    1171                 :            :         return err;
    1172                 :            : }
    1173                 :            : 
    1174                 :            : static const char *
    1175                 :         10 : eval_bele(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1176                 :            : {
    1177                 :            :         uint64_t msk;
    1178                 :            :         struct bpf_eval_state *st;
    1179                 :            :         struct bpf_reg_val *rd;
    1180                 :            :         const char *err;
    1181                 :            : 
    1182                 :         10 :         msk = RTE_LEN2MASK(ins->imm, uint64_t);
    1183                 :            : 
    1184                 :         10 :         st = bvf->evst;
    1185         [ +  - ]:         10 :         rd = st->rv + ins->dst_reg;
    1186                 :            : 
    1187                 :            :         err = eval_defined(rd, NULL);
    1188                 :            :         if (err != NULL)
    1189                 :            :                 return err;
    1190                 :            : 
    1191                 :            : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
    1192         [ +  + ]:         10 :         if (ins->code == (BPF_ALU | EBPF_END | EBPF_TO_BE))
    1193                 :            :                 eval_max_bound(rd, msk);
    1194                 :            :         else
    1195                 :            :                 eval_apply_mask(rd, msk);
    1196                 :            : #else
    1197                 :            :         if (ins->code == (BPF_ALU | EBPF_END | EBPF_TO_LE))
    1198                 :            :                 eval_max_bound(rd, msk);
    1199                 :            :         else
    1200                 :            :                 eval_apply_mask(rd, msk);
    1201                 :            : #endif
    1202                 :            : 
    1203                 :            :         return NULL;
    1204                 :            : }
    1205                 :            : 
    1206                 :            : static const char *
    1207                 :        726 : eval_ptr(struct bpf_verifier *bvf, struct bpf_reg_val *rm, uint32_t opsz,
    1208                 :            :         uint32_t align, int16_t off)
    1209                 :            : {
    1210                 :            :         struct bpf_reg_val rv;
    1211                 :            : 
    1212                 :            :         /* calculate reg + offset */
    1213                 :        726 :         eval_fill_imm(&rv, rm->mask, off);
    1214                 :        726 :         eval_add(rm, &rv, rm->mask);
    1215                 :            : 
    1216         [ +  + ]:        726 :         if (RTE_BPF_ARG_PTR_TYPE(rm->v.type) == 0)
    1217                 :            :                 return "destination is not a pointer";
    1218                 :            : 
    1219         [ +  - ]:        724 :         if (rm->mask != UINT64_MAX)
    1220                 :            :                 return "pointer truncation";
    1221                 :            : 
    1222         [ +  - ]:        724 :         if (rm->u.max + opsz > rm->v.size ||
    1223         [ +  - ]:        724 :                         (uint64_t)rm->s.max + opsz > rm->v.size ||
    1224         [ +  - ]:        724 :                         rm->s.min < 0)
    1225                 :            :                 return "memory boundary violation";
    1226                 :            : 
    1227         [ +  - ]:        724 :         if (rm->u.max % align !=  0)
    1228                 :            :                 return "unaligned memory access";
    1229                 :            : 
    1230         [ +  + ]:        724 :         if (rm->v.type == BPF_ARG_PTR_STACK) {
    1231                 :            : 
    1232   [ +  -  +  -  :         43 :                 if (rm->u.max != rm->u.min || rm->s.max != rm->s.min ||
                   +  - ]
    1233                 :            :                                 rm->u.max != (uint64_t)rm->s.max)
    1234                 :            :                         return "stack access with variable offset";
    1235                 :            : 
    1236                 :         43 :                 bvf->stack_sz = RTE_MAX(bvf->stack_sz, rm->v.size - rm->u.max);
    1237                 :            : 
    1238                 :            :         /* pointer to mbuf */
    1239         [ +  + ]:        681 :         } else if (rm->v.type == RTE_BPF_ARG_PTR_MBUF) {
    1240                 :            : 
    1241   [ +  -  +  -  :          2 :                 if (rm->u.max != rm->u.min || rm->s.max != rm->s.min ||
                   -  + ]
    1242                 :            :                                 rm->u.max != (uint64_t)rm->s.max)
    1243                 :          0 :                         return "mbuf access with variable offset";
    1244                 :            :         }
    1245                 :            : 
    1246                 :            :         return NULL;
    1247                 :            : }
    1248                 :            : 
    1249                 :            : static void
    1250                 :            : eval_max_load(struct bpf_reg_val *rv, uint64_t mask)
    1251                 :            : {
    1252                 :            :         eval_umax_bound(rv, mask);
    1253                 :            : 
    1254                 :            :         /* full 64-bit load */
    1255   [ -  +  +  + ]:        609 :         if (mask == UINT64_MAX)
    1256                 :            :                 eval_smax_bound(rv, mask);
    1257                 :            :         else {
    1258                 :            :                 /* zero-extend load */
    1259                 :         30 :                 rv->s.min = rv->u.min;
    1260                 :         30 :                 rv->s.max = rv->u.max;
    1261                 :            :         }
    1262                 :            : }
    1263                 :            : 
    1264                 :            : 
    1265                 :            : static const char *
    1266                 :        626 : eval_load(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1267                 :            : {
    1268                 :            :         uint32_t opsz;
    1269                 :            :         uint64_t msk;
    1270                 :            :         const char *err;
    1271                 :            :         struct bpf_eval_state *st;
    1272                 :            :         struct bpf_reg_val *rd, rs;
    1273                 :            :         const struct bpf_reg_val *sv;
    1274                 :            : 
    1275                 :        626 :         st = bvf->evst;
    1276                 :        626 :         rd = st->rv + ins->dst_reg;
    1277                 :        626 :         rs = st->rv[ins->src_reg];
    1278         [ +  + ]:        626 :         opsz = bpf_size(BPF_SIZE(ins->code));
    1279                 :        626 :         msk = RTE_LEN2MASK(opsz * CHAR_BIT, uint64_t);
    1280                 :            : 
    1281                 :        626 :         err = eval_ptr(bvf, &rs, opsz, 1, ins->off);
    1282         [ +  - ]:        626 :         if (err != NULL)
    1283                 :            :                 return err;
    1284                 :            : 
    1285         [ +  + ]:        626 :         if (rs.v.type == BPF_ARG_PTR_STACK) {
    1286                 :            : 
    1287                 :         17 :                 sv = st->sv + rs.u.max / sizeof(uint64_t);
    1288   [ +  -  +  - ]:         17 :                 if (sv->v.type == RTE_BPF_ARG_UNDEF || sv->mask < msk)
    1289                 :            :                         return "undefined value on the stack";
    1290                 :            : 
    1291                 :         17 :                 *rd = *sv;
    1292                 :            : 
    1293                 :            :         /* pointer to mbuf */
    1294         [ +  + ]:        609 :         } else if (rs.v.type == RTE_BPF_ARG_PTR_MBUF) {
    1295                 :            : 
    1296         [ -  + ]:          2 :                 if (rs.u.max == offsetof(struct rte_mbuf, next)) {
    1297                 :            :                         eval_fill_imm(rd, msk, 0);
    1298                 :          0 :                         rd->v = rs.v;
    1299         [ -  + ]:          2 :                 } else if (rs.u.max == offsetof(struct rte_mbuf, buf_addr)) {
    1300                 :            :                         eval_fill_imm(rd, msk, 0);
    1301                 :          0 :                         rd->v.type = RTE_BPF_ARG_PTR;
    1302                 :          0 :                         rd->v.size = rs.v.buf_size;
    1303         [ -  + ]:          2 :                 } else if (rs.u.max == offsetof(struct rte_mbuf, data_off)) {
    1304                 :            :                         eval_fill_imm(rd, msk, RTE_PKTMBUF_HEADROOM);
    1305                 :            :                         rd->v.type = RTE_BPF_ARG_RAW;
    1306                 :            :                 } else {
    1307                 :            :                         eval_max_load(rd, msk);
    1308                 :          2 :                         rd->v.type = RTE_BPF_ARG_RAW;
    1309                 :            :                 }
    1310                 :            : 
    1311                 :            :         /* pointer to raw data */
    1312                 :            :         } else {
    1313                 :            :                 eval_max_load(rd, msk);
    1314                 :        607 :                 rd->v.type = RTE_BPF_ARG_RAW;
    1315                 :            :         }
    1316                 :            : 
    1317                 :            :         return NULL;
    1318                 :            : }
    1319                 :            : 
    1320                 :            : static const char *
    1321                 :            : eval_mbuf_store(const struct bpf_reg_val *rv, uint32_t opsz)
    1322                 :            : {
    1323                 :            :         uint32_t i;
    1324                 :            : 
    1325                 :            :         static const struct {
    1326                 :            :                 size_t off;
    1327                 :            :                 size_t sz;
    1328                 :            :         } mbuf_ro_fileds[] = {
    1329                 :            :                 { .off = offsetof(struct rte_mbuf, buf_addr), },
    1330                 :            :                 { .off = offsetof(struct rte_mbuf, refcnt), },
    1331                 :            :                 { .off = offsetof(struct rte_mbuf, nb_segs), },
    1332                 :            :                 { .off = offsetof(struct rte_mbuf, buf_len), },
    1333                 :            :                 { .off = offsetof(struct rte_mbuf, pool), },
    1334                 :            :                 { .off = offsetof(struct rte_mbuf, next), },
    1335                 :            :                 { .off = offsetof(struct rte_mbuf, priv_size), },
    1336                 :            :         };
    1337                 :            : 
    1338         [ #  # ]:          0 :         for (i = 0; i != RTE_DIM(mbuf_ro_fileds) &&
    1339                 :          0 :                         (mbuf_ro_fileds[i].off + mbuf_ro_fileds[i].sz <=
    1340   [ #  #  #  # ]:          0 :                         rv->u.max || rv->u.max + opsz <= mbuf_ro_fileds[i].off);
    1341                 :          0 :                         i++)
    1342                 :            :                 ;
    1343                 :            : 
    1344         [ #  # ]:          0 :         if (i != RTE_DIM(mbuf_ro_fileds))
    1345                 :            :                 return "store to the read-only mbuf field";
    1346                 :            : 
    1347                 :            :         return NULL;
    1348                 :            : 
    1349                 :            : }
    1350                 :            : 
    1351                 :            : static const char *
    1352                 :        313 : eval_store(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1353                 :            : {
    1354                 :            :         uint32_t opsz;
    1355                 :            :         uint64_t msk;
    1356                 :            :         const char *err;
    1357                 :            :         struct bpf_eval_state *st;
    1358                 :            :         struct bpf_reg_val rd, rs, *sv;
    1359                 :            : 
    1360         [ +  + ]:        313 :         opsz = bpf_size(BPF_SIZE(ins->code));
    1361                 :        313 :         msk = RTE_LEN2MASK(opsz * CHAR_BIT, uint64_t);
    1362                 :            : 
    1363                 :        313 :         st = bvf->evst;
    1364                 :        313 :         rd = st->rv[ins->dst_reg];
    1365                 :            : 
    1366         [ +  + ]:        313 :         if (BPF_CLASS(ins->code) == BPF_STX) {
    1367                 :        303 :                 rs = st->rv[ins->src_reg];
    1368         [ +  + ]:        303 :                 if (BPF_MODE(ins->code) == EBPF_ATOMIC)
    1369      [ +  +  + ]:        260 :                         switch (ins->imm) {
    1370                 :            :                         case BPF_ATOMIC_ADD:
    1371                 :            :                                 break;
    1372                 :         13 :                         case BPF_ATOMIC_XCHG:
    1373                 :            :                                 eval_max_bound(&st->rv[ins->src_reg], msk);
    1374                 :            :                                 break;
    1375                 :            :                         default:
    1376                 :            :                                 return "unsupported atomic operation";
    1377                 :            :                         }
    1378                 :            :                 eval_apply_mask(&rs, msk);
    1379                 :            :         } else
    1380                 :         10 :                 eval_fill_imm(&rs, msk, ins->imm);
    1381                 :            : 
    1382                 :            :         err = eval_defined(NULL, &rs);
    1383                 :            :         if (err != NULL)
    1384                 :            :                 return err;
    1385                 :            : 
    1386                 :         89 :         err = eval_ptr(bvf, &rd, opsz, 1, ins->off);
    1387         [ +  + ]:         89 :         if (err != NULL)
    1388                 :            :                 return err;
    1389                 :            : 
    1390         [ +  + ]:         87 :         if (rd.v.type == BPF_ARG_PTR_STACK) {
    1391                 :            : 
    1392                 :         17 :                 sv = st->sv + rd.u.max / sizeof(uint64_t);
    1393         [ -  + ]:         17 :                 if (BPF_CLASS(ins->code) == BPF_STX &&
    1394                 :            :                                 BPF_MODE(ins->code) == EBPF_ATOMIC)
    1395                 :            :                         eval_max_bound(sv, msk);
    1396                 :            :                 else
    1397                 :         17 :                         *sv = rs;
    1398                 :            : 
    1399                 :            :         /* pointer to mbuf */
    1400         [ -  + ]:         70 :         } else if (rd.v.type == RTE_BPF_ARG_PTR_MBUF) {
    1401                 :            :                 err = eval_mbuf_store(&rd, opsz);
    1402                 :            :                 if (err != NULL)
    1403                 :          0 :                         return err;
    1404                 :            :         }
    1405                 :            : 
    1406                 :            :         return NULL;
    1407                 :            : }
    1408                 :            : 
    1409                 :            : static const char *
    1410                 :        199 : eval_ja(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1411                 :            : {
    1412                 :            :         RTE_SET_USED(bvf);
    1413                 :            :         RTE_SET_USED(ins);
    1414                 :        199 :         return NULL;
    1415                 :            : }
    1416                 :            : 
    1417                 :            : static const char *
    1418                 :        116 : eval_func_arg(struct bpf_verifier *bvf, const struct rte_bpf_arg *arg,
    1419                 :            :         struct bpf_reg_val *rv)
    1420                 :            : {
    1421                 :            :         uint32_t i, n;
    1422                 :            :         struct bpf_eval_state *st;
    1423                 :            :         const char *err;
    1424                 :            : 
    1425                 :        116 :         st = bvf->evst;
    1426                 :            : 
    1427         [ +  - ]:        116 :         if (rv->v.type == RTE_BPF_ARG_UNDEF)
    1428                 :            :                 return "Undefined argument type";
    1429                 :            : 
    1430   [ +  +  +  - ]:        116 :         if (arg->type != rv->v.type &&
    1431         [ +  - ]:          9 :                         arg->type != RTE_BPF_ARG_RAW &&
    1432                 :          9 :                         (arg->type != RTE_BPF_ARG_PTR ||
    1433         [ +  - ]:          9 :                         RTE_BPF_ARG_PTR_TYPE(rv->v.type) == 0))
    1434                 :            :                 return "Invalid argument type";
    1435                 :            : 
    1436                 :            :         err = NULL;
    1437                 :            : 
    1438                 :            :         /* argument is a pointer */
    1439         [ +  + ]:        116 :         if (RTE_BPF_ARG_PTR_TYPE(arg->type) != 0) {
    1440                 :            : 
    1441                 :         11 :                 err = eval_ptr(bvf, rv, arg->size, 1, 0);
    1442                 :            : 
    1443                 :            :                 /*
    1444                 :            :                  * pointer to the variable on the stack is passed
    1445                 :            :                  * as an argument, mark stack space it occupies as initialized.
    1446                 :            :                  */
    1447   [ +  -  +  + ]:         11 :                 if (err == NULL && rv->v.type == BPF_ARG_PTR_STACK) {
    1448                 :            : 
    1449                 :          9 :                         i = rv->u.max / sizeof(uint64_t);
    1450                 :          9 :                         n = i + arg->size / sizeof(uint64_t);
    1451         [ +  + ]:         14 :                         while (i != n) {
    1452                 :          5 :                                 eval_fill_max_bound(st->sv + i, UINT64_MAX);
    1453                 :          5 :                                 i++;
    1454                 :            :                         };
    1455                 :            :                 }
    1456                 :            :         }
    1457                 :            : 
    1458                 :            :         return err;
    1459                 :            : }
    1460                 :            : 
    1461                 :            : static const char *
    1462                 :        107 : eval_call(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1463                 :            : {
    1464                 :            :         uint32_t i, idx;
    1465                 :            :         struct bpf_reg_val *rv;
    1466                 :            :         const struct rte_bpf_xsym *xsym;
    1467                 :            :         const char *err;
    1468                 :            : 
    1469                 :        107 :         idx = ins->imm;
    1470                 :            : 
    1471         [ +  - ]:        107 :         if (idx >= bvf->prm->nb_xsym ||
    1472         [ +  - ]:        107 :                         bvf->prm->xsym[idx].type != RTE_BPF_XTYPE_FUNC)
    1473                 :            :                 return "invalid external function index";
    1474                 :            : 
    1475                 :            :         /* for now don't support function calls on 32 bit platform */
    1476                 :            :         if (sizeof(uint64_t) != sizeof(uintptr_t))
    1477                 :            :                 return "function calls are supported only for 64 bit apps";
    1478                 :            : 
    1479                 :            :         xsym = bvf->prm->xsym + idx;
    1480                 :            : 
    1481                 :            :         /* evaluate function arguments */
    1482                 :            :         err = NULL;
    1483   [ +  +  +  - ]:        223 :         for (i = 0; i != xsym->func.nb_args && err == NULL; i++) {
    1484                 :        116 :                 err = eval_func_arg(bvf, xsym->func.args + i,
    1485                 :        116 :                         bvf->evst->rv + EBPF_REG_1 + i);
    1486                 :            :         }
    1487                 :            : 
    1488                 :            :         /* R1-R5 argument/scratch registers */
    1489         [ +  + ]:        642 :         for (i = EBPF_REG_1; i != EBPF_REG_6; i++)
    1490                 :        535 :                 bvf->evst->rv[i].v.type = RTE_BPF_ARG_UNDEF;
    1491                 :            : 
    1492                 :            :         /* update return value */
    1493                 :            : 
    1494                 :        107 :         rv = bvf->evst->rv + EBPF_REG_0;
    1495                 :        107 :         rv->v = xsym->func.ret;
    1496         [ +  + ]:        107 :         if (rv->v.type == RTE_BPF_ARG_RAW)
    1497                 :        104 :                 eval_fill_max_bound(rv,
    1498                 :        104 :                         RTE_LEN2MASK(rv->v.size * CHAR_BIT, uint64_t));
    1499         [ +  + ]:          3 :         else if (RTE_BPF_ARG_PTR_TYPE(rv->v.type) != 0)
    1500                 :            :                 eval_fill_imm64(rv, UINTPTR_MAX, 0);
    1501                 :            : 
    1502                 :            :         return err;
    1503                 :            : }
    1504                 :            : 
    1505                 :            : static void
    1506                 :        555 : eval_jeq_jne(struct bpf_reg_val *trd, struct bpf_reg_val *trs)
    1507                 :            : {
    1508                 :            :         /* sreg is constant */
    1509         [ +  + ]:        555 :         if (trs->u.min == trs->u.max) {
    1510                 :        537 :                 trd->u = trs->u;
    1511                 :            :         /* dreg is constant */
    1512         [ +  + ]:         18 :         } else if (trd->u.min == trd->u.max) {
    1513                 :          8 :                 trs->u = trd->u;
    1514                 :            :         } else {
    1515                 :         10 :                 trd->u.max = RTE_MIN(trd->u.max, trs->u.max);
    1516                 :         10 :                 trd->u.min = RTE_MAX(trd->u.min, trs->u.min);
    1517                 :         10 :                 trs->u = trd->u;
    1518                 :            :         }
    1519                 :            : 
    1520                 :            :         /* sreg is constant */
    1521         [ +  + ]:        555 :         if (trs->s.min == trs->s.max) {
    1522                 :        537 :                 trd->s = trs->s;
    1523                 :            :         /* dreg is constant */
    1524         [ +  + ]:         18 :         } else if (trd->s.min == trd->s.max) {
    1525                 :          8 :                 trs->s = trd->s;
    1526                 :            :         } else {
    1527                 :         10 :                 trd->s.max = RTE_MIN(trd->s.max, trs->s.max);
    1528                 :         10 :                 trd->s.min = RTE_MAX(trd->s.min, trs->s.min);
    1529                 :         10 :                 trs->s = trd->s;
    1530                 :            :         }
    1531                 :        555 : }
    1532                 :            : 
    1533                 :            : static void
    1534                 :            : eval_jgt_jle(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
    1535                 :            :         struct bpf_reg_val *frd, struct bpf_reg_val *frs)
    1536                 :            : {
    1537   [ +  +  +  + ]:        685 :         if (frd->u.min <= frs->u.max) {
    1538                 :        669 :                 frd->u.max = RTE_MIN(frd->u.max, frs->u.max);
    1539                 :        669 :                 frs->u.min = RTE_MAX(frs->u.min, frd->u.min);
    1540                 :            :         } else
    1541                 :         16 :                 frd->v.type = frs->v.type = BPF_ARG_UNINHABITED;
    1542                 :            : 
    1543   [ +  +  +  + ]:        685 :         if (trs->u.min < trd->u.max) {
    1544                 :        645 :                 trd->u.min = RTE_MAX(trd->u.min, trs->u.min + 1);
    1545                 :        645 :                 trs->u.max = RTE_MIN(trs->u.max, trd->u.max - 1);
    1546                 :            :         } else
    1547                 :         40 :                 trd->v.type = trs->v.type = BPF_ARG_UNINHABITED;
    1548                 :            : }
    1549                 :            : 
    1550                 :            : static void
    1551                 :            : eval_jlt_jge(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
    1552                 :            :         struct bpf_reg_val *frd, struct bpf_reg_val *frs)
    1553                 :            : {
    1554   [ +  +  +  + ]:        612 :         if (frs->u.min <= frd->u.max) {
    1555                 :        596 :                 frd->u.min = RTE_MAX(frd->u.min, frs->u.min);
    1556                 :        596 :                 frs->u.max = RTE_MIN(frs->u.max, frd->u.max);
    1557                 :            :         } else
    1558                 :         16 :                 frd->v.type = frs->v.type = BPF_ARG_UNINHABITED;
    1559                 :            : 
    1560   [ +  +  +  + ]:        612 :         if (trd->u.min < trs->u.max) {
    1561                 :        586 :                 trd->u.max = RTE_MIN(trd->u.max, trs->u.max - 1);
    1562                 :        586 :                 trs->u.min = RTE_MAX(trs->u.min, trd->u.min + 1);
    1563                 :            :         } else
    1564                 :         26 :                 trd->v.type = trs->v.type = BPF_ARG_UNINHABITED;
    1565                 :            : }
    1566                 :            : 
    1567                 :            : static void
    1568                 :            : eval_jsgt_jsle(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
    1569                 :            :         struct bpf_reg_val *frd, struct bpf_reg_val *frs)
    1570                 :            : {
    1571   [ +  +  +  + ]:        648 :         if (frd->s.min <= frs->s.max) {
    1572                 :        632 :                 frd->s.max = RTE_MIN(frd->s.max, frs->s.max);
    1573                 :        632 :                 frs->s.min = RTE_MAX(frs->s.min, frd->s.min);
    1574                 :            :         } else
    1575                 :         16 :                 frd->v.type = frs->v.type = BPF_ARG_UNINHABITED;
    1576                 :            : 
    1577   [ +  +  +  + ]:        648 :         if (trs->s.min < trd->s.max) {
    1578                 :        604 :                 trd->s.min = RTE_MAX(trd->s.min, trs->s.min + 1);
    1579                 :        604 :                 trs->s.max = RTE_MIN(trs->s.max, trd->s.max - 1);
    1580                 :            :         } else
    1581                 :         44 :                 trd->v.type = trs->v.type = BPF_ARG_UNINHABITED;
    1582                 :            : }
    1583                 :            : 
    1584                 :            : static void
    1585                 :            : eval_jslt_jsge(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
    1586                 :            :         struct bpf_reg_val *frd, struct bpf_reg_val *frs)
    1587                 :            : {
    1588   [ +  +  +  + ]:        603 :         if (frs->s.min <= frd->s.max) {
    1589                 :        587 :                 frd->s.min = RTE_MAX(frd->s.min, frs->s.min);
    1590                 :        587 :                 frs->s.max = RTE_MIN(frs->s.max, frd->s.max);
    1591                 :            :         } else
    1592                 :         16 :                 frd->v.type = frs->v.type = BPF_ARG_UNINHABITED;
    1593                 :            : 
    1594   [ +  +  +  + ]:        603 :         if (trd->s.min < trs->s.max) {
    1595                 :        579 :                 trd->s.max = RTE_MIN(trd->s.max, trs->s.max - 1);
    1596                 :        579 :                 trs->s.min = RTE_MAX(trs->s.min, trd->s.min + 1);
    1597                 :            :         } else
    1598                 :         24 :                 trd->v.type = trs->v.type = BPF_ARG_UNINHABITED;
    1599                 :            : }
    1600                 :            : 
    1601                 :            : static const char *
    1602                 :       3233 : eval_jcc(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
    1603                 :            : {
    1604                 :            :         uint32_t op;
    1605                 :            :         const char *err;
    1606                 :            :         struct bpf_eval_state *fst, *tst;
    1607                 :            :         struct bpf_reg_val *frd, *frs, *trd, *trs;
    1608                 :            :         struct bpf_reg_val rvf, rvt;
    1609                 :            : 
    1610                 :       3233 :         tst = bvf->evst;
    1611                 :       3233 :         fst = bvf->evin->evst.cur;
    1612                 :            : 
    1613                 :       3233 :         frd = fst->rv + ins->dst_reg;
    1614                 :       3233 :         trd = tst->rv + ins->dst_reg;
    1615                 :            : 
    1616         [ +  + ]:       3233 :         if (BPF_SRC(ins->code) == BPF_X) {
    1617                 :        625 :                 frs = fst->rv + ins->src_reg;
    1618                 :        625 :                 trs = tst->rv + ins->src_reg;
    1619                 :            :         } else {
    1620                 :            :                 frs = &rvf;
    1621                 :            :                 trs = &rvt;
    1622                 :       2608 :                 eval_fill_imm(frs, UINT64_MAX, ins->imm);
    1623                 :            :                 eval_fill_imm(trs, UINT64_MAX, ins->imm);
    1624                 :            :         }
    1625                 :            : 
    1626                 :            :         err = eval_defined(trd, trs);
    1627                 :            :         if (err != NULL)
    1628                 :          0 :                 return err;
    1629                 :            : 
    1630                 :       3233 :         op = BPF_OP(ins->code);
    1631                 :            : 
    1632         [ +  + ]:       3233 :         if (op == BPF_JEQ)
    1633                 :        215 :                 eval_jeq_jne(trd, trs);
    1634         [ +  + ]:       3018 :         else if (op == EBPF_JNE)
    1635                 :        340 :                 eval_jeq_jne(frd, frs);
    1636         [ +  + ]:       2678 :         else if (op == BPF_JGT)
    1637                 :            :                 eval_jgt_jle(trd, trs, frd, frs);
    1638         [ +  + ]:       2077 :         else if (op == EBPF_JLE)
    1639                 :            :                 eval_jgt_jle(frd, frs, trd, trs);
    1640         [ +  + ]:       1993 :         else if (op == EBPF_JLT)
    1641                 :            :                 eval_jlt_jge(trd, trs, frd, frs);
    1642         [ +  + ]:       1430 :         else if (op == BPF_JGE)
    1643                 :            :                 eval_jlt_jge(frd, frs, trd, trs);
    1644         [ +  + ]:       1381 :         else if (op == EBPF_JSGT)
    1645                 :            :                 eval_jsgt_jsle(trd, trs, frd, frs);
    1646         [ +  + ]:        775 :         else if (op == EBPF_JSLE)
    1647                 :            :                 eval_jsgt_jsle(frd, frs, trd, trs);
    1648         [ +  + ]:        733 :         else if (op == EBPF_JSLT)
    1649                 :            :                 eval_jslt_jsge(trd, trs, frd, frs);
    1650         [ +  + ]:        170 :         else if (op == EBPF_JSGE)
    1651                 :            :                 eval_jslt_jsge(frd, frs, trd, trs);
    1652                 :            : 
    1653         [ +  + ]:       3233 :         if (trd->v.type == BPF_ARG_UNINHABITED ||
    1654         [ -  + ]:       3132 :                         trs->v.type == BPF_ARG_UNINHABITED)
    1655                 :        101 :                 tst->unreachable = true;
    1656                 :            : 
    1657         [ +  + ]:       3233 :         if (frd->v.type == BPF_ARG_UNINHABITED ||
    1658         [ -  + ]:       3136 :                         frs->v.type == BPF_ARG_UNINHABITED)
    1659                 :         97 :                 fst->unreachable = true;
    1660                 :            : 
    1661                 :            :         return NULL;
    1662                 :            : }
    1663                 :            : 
    1664                 :            : /*
    1665                 :            :  * validate parameters for each instruction type.
    1666                 :            :  */
    1667                 :            : static const struct bpf_ins_check ins_chk[UINT8_MAX + 1] = {
    1668                 :            :         /* ALU IMM 32-bit instructions */
    1669                 :            :         [(BPF_ALU | BPF_ADD | BPF_K)] = {
    1670                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1671                 :            :                 .off = { .min = 0, .max = 0},
    1672                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1673                 :            :                 .eval = eval_alu,
    1674                 :            :         },
    1675                 :            :         [(BPF_ALU | BPF_SUB | BPF_K)] = {
    1676                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1677                 :            :                 .off = { .min = 0, .max = 0},
    1678                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1679                 :            :                 .eval = eval_alu,
    1680                 :            :         },
    1681                 :            :         [(BPF_ALU | BPF_AND | BPF_K)] = {
    1682                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1683                 :            :                 .off = { .min = 0, .max = 0},
    1684                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1685                 :            :                 .eval = eval_alu,
    1686                 :            :         },
    1687                 :            :         [(BPF_ALU | BPF_OR | BPF_K)] = {
    1688                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1689                 :            :                 .off = { .min = 0, .max = 0},
    1690                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1691                 :            :                 .eval = eval_alu,
    1692                 :            :         },
    1693                 :            :         [(BPF_ALU | BPF_LSH | BPF_K)] = {
    1694                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1695                 :            :                 .off = { .min = 0, .max = 0},
    1696                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1697                 :            :                 .eval = eval_alu,
    1698                 :            :         },
    1699                 :            :         [(BPF_ALU | BPF_RSH | BPF_K)] = {
    1700                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1701                 :            :                 .off = { .min = 0, .max = 0},
    1702                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1703                 :            :                 .eval = eval_alu,
    1704                 :            :         },
    1705                 :            :         [(BPF_ALU | BPF_XOR | BPF_K)] = {
    1706                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1707                 :            :                 .off = { .min = 0, .max = 0},
    1708                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1709                 :            :                 .eval = eval_alu,
    1710                 :            :         },
    1711                 :            :         [(BPF_ALU | BPF_MUL | BPF_K)] = {
    1712                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1713                 :            :                 .off = { .min = 0, .max = 0},
    1714                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1715                 :            :                 .eval = eval_alu,
    1716                 :            :         },
    1717                 :            :         [(BPF_ALU | EBPF_MOV | BPF_K)] = {
    1718                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1719                 :            :                 .off = { .min = 0, .max = 0},
    1720                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1721                 :            :                 .eval = eval_alu,
    1722                 :            :         },
    1723                 :            :         [(BPF_ALU | BPF_DIV | BPF_K)] = {
    1724                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1725                 :            :                 .off = { .min = 0, .max = 0},
    1726                 :            :                 .imm = { .min = 1, .max = UINT32_MAX},
    1727                 :            :                 .eval = eval_alu,
    1728                 :            :         },
    1729                 :            :         [(BPF_ALU | BPF_MOD | BPF_K)] = {
    1730                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1731                 :            :                 .off = { .min = 0, .max = 0},
    1732                 :            :                 .imm = { .min = 1, .max = UINT32_MAX},
    1733                 :            :                 .eval = eval_alu,
    1734                 :            :         },
    1735                 :            :         /* ALU IMM 64-bit instructions */
    1736                 :            :         [(EBPF_ALU64 | BPF_ADD | BPF_K)] = {
    1737                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1738                 :            :                 .off = { .min = 0, .max = 0},
    1739                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1740                 :            :                 .eval = eval_alu,
    1741                 :            :         },
    1742                 :            :         [(EBPF_ALU64 | BPF_SUB | BPF_K)] = {
    1743                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1744                 :            :                 .off = { .min = 0, .max = 0},
    1745                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1746                 :            :                 .eval = eval_alu,
    1747                 :            :         },
    1748                 :            :         [(EBPF_ALU64 | BPF_AND | BPF_K)] = {
    1749                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1750                 :            :                 .off = { .min = 0, .max = 0},
    1751                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1752                 :            :                 .eval = eval_alu,
    1753                 :            :         },
    1754                 :            :         [(EBPF_ALU64 | BPF_OR | BPF_K)] = {
    1755                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1756                 :            :                 .off = { .min = 0, .max = 0},
    1757                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1758                 :            :                 .eval = eval_alu,
    1759                 :            :         },
    1760                 :            :         [(EBPF_ALU64 | BPF_LSH | BPF_K)] = {
    1761                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1762                 :            :                 .off = { .min = 0, .max = 0},
    1763                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1764                 :            :                 .eval = eval_alu,
    1765                 :            :         },
    1766                 :            :         [(EBPF_ALU64 | BPF_RSH | BPF_K)] = {
    1767                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1768                 :            :                 .off = { .min = 0, .max = 0},
    1769                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1770                 :            :                 .eval = eval_alu,
    1771                 :            :         },
    1772                 :            :         [(EBPF_ALU64 | EBPF_ARSH | BPF_K)] = {
    1773                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1774                 :            :                 .off = { .min = 0, .max = 0},
    1775                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1776                 :            :                 .eval = eval_alu,
    1777                 :            :         },
    1778                 :            :         [(EBPF_ALU64 | BPF_XOR | BPF_K)] = {
    1779                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1780                 :            :                 .off = { .min = 0, .max = 0},
    1781                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1782                 :            :                 .eval = eval_alu,
    1783                 :            :         },
    1784                 :            :         [(EBPF_ALU64 | BPF_MUL | BPF_K)] = {
    1785                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1786                 :            :                 .off = { .min = 0, .max = 0},
    1787                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1788                 :            :                 .eval = eval_alu,
    1789                 :            :         },
    1790                 :            :         [(EBPF_ALU64 | EBPF_MOV | BPF_K)] = {
    1791                 :            :                 .mask = {.dreg = WRT_REGS, .sreg = ZERO_REG},
    1792                 :            :                 .off = { .min = 0, .max = 0},
    1793                 :            :                 .imm = { .min = 0, .max = UINT32_MAX,},
    1794                 :            :                 .eval = eval_alu,
    1795                 :            :         },
    1796                 :            :         [(EBPF_ALU64 | BPF_DIV | BPF_K)] = {
    1797                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1798                 :            :                 .off = { .min = 0, .max = 0},
    1799                 :            :                 .imm = { .min = 1, .max = UINT32_MAX},
    1800                 :            :                 .eval = eval_alu,
    1801                 :            :         },
    1802                 :            :         [(EBPF_ALU64 | BPF_MOD | BPF_K)] = {
    1803                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1804                 :            :                 .off = { .min = 0, .max = 0},
    1805                 :            :                 .imm = { .min = 1, .max = UINT32_MAX},
    1806                 :            :                 .eval = eval_alu,
    1807                 :            :         },
    1808                 :            :         /* ALU REG 32-bit instructions */
    1809                 :            :         [(BPF_ALU | BPF_ADD | BPF_X)] = {
    1810                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1811                 :            :                 .off = { .min = 0, .max = 0},
    1812                 :            :                 .imm = { .min = 0, .max = 0},
    1813                 :            :                 .eval = eval_alu,
    1814                 :            :         },
    1815                 :            :         [(BPF_ALU | BPF_SUB | BPF_X)] = {
    1816                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1817                 :            :                 .off = { .min = 0, .max = 0},
    1818                 :            :                 .imm = { .min = 0, .max = 0},
    1819                 :            :                 .eval = eval_alu,
    1820                 :            :         },
    1821                 :            :         [(BPF_ALU | BPF_AND | BPF_X)] = {
    1822                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1823                 :            :                 .off = { .min = 0, .max = 0},
    1824                 :            :                 .imm = { .min = 0, .max = 0},
    1825                 :            :                 .eval = eval_alu,
    1826                 :            :         },
    1827                 :            :         [(BPF_ALU | BPF_OR | BPF_X)] = {
    1828                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1829                 :            :                 .off = { .min = 0, .max = 0},
    1830                 :            :                 .imm = { .min = 0, .max = 0},
    1831                 :            :                 .eval = eval_alu,
    1832                 :            :         },
    1833                 :            :         [(BPF_ALU | BPF_LSH | BPF_X)] = {
    1834                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1835                 :            :                 .off = { .min = 0, .max = 0},
    1836                 :            :                 .imm = { .min = 0, .max = 0},
    1837                 :            :                 .eval = eval_alu,
    1838                 :            :         },
    1839                 :            :         [(BPF_ALU | BPF_RSH | BPF_X)] = {
    1840                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1841                 :            :                 .off = { .min = 0, .max = 0},
    1842                 :            :                 .imm = { .min = 0, .max = 0},
    1843                 :            :                 .eval = eval_alu,
    1844                 :            :         },
    1845                 :            :         [(BPF_ALU | BPF_XOR | BPF_X)] = {
    1846                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1847                 :            :                 .off = { .min = 0, .max = 0},
    1848                 :            :                 .imm = { .min = 0, .max = 0},
    1849                 :            :                 .eval = eval_alu,
    1850                 :            :         },
    1851                 :            :         [(BPF_ALU | BPF_MUL | BPF_X)] = {
    1852                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1853                 :            :                 .off = { .min = 0, .max = 0},
    1854                 :            :                 .imm = { .min = 0, .max = 0},
    1855                 :            :                 .eval = eval_alu,
    1856                 :            :         },
    1857                 :            :         [(BPF_ALU | BPF_DIV | BPF_X)] = {
    1858                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1859                 :            :                 .off = { .min = 0, .max = 0},
    1860                 :            :                 .imm = { .min = 0, .max = 0},
    1861                 :            :                 .eval = eval_alu,
    1862                 :            :         },
    1863                 :            :         [(BPF_ALU | BPF_MOD | BPF_X)] = {
    1864                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1865                 :            :                 .off = { .min = 0, .max = 0},
    1866                 :            :                 .imm = { .min = 0, .max = 0},
    1867                 :            :                 .eval = eval_alu,
    1868                 :            :         },
    1869                 :            :         [(BPF_ALU | EBPF_MOV | BPF_X)] = {
    1870                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1871                 :            :                 .off = { .min = 0, .max = 0},
    1872                 :            :                 .imm = { .min = 0, .max = 0},
    1873                 :            :                 .eval = eval_alu,
    1874                 :            :         },
    1875                 :            :         [(BPF_ALU | BPF_NEG)] = {
    1876                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1877                 :            :                 .off = { .min = 0, .max = 0},
    1878                 :            :                 .imm = { .min = 0, .max = 0},
    1879                 :            :                 .eval = eval_alu,
    1880                 :            :         },
    1881                 :            :         [(BPF_ALU | EBPF_END | EBPF_TO_BE)] = {
    1882                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1883                 :            :                 .off = { .min = 0, .max = 0},
    1884                 :            :                 .imm = { .min = 16, .max = 64},
    1885                 :            :                 .check = check_alu_bele,
    1886                 :            :                 .eval = eval_bele,
    1887                 :            :         },
    1888                 :            :         [(BPF_ALU | EBPF_END | EBPF_TO_LE)] = {
    1889                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1890                 :            :                 .off = { .min = 0, .max = 0},
    1891                 :            :                 .imm = { .min = 16, .max = 64},
    1892                 :            :                 .check = check_alu_bele,
    1893                 :            :                 .eval = eval_bele,
    1894                 :            :         },
    1895                 :            :         /* ALU REG 64-bit instructions */
    1896                 :            :         [(EBPF_ALU64 | BPF_ADD | BPF_X)] = {
    1897                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1898                 :            :                 .off = { .min = 0, .max = 0},
    1899                 :            :                 .imm = { .min = 0, .max = 0},
    1900                 :            :                 .eval = eval_alu,
    1901                 :            :         },
    1902                 :            :         [(EBPF_ALU64 | BPF_SUB | BPF_X)] = {
    1903                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1904                 :            :                 .off = { .min = 0, .max = 0},
    1905                 :            :                 .imm = { .min = 0, .max = 0},
    1906                 :            :                 .eval = eval_alu,
    1907                 :            :         },
    1908                 :            :         [(EBPF_ALU64 | BPF_AND | BPF_X)] = {
    1909                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1910                 :            :                 .off = { .min = 0, .max = 0},
    1911                 :            :                 .imm = { .min = 0, .max = 0},
    1912                 :            :                 .eval = eval_alu,
    1913                 :            :         },
    1914                 :            :         [(EBPF_ALU64 | BPF_OR | BPF_X)] = {
    1915                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1916                 :            :                 .off = { .min = 0, .max = 0},
    1917                 :            :                 .imm = { .min = 0, .max = 0},
    1918                 :            :                 .eval = eval_alu,
    1919                 :            :         },
    1920                 :            :         [(EBPF_ALU64 | BPF_LSH | BPF_X)] = {
    1921                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1922                 :            :                 .off = { .min = 0, .max = 0},
    1923                 :            :                 .imm = { .min = 0, .max = 0},
    1924                 :            :                 .eval = eval_alu,
    1925                 :            :         },
    1926                 :            :         [(EBPF_ALU64 | BPF_RSH | BPF_X)] = {
    1927                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1928                 :            :                 .off = { .min = 0, .max = 0},
    1929                 :            :                 .imm = { .min = 0, .max = 0},
    1930                 :            :                 .eval = eval_alu,
    1931                 :            :         },
    1932                 :            :         [(EBPF_ALU64 | EBPF_ARSH | BPF_X)] = {
    1933                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1934                 :            :                 .off = { .min = 0, .max = 0},
    1935                 :            :                 .imm = { .min = 0, .max = 0},
    1936                 :            :                 .eval = eval_alu,
    1937                 :            :         },
    1938                 :            :         [(EBPF_ALU64 | BPF_XOR | BPF_X)] = {
    1939                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1940                 :            :                 .off = { .min = 0, .max = 0},
    1941                 :            :                 .imm = { .min = 0, .max = 0},
    1942                 :            :                 .eval = eval_alu,
    1943                 :            :         },
    1944                 :            :         [(EBPF_ALU64 | BPF_MUL | BPF_X)] = {
    1945                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1946                 :            :                 .off = { .min = 0, .max = 0},
    1947                 :            :                 .imm = { .min = 0, .max = 0},
    1948                 :            :                 .eval = eval_alu,
    1949                 :            :         },
    1950                 :            :         [(EBPF_ALU64 | BPF_DIV | BPF_X)] = {
    1951                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1952                 :            :                 .off = { .min = 0, .max = 0},
    1953                 :            :                 .imm = { .min = 0, .max = 0},
    1954                 :            :                 .eval = eval_alu,
    1955                 :            :         },
    1956                 :            :         [(EBPF_ALU64 | BPF_MOD | BPF_X)] = {
    1957                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1958                 :            :                 .off = { .min = 0, .max = 0},
    1959                 :            :                 .imm = { .min = 0, .max = 0},
    1960                 :            :                 .eval = eval_alu,
    1961                 :            :         },
    1962                 :            :         [(EBPF_ALU64 | EBPF_MOV | BPF_X)] = {
    1963                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ALL_REGS},
    1964                 :            :                 .off = { .min = 0, .max = 0},
    1965                 :            :                 .imm = { .min = 0, .max = 0},
    1966                 :            :                 .eval = eval_alu,
    1967                 :            :         },
    1968                 :            :         [(EBPF_ALU64 | BPF_NEG)] = {
    1969                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    1970                 :            :                 .off = { .min = 0, .max = 0},
    1971                 :            :                 .imm = { .min = 0, .max = 0},
    1972                 :            :                 .eval = eval_alu,
    1973                 :            :         },
    1974                 :            :         /* load instructions */
    1975                 :            :         [(BPF_LDX | BPF_MEM | BPF_B)] = {
    1976                 :            :                 .mask = {. dreg = WRT_REGS, .sreg = ALL_REGS},
    1977                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    1978                 :            :                 .imm = { .min = 0, .max = 0},
    1979                 :            :                 .eval = eval_load,
    1980                 :            :         },
    1981                 :            :         [(BPF_LDX | BPF_MEM | BPF_H)] = {
    1982                 :            :                 .mask = {. dreg = WRT_REGS, .sreg = ALL_REGS},
    1983                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    1984                 :            :                 .imm = { .min = 0, .max = 0},
    1985                 :            :                 .eval = eval_load,
    1986                 :            :         },
    1987                 :            :         [(BPF_LDX | BPF_MEM | BPF_W)] = {
    1988                 :            :                 .mask = {. dreg = WRT_REGS, .sreg = ALL_REGS},
    1989                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    1990                 :            :                 .imm = { .min = 0, .max = 0},
    1991                 :            :                 .eval = eval_load,
    1992                 :            :         },
    1993                 :            :         [(BPF_LDX | BPF_MEM | EBPF_DW)] = {
    1994                 :            :                 .mask = {. dreg = WRT_REGS, .sreg = ALL_REGS},
    1995                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    1996                 :            :                 .imm = { .min = 0, .max = 0},
    1997                 :            :                 .eval = eval_load,
    1998                 :            :         },
    1999                 :            :         /* load 64 bit immediate value */
    2000                 :            :         [(BPF_LD | BPF_IMM | EBPF_DW)] = {
    2001                 :            :                 .mask = { .dreg = WRT_REGS, .sreg = ZERO_REG},
    2002                 :            :                 .off = { .min = 0, .max = 0},
    2003                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2004                 :            :                 .eval = eval_ld_imm64,
    2005                 :            :         },
    2006                 :            :         /* load absolute instructions */
    2007                 :            :         [(BPF_LD | BPF_ABS | BPF_B)] = {
    2008                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = ZERO_REG},
    2009                 :            :                 .off = { .min = 0, .max = 0},
    2010                 :            :                 .imm = { .min = 0, .max = INT32_MAX},
    2011                 :            :                 .eval = eval_ld_mbuf,
    2012                 :            :         },
    2013                 :            :         [(BPF_LD | BPF_ABS | BPF_H)] = {
    2014                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = ZERO_REG},
    2015                 :            :                 .off = { .min = 0, .max = 0},
    2016                 :            :                 .imm = { .min = 0, .max = INT32_MAX},
    2017                 :            :                 .eval = eval_ld_mbuf,
    2018                 :            :         },
    2019                 :            :         [(BPF_LD | BPF_ABS | BPF_W)] = {
    2020                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = ZERO_REG},
    2021                 :            :                 .off = { .min = 0, .max = 0},
    2022                 :            :                 .imm = { .min = 0, .max = INT32_MAX},
    2023                 :            :                 .eval = eval_ld_mbuf,
    2024                 :            :         },
    2025                 :            :         /* load indirect instructions */
    2026                 :            :         [(BPF_LD | BPF_IND | BPF_B)] = {
    2027                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = IND_SRC_REGS},
    2028                 :            :                 .off = { .min = 0, .max = 0},
    2029                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2030                 :            :                 .eval = eval_ld_mbuf,
    2031                 :            :         },
    2032                 :            :         [(BPF_LD | BPF_IND | BPF_H)] = {
    2033                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = IND_SRC_REGS},
    2034                 :            :                 .off = { .min = 0, .max = 0},
    2035                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2036                 :            :                 .eval = eval_ld_mbuf,
    2037                 :            :         },
    2038                 :            :         [(BPF_LD | BPF_IND | BPF_W)] = {
    2039                 :            :                 .mask = {. dreg = ZERO_REG, .sreg = IND_SRC_REGS},
    2040                 :            :                 .off = { .min = 0, .max = 0},
    2041                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2042                 :            :                 .eval = eval_ld_mbuf,
    2043                 :            :         },
    2044                 :            :         /* store REG instructions */
    2045                 :            :         [(BPF_STX | BPF_MEM | BPF_B)] = {
    2046                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2047                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2048                 :            :                 .imm = { .min = 0, .max = 0},
    2049                 :            :                 .eval = eval_store,
    2050                 :            :         },
    2051                 :            :         [(BPF_STX | BPF_MEM | BPF_H)] = {
    2052                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2053                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2054                 :            :                 .imm = { .min = 0, .max = 0},
    2055                 :            :                 .eval = eval_store,
    2056                 :            :         },
    2057                 :            :         [(BPF_STX | BPF_MEM | BPF_W)] = {
    2058                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2059                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2060                 :            :                 .imm = { .min = 0, .max = 0},
    2061                 :            :                 .eval = eval_store,
    2062                 :            :         },
    2063                 :            :         [(BPF_STX | BPF_MEM | EBPF_DW)] = {
    2064                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2065                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2066                 :            :                 .imm = { .min = 0, .max = 0},
    2067                 :            :                 .eval = eval_store,
    2068                 :            :         },
    2069                 :            :         /* atomic instructions */
    2070                 :            :         [(BPF_STX | EBPF_ATOMIC | BPF_W)] = {
    2071                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2072                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2073                 :            :                 .imm = { .min = BPF_ATOMIC_ADD, .max = BPF_ATOMIC_XCHG},
    2074                 :            :                 .eval = eval_store,
    2075                 :            :         },
    2076                 :            :         [(BPF_STX | EBPF_ATOMIC | EBPF_DW)] = {
    2077                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2078                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2079                 :            :                 .imm = { .min = BPF_ATOMIC_ADD, .max = BPF_ATOMIC_XCHG},
    2080                 :            :                 .eval = eval_store,
    2081                 :            :         },
    2082                 :            :         /* store IMM instructions */
    2083                 :            :         [(BPF_ST | BPF_MEM | BPF_B)] = {
    2084                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2085                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2086                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2087                 :            :                 .eval = eval_store,
    2088                 :            :         },
    2089                 :            :         [(BPF_ST | BPF_MEM | BPF_H)] = {
    2090                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2091                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2092                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2093                 :            :                 .eval = eval_store,
    2094                 :            :         },
    2095                 :            :         [(BPF_ST | BPF_MEM | BPF_W)] = {
    2096                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2097                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2098                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2099                 :            :                 .eval = eval_store,
    2100                 :            :         },
    2101                 :            :         [(BPF_ST | BPF_MEM | EBPF_DW)] = {
    2102                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2103                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2104                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2105                 :            :                 .eval = eval_store,
    2106                 :            :         },
    2107                 :            :         /* jump instruction */
    2108                 :            :         [(BPF_JMP | BPF_JA)] = {
    2109                 :            :                 .mask = { .dreg = ZERO_REG, .sreg = ZERO_REG},
    2110                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2111                 :            :                 .imm = { .min = 0, .max = 0},
    2112                 :            :                 .eval = eval_ja,
    2113                 :            :         },
    2114                 :            :         /* jcc IMM instructions */
    2115                 :            :         [(BPF_JMP | BPF_JEQ | BPF_K)] = {
    2116                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2117                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2118                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2119                 :            :                 .eval = eval_jcc,
    2120                 :            :         },
    2121                 :            :         [(BPF_JMP | EBPF_JNE | BPF_K)] = {
    2122                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2123                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2124                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2125                 :            :                 .eval = eval_jcc,
    2126                 :            :         },
    2127                 :            :         [(BPF_JMP | BPF_JGT | BPF_K)] = {
    2128                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2129                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2130                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2131                 :            :                 .eval = eval_jcc,
    2132                 :            :         },
    2133                 :            :         [(BPF_JMP | EBPF_JLT | BPF_K)] = {
    2134                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2135                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2136                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2137                 :            :                 .eval = eval_jcc,
    2138                 :            :         },
    2139                 :            :         [(BPF_JMP | BPF_JGE | BPF_K)] = {
    2140                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2141                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2142                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2143                 :            :                 .eval = eval_jcc,
    2144                 :            :         },
    2145                 :            :         [(BPF_JMP | EBPF_JLE | BPF_K)] = {
    2146                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2147                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2148                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2149                 :            :                 .eval = eval_jcc,
    2150                 :            :         },
    2151                 :            :         [(BPF_JMP | EBPF_JSGT | BPF_K)] = {
    2152                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2153                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2154                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2155                 :            :                 .eval = eval_jcc,
    2156                 :            :         },
    2157                 :            :         [(BPF_JMP | EBPF_JSLT | BPF_K)] = {
    2158                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2159                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2160                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2161                 :            :                 .eval = eval_jcc,
    2162                 :            :         },
    2163                 :            :         [(BPF_JMP | EBPF_JSGE | BPF_K)] = {
    2164                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2165                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2166                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2167                 :            :                 .eval = eval_jcc,
    2168                 :            :         },
    2169                 :            :         [(BPF_JMP | EBPF_JSLE | BPF_K)] = {
    2170                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2171                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2172                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2173                 :            :                 .eval = eval_jcc,
    2174                 :            :         },
    2175                 :            :         [(BPF_JMP | BPF_JSET | BPF_K)] = {
    2176                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ZERO_REG},
    2177                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2178                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2179                 :            :                 .eval = eval_jcc,
    2180                 :            :         },
    2181                 :            :         /* jcc REG instructions */
    2182                 :            :         [(BPF_JMP | BPF_JEQ | BPF_X)] = {
    2183                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2184                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2185                 :            :                 .imm = { .min = 0, .max = 0},
    2186                 :            :                 .eval = eval_jcc,
    2187                 :            :         },
    2188                 :            :         [(BPF_JMP | EBPF_JNE | BPF_X)] = {
    2189                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2190                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2191                 :            :                 .imm = { .min = 0, .max = 0},
    2192                 :            :                 .eval = eval_jcc,
    2193                 :            :         },
    2194                 :            :         [(BPF_JMP | BPF_JGT | BPF_X)] = {
    2195                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2196                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2197                 :            :                 .imm = { .min = 0, .max = 0},
    2198                 :            :                 .eval = eval_jcc,
    2199                 :            :         },
    2200                 :            :         [(BPF_JMP | EBPF_JLT | BPF_X)] = {
    2201                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2202                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2203                 :            :                 .imm = { .min = 0, .max = 0},
    2204                 :            :                 .eval = eval_jcc,
    2205                 :            :         },
    2206                 :            :         [(BPF_JMP | BPF_JGE | BPF_X)] = {
    2207                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2208                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2209                 :            :                 .imm = { .min = 0, .max = 0},
    2210                 :            :                 .eval = eval_jcc,
    2211                 :            :         },
    2212                 :            :         [(BPF_JMP | EBPF_JLE | BPF_X)] = {
    2213                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2214                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2215                 :            :                 .imm = { .min = 0, .max = 0},
    2216                 :            :                 .eval = eval_jcc,
    2217                 :            :         },
    2218                 :            :         [(BPF_JMP | EBPF_JSGT | BPF_X)] = {
    2219                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2220                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2221                 :            :                 .imm = { .min = 0, .max = 0},
    2222                 :            :                 .eval = eval_jcc,
    2223                 :            :         },
    2224                 :            :         [(BPF_JMP | EBPF_JSLT | BPF_X)] = {
    2225                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2226                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2227                 :            :                 .imm = { .min = 0, .max = 0},
    2228                 :            :                 .eval = eval_jcc,
    2229                 :            :         },
    2230                 :            :         [(BPF_JMP | EBPF_JSGE | BPF_X)] = {
    2231                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2232                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2233                 :            :                 .imm = { .min = 0, .max = 0},
    2234                 :            :                 .eval = eval_jcc,
    2235                 :            :         },
    2236                 :            :         [(BPF_JMP | EBPF_JSLE | BPF_X)] = {
    2237                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2238                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2239                 :            :                 .imm = { .min = 0, .max = 0},
    2240                 :            :                 .eval = eval_jcc,
    2241                 :            :         },
    2242                 :            :         [(BPF_JMP | BPF_JSET | BPF_X)] = {
    2243                 :            :                 .mask = { .dreg = ALL_REGS, .sreg = ALL_REGS},
    2244                 :            :                 .off = { .min = 0, .max = UINT16_MAX},
    2245                 :            :                 .imm = { .min = 0, .max = 0},
    2246                 :            :                 .eval = eval_jcc,
    2247                 :            :         },
    2248                 :            :         /* call instruction */
    2249                 :            :         [(BPF_JMP | EBPF_CALL)] = {
    2250                 :            :                 .mask = { .dreg = ZERO_REG, .sreg = ZERO_REG},
    2251                 :            :                 .off = { .min = 0, .max = 0},
    2252                 :            :                 .imm = { .min = 0, .max = UINT32_MAX},
    2253                 :            :                 .eval = eval_call,
    2254                 :            :         },
    2255                 :            :         /* ret instruction */
    2256                 :            :         [(BPF_JMP | EBPF_EXIT)] = {
    2257                 :            :                 .mask = { .dreg = ZERO_REG, .sreg = ZERO_REG},
    2258                 :            :                 .off = { .min = 0, .max = 0},
    2259                 :            :                 .imm = { .min = 0, .max = 0},
    2260                 :            :                 .eval = eval_exit,
    2261                 :            :         },
    2262                 :            : };
    2263                 :            : 
    2264                 :            : /*
    2265                 :            :  * make sure that instruction syntax is valid,
    2266                 :            :  * and its fields don't violate particular instruction type restrictions.
    2267                 :            :  */
    2268                 :            : static const char *
    2269                 :       8565 : check_syntax(const struct ebpf_insn *ins)
    2270                 :            : {
    2271                 :            : 
    2272                 :            :         uint8_t op;
    2273                 :            :         uint16_t off;
    2274                 :            :         uint32_t imm;
    2275                 :            : 
    2276                 :       8565 :         op = ins->code;
    2277                 :            : 
    2278         [ +  - ]:       8565 :         if (ins_chk[op].mask.dreg == 0)
    2279                 :            :                 return "invalid opcode";
    2280                 :            : 
    2281         [ +  - ]:       8565 :         if ((ins_chk[op].mask.dreg & 1 << ins->dst_reg) == 0)
    2282                 :            :                 return "invalid dst-reg field";
    2283                 :            : 
    2284         [ +  - ]:       8565 :         if ((ins_chk[op].mask.sreg & 1 << ins->src_reg) == 0)
    2285                 :            :                 return "invalid src-reg field";
    2286                 :            : 
    2287                 :       8565 :         off = ins->off;
    2288   [ +  -  +  - ]:       8565 :         if (ins_chk[op].off.min > off || ins_chk[op].off.max < off)
    2289                 :            :                 return "invalid off field";
    2290                 :            : 
    2291                 :       8565 :         imm = ins->imm;
    2292   [ +  -  +  + ]:       8565 :         if (ins_chk[op].imm.min > imm || ins_chk[op].imm.max < imm)
    2293                 :            :                 return "invalid imm field";
    2294                 :            : 
    2295         [ +  + ]:       8561 :         if (ins_chk[op].check != NULL)
    2296                 :          8 :                 return ins_chk[op].check(ins);
    2297                 :            : 
    2298                 :            :         return NULL;
    2299                 :            : }
    2300                 :            : 
    2301                 :            : /*
    2302                 :            :  * helper function, return instruction index for the given node.
    2303                 :            :  */
    2304                 :            : static uint32_t
    2305                 :            : get_node_idx(const struct bpf_verifier *bvf, const struct inst_node *node)
    2306                 :            : {
    2307                 :      33242 :         return node - bvf->in;
    2308                 :            : }
    2309                 :            : 
    2310                 :            : /*
    2311                 :            :  * helper function, used to walk through constructed CFG.
    2312                 :            :  */
    2313                 :            : static struct inst_node *
    2314                 :            : get_next_node(struct bpf_verifier *bvf, struct inst_node *node)
    2315                 :            : {
    2316                 :            :         uint32_t ce, ne, dst;
    2317                 :            : 
    2318                 :      40157 :         ne = node->nb_edge;
    2319                 :      40157 :         ce = node->cur_edge;
    2320   [ +  +  +  + ]:      40157 :         if (ce == ne)
    2321                 :            :                 return NULL;
    2322                 :            : 
    2323                 :      21070 :         node->cur_edge++;
    2324                 :      21070 :         dst = node->edge_dest[ce];
    2325                 :      21070 :         return bvf->in + dst;
    2326                 :            : }
    2327                 :            : 
    2328                 :            : static void
    2329                 :            : set_node_colour(struct bpf_verifier *bvf, struct inst_node *node,
    2330                 :            :         uint32_t new)
    2331                 :            : {
    2332                 :            :         uint32_t prev;
    2333                 :            : 
    2334                 :            :         prev = node->colour;
    2335                 :      17096 :         node->colour = new;
    2336                 :            : 
    2337                 :      17096 :         bvf->node_colour[prev]--;
    2338                 :      17096 :         bvf->node_colour[new]++;
    2339                 :       8548 : }
    2340                 :            : 
    2341                 :            : /*
    2342                 :            :  * helper function, add new edge between two nodes.
    2343                 :            :  */
    2344                 :            : static int
    2345                 :      10354 : add_edge(struct bpf_verifier *bvf, struct inst_node *node, uint32_t nidx)
    2346                 :            : {
    2347                 :            :         uint32_t ne;
    2348                 :            : 
    2349         [ +  + ]:      10354 :         if (nidx >= bvf->prm->raw.nb_ins) {
    2350                 :          1 :                 RTE_BPF_LOG_FUNC_LINE(ERR,
    2351                 :            :                         "program boundary violation at pc: %u, next pc: %u",
    2352                 :            :                         get_node_idx(bvf, node), nidx);
    2353                 :          1 :                 return -EINVAL;
    2354                 :            :         }
    2355                 :            : 
    2356                 :      10353 :         ne = node->nb_edge;
    2357         [ -  + ]:      10353 :         if (ne >= RTE_DIM(node->edge_dest)) {
    2358                 :          0 :                 RTE_BPF_LOG_FUNC_LINE(ERR, "internal error at pc: %u",
    2359                 :            :                         get_node_idx(bvf, node));
    2360                 :          0 :                 return -EINVAL;
    2361                 :            :         }
    2362                 :            : 
    2363                 :      10353 :         node->edge_dest[ne] = nidx;
    2364                 :      10353 :         node->nb_edge = ne + 1;
    2365                 :      10353 :         return 0;
    2366                 :            : }
    2367                 :            : 
    2368                 :            : /*
    2369                 :            :  * helper function, determine type of edge between two nodes.
    2370                 :            :  */
    2371                 :            : static void
    2372                 :            : set_edge_type(struct bpf_verifier *bvf, struct inst_node *node,
    2373                 :            :         const struct inst_node *next)
    2374                 :            : {
    2375                 :            :         uint32_t ce, clr, type;
    2376                 :            : 
    2377                 :      10341 :         ce = node->cur_edge - 1;
    2378                 :      10341 :         clr = next->colour;
    2379                 :            : 
    2380                 :            :         type = UNKNOWN_EDGE;
    2381                 :            : 
    2382         [ +  + ]:      10341 :         if (clr == WHITE)
    2383                 :            :                 type = TREE_EDGE;
    2384         [ +  - ]:       2627 :         else if (clr == GREY)
    2385                 :            :                 type = BACK_EDGE;
    2386         [ +  - ]:       2627 :         else if (clr == BLACK)
    2387                 :            :                 /*
    2388                 :            :                  * in fact it could be either direct or cross edge,
    2389                 :            :                  * but for now, we don't need to distinguish between them.
    2390                 :            :                  */
    2391                 :            :                 type = CROSS_EDGE;
    2392                 :            : 
    2393                 :      10341 :         node->edge_type[ce] = type;
    2394                 :      10341 :         bvf->edge_type[type]++;
    2395                 :            : }
    2396                 :            : 
    2397                 :            : /*
    2398                 :            :  * Depth-First Search (DFS) through previously constructed
    2399                 :            :  * Control Flow Graph (CFG).
    2400                 :            :  * Information collected at this path would be used later
    2401                 :            :  * to determine is there any loops, and/or statically unreachable instructions.
    2402                 :            :  * PREREQUISITE: there is at least one node.
    2403                 :            :  */
    2404                 :            : static void
    2405                 :        834 : dfs(struct bpf_verifier *bvf)
    2406                 :            : {
    2407                 :            :         struct inst_node *next, *node;
    2408                 :            : 
    2409                 :            :         RTE_ASSERT(bvf->nb_nodes != 0);
    2410                 :            :         /*
    2411                 :            :          * Since there is at least one node, node with index 0 always exists;
    2412                 :            :          * it is our program entry point.
    2413                 :            :          */
    2414                 :        834 :         node = &bvf->in[0];
    2415                 :            :         do {
    2416                 :            : 
    2417         [ +  + ]:      16262 :                 if (node->colour == WHITE)
    2418                 :            :                         set_node_colour(bvf, node, GREY);
    2419                 :            : 
    2420         [ +  - ]:      16262 :                 if (node->colour == GREY) {
    2421                 :            : 
    2422                 :            :                         /* find next unprocessed child node */
    2423                 :            :                         do {
    2424                 :            :                                 next = get_next_node(bvf, node);
    2425         [ +  - ]:      10341 :                                 if (next == NULL)
    2426                 :            :                                         break;
    2427                 :            :                                 set_edge_type(bvf, node, next);
    2428         [ +  + ]:      10341 :                         } while (next->colour != WHITE);
    2429                 :            : 
    2430         [ +  + ]:      16262 :                         if (next != NULL) {
    2431                 :            :                                 /* proceed with next child */
    2432                 :       7714 :                                 next->prev_node = node;
    2433                 :            :                                 node = next;
    2434                 :            :                         } else {
    2435                 :            :                                 /*
    2436                 :            :                                  * finished with current node and all it's kids,
    2437                 :            :                                  * proceed with parent
    2438                 :            :                                  */
    2439                 :            :                                 set_node_colour(bvf, node, BLACK);
    2440                 :       8548 :                                 node->cur_edge = 0;
    2441                 :       8548 :                                 node = node->prev_node;
    2442                 :            :                         }
    2443                 :            :                 } else
    2444                 :            :                         node = NULL;
    2445         [ +  + ]:      16262 :         } while (node != NULL);
    2446                 :        834 : }
    2447                 :            : 
    2448                 :            : /*
    2449                 :            :  * report statically unreachable instructions.
    2450                 :            :  */
    2451                 :            : static void
    2452                 :          0 : log_unreachable(const struct bpf_verifier *bvf)
    2453                 :            : {
    2454                 :            :         uint32_t i;
    2455                 :            :         struct inst_node *node;
    2456                 :            :         const struct ebpf_insn *ins;
    2457                 :            : 
    2458         [ #  # ]:          0 :         for (i = 0; i != bvf->prm->raw.nb_ins; i++) {
    2459                 :            : 
    2460                 :          0 :                 node = bvf->in + i;
    2461                 :          0 :                 ins = bvf->prm->raw.ins + i;
    2462                 :            : 
    2463         [ #  # ]:          0 :                 if (node->colour == WHITE &&
    2464         [ #  # ]:          0 :                                 ins->code != (BPF_LD | BPF_IMM | EBPF_DW))
    2465                 :          0 :                         RTE_BPF_LOG_LINE(ERR, "unreachable code at pc: %u;", i);
    2466                 :            :         }
    2467                 :          0 : }
    2468                 :            : 
    2469                 :            : /*
    2470                 :            :  * report loops detected.
    2471                 :            :  */
    2472                 :            : static void
    2473                 :          0 : log_loop(const struct bpf_verifier *bvf)
    2474                 :            : {
    2475                 :            :         uint32_t i, j;
    2476                 :            :         struct inst_node *node;
    2477                 :            : 
    2478         [ #  # ]:          0 :         for (i = 0; i != bvf->prm->raw.nb_ins; i++) {
    2479                 :            : 
    2480                 :          0 :                 node = bvf->in + i;
    2481         [ #  # ]:          0 :                 if (node->colour != BLACK)
    2482                 :          0 :                         continue;
    2483                 :            : 
    2484         [ #  # ]:          0 :                 for (j = 0; j != node->nb_edge; j++) {
    2485         [ #  # ]:          0 :                         if (node->edge_type[j] == BACK_EDGE)
    2486                 :          0 :                                 RTE_BPF_LOG_LINE(ERR,
    2487                 :            :                                         "loop at pc:%u --> pc:%u;",
    2488                 :            :                                         i, node->edge_dest[j]);
    2489                 :            :                 }
    2490                 :            :         }
    2491                 :          0 : }
    2492                 :            : 
    2493                 :            : /*
    2494                 :            :  * First pass goes though all instructions in the set, checks that each
    2495                 :            :  * instruction is a valid one (correct syntax, valid field values, etc.)
    2496                 :            :  * and constructs control flow graph (CFG).
    2497                 :            :  * Then depth-first search is performed over the constructed graph.
    2498                 :            :  * Programs with unreachable instructions and/or loops will be rejected.
    2499                 :            :  */
    2500                 :            : static int
    2501                 :        839 : validate(struct bpf_verifier *bvf)
    2502                 :            : {
    2503                 :            :         int32_t rc;
    2504                 :            :         uint32_t i;
    2505                 :            :         struct inst_node *node;
    2506                 :            :         const struct ebpf_insn *ins;
    2507                 :            :         const char *err;
    2508                 :            : 
    2509                 :            :         rc = 0;
    2510         [ +  + ]:       9404 :         for (i = 0; i < bvf->prm->raw.nb_ins; i++) {
    2511                 :            : 
    2512                 :       8565 :                 ins = bvf->prm->raw.ins + i;
    2513                 :       8565 :                 node = bvf->in + i;
    2514                 :            : 
    2515                 :       8565 :                 err = check_syntax(ins);
    2516         [ +  + ]:       8565 :                 if (err != 0) {
    2517                 :          4 :                         RTE_BPF_LOG_FUNC_LINE(ERR, "%s at pc: %u", err, i);
    2518                 :          4 :                         rc |= -EINVAL;
    2519                 :            :                 }
    2520                 :            : 
    2521                 :            :                 /*
    2522                 :            :                  * construct CFG, jcc nodes have to outgoing edges,
    2523                 :            :                  * 'exit' nodes - none, all other nodes have exactly one
    2524                 :            :                  * outgoing edge.
    2525                 :            :                  */
    2526   [ +  +  +  +  :       8565 :                 switch (ins->code) {
                   +  + ]
    2527                 :            :                 case (BPF_JMP | EBPF_EXIT):
    2528                 :            :                         break;
    2529                 :       3010 :                 case (BPF_JMP | BPF_JEQ | BPF_K):
    2530                 :            :                 case (BPF_JMP | EBPF_JNE | BPF_K):
    2531                 :            :                 case (BPF_JMP | BPF_JGT | BPF_K):
    2532                 :            :                 case (BPF_JMP | EBPF_JLT | BPF_K):
    2533                 :            :                 case (BPF_JMP | BPF_JGE | BPF_K):
    2534                 :            :                 case (BPF_JMP | EBPF_JLE | BPF_K):
    2535                 :            :                 case (BPF_JMP | EBPF_JSGT | BPF_K):
    2536                 :            :                 case (BPF_JMP | EBPF_JSLT | BPF_K):
    2537                 :            :                 case (BPF_JMP | EBPF_JSGE | BPF_K):
    2538                 :            :                 case (BPF_JMP | EBPF_JSLE | BPF_K):
    2539                 :            :                 case (BPF_JMP | BPF_JSET | BPF_K):
    2540                 :            :                 case (BPF_JMP | BPF_JEQ | BPF_X):
    2541                 :            :                 case (BPF_JMP | EBPF_JNE | BPF_X):
    2542                 :            :                 case (BPF_JMP | BPF_JGT | BPF_X):
    2543                 :            :                 case (BPF_JMP | EBPF_JLT | BPF_X):
    2544                 :            :                 case (BPF_JMP | BPF_JGE | BPF_X):
    2545                 :            :                 case (BPF_JMP | EBPF_JLE | BPF_X):
    2546                 :            :                 case (BPF_JMP | EBPF_JSGT | BPF_X):
    2547                 :            :                 case (BPF_JMP | EBPF_JSLT | BPF_X):
    2548                 :            :                 case (BPF_JMP | EBPF_JSGE | BPF_X):
    2549                 :            :                 case (BPF_JMP | EBPF_JSLE | BPF_X):
    2550                 :            :                 case (BPF_JMP | BPF_JSET | BPF_X):
    2551                 :       3010 :                         rc |= add_edge(bvf, node, i + ins->off + 1);
    2552                 :       3010 :                         rc |= add_edge(bvf, node, i + 1);
    2553                 :       3010 :                         bvf->nb_jcc_nodes++;
    2554                 :       3010 :                         break;
    2555                 :         48 :                 case (BPF_JMP | BPF_JA):
    2556                 :         48 :                         rc |= add_edge(bvf, node, i + ins->off + 1);
    2557                 :         48 :                         break;
    2558                 :            :                 /* load 64 bit immediate value */
    2559                 :        369 :                 case (BPF_LD | BPF_IMM | EBPF_DW):
    2560                 :        369 :                         rc |= add_edge(bvf, node, i + 2);
    2561                 :        369 :                         i++;
    2562                 :        369 :                         break;
    2563                 :        488 :                 case (BPF_LD | BPF_ABS | BPF_B):
    2564                 :            :                 case (BPF_LD | BPF_ABS | BPF_H):
    2565                 :            :                 case (BPF_LD | BPF_ABS | BPF_W):
    2566                 :            :                 case (BPF_LD | BPF_IND | BPF_B):
    2567                 :            :                 case (BPF_LD | BPF_IND | BPF_H):
    2568                 :            :                 case (BPF_LD | BPF_IND | BPF_W):
    2569                 :        488 :                         bvf->nb_ldmb_nodes++;
    2570                 :            :                         /* fallthrough */
    2571                 :       3917 :                 default:
    2572                 :       3917 :                         rc |= add_edge(bvf, node, i + 1);
    2573                 :       3917 :                         break;
    2574                 :            :                 }
    2575                 :            : 
    2576                 :       8565 :                 bvf->nb_nodes++;
    2577                 :       8565 :                 bvf->node_colour[WHITE]++;
    2578                 :            :         }
    2579                 :            : 
    2580         [ +  + ]:        839 :         if (rc != 0)
    2581                 :            :                 return rc;
    2582                 :            : 
    2583         [ -  + ]:        834 :         if (bvf->nb_nodes == 0) {
    2584                 :          0 :                 RTE_BPF_LOG_LINE(ERR, "%s(%p) the program is empty",
    2585                 :            :                         __func__, bvf);
    2586                 :          0 :                 return -EINVAL;
    2587                 :            :         }
    2588                 :            : 
    2589                 :        834 :         dfs(bvf);
    2590                 :            : 
    2591                 :        834 :         RTE_LOG(DEBUG, BPF, "%s(%p) stats:\n"
    2592                 :            :                 "nb_nodes=%u;\n"
    2593                 :            :                 "nb_jcc_nodes=%u;\n"
    2594                 :            :                 "node_color={[WHITE]=%u, [GREY]=%u,, [BLACK]=%u};\n"
    2595                 :            :                 "edge_type={[UNKNOWN]=%u, [TREE]=%u, [BACK]=%u, [CROSS]=%u};\n",
    2596                 :            :                 __func__, bvf,
    2597                 :            :                 bvf->nb_nodes,
    2598                 :            :                 bvf->nb_jcc_nodes,
    2599                 :            :                 bvf->node_colour[WHITE], bvf->node_colour[GREY],
    2600                 :            :                         bvf->node_colour[BLACK],
    2601                 :            :                 bvf->edge_type[UNKNOWN_EDGE], bvf->edge_type[TREE_EDGE],
    2602                 :            :                 bvf->edge_type[BACK_EDGE], bvf->edge_type[CROSS_EDGE]);
    2603                 :            : 
    2604         [ -  + ]:        834 :         if (bvf->node_colour[BLACK] != bvf->nb_nodes) {
    2605                 :          0 :                 RTE_BPF_LOG_LINE(ERR, "%s(%p) unreachable instructions;",
    2606                 :            :                         __func__, bvf);
    2607                 :          0 :                 log_unreachable(bvf);
    2608                 :          0 :                 return -EINVAL;
    2609                 :            :         }
    2610                 :            : 
    2611   [ +  -  +  - ]:        834 :         if (bvf->node_colour[GREY] != 0 || bvf->node_colour[WHITE] != 0 ||
    2612         [ -  + ]:        834 :                         bvf->edge_type[UNKNOWN_EDGE] != 0) {
    2613                 :          0 :                 RTE_BPF_LOG_LINE(ERR, "%s(%p) DFS internal error;",
    2614                 :            :                         __func__, bvf);
    2615                 :          0 :                 return -EINVAL;
    2616                 :            :         }
    2617                 :            : 
    2618         [ -  + ]:        834 :         if (bvf->edge_type[BACK_EDGE] != 0) {
    2619                 :          0 :                 RTE_BPF_LOG_LINE(ERR, "%s(%p) loops detected;",
    2620                 :            :                         __func__, bvf);
    2621                 :          0 :                 log_loop(bvf);
    2622                 :          0 :                 return -EINVAL;
    2623                 :            :         }
    2624                 :            : 
    2625                 :            :         return 0;
    2626                 :            : }
    2627                 :            : 
    2628                 :            : /*
    2629                 :            :  * helper functions get/free eval states.
    2630                 :            :  */
    2631                 :            : static struct bpf_eval_state *
    2632                 :            : pull_eval_state(struct evst_pool *pool)
    2633                 :            : {
    2634                 :            :         uint32_t n;
    2635                 :            : 
    2636                 :       9129 :         n = pool->cur;
    2637         [ +  + ]:       5896 :         if (n == pool->num)
    2638                 :            :                 return NULL;
    2639                 :            : 
    2640                 :       9657 :         pool->cur = n + 1;
    2641                 :       5590 :         return pool->ent + n;
    2642                 :            : }
    2643                 :            : 
    2644                 :            : static void
    2645                 :            : push_eval_state(struct evst_pool *pool)
    2646                 :            : {
    2647                 :            :         RTE_ASSERT(pool->cur != 0);
    2648                 :       3233 :         pool->cur--;
    2649                 :            : }
    2650                 :            : 
    2651                 :            : static void
    2652                 :        834 : evst_pool_fini(struct bpf_verifier *bvf)
    2653                 :            : {
    2654                 :        834 :         bvf->evst = NULL;
    2655                 :        834 :         free(bvf->evst_sr_pool.ent);
    2656                 :        834 :         memset(&bvf->evst_sr_pool, 0, sizeof(bvf->evst_sr_pool));
    2657                 :        834 :         memset(&bvf->evst_tp_pool, 0, sizeof(bvf->evst_tp_pool));
    2658                 :        834 : }
    2659                 :            : 
    2660                 :            : static int
    2661                 :        834 : evst_pool_init(struct bpf_verifier *bvf)
    2662                 :            : {
    2663                 :            :         uint32_t k, n;
    2664                 :            : 
    2665         [ +  - ]:        834 :         if (bvf->nb_jcc_nodes > UINT32_MAX / 4)
    2666                 :            :                 /* Calculations that follow may overflow. */
    2667                 :            :                 return -E2BIG;
    2668                 :            : 
    2669                 :            :         /*
    2670                 :            :          * We need nb_jcc_nodes + 1 for save_cur/restore_cur
    2671                 :            :          * remaining ones will be used for state tracking/pruning.
    2672                 :            :          */
    2673                 :        834 :         k = bvf->nb_jcc_nodes + 1;
    2674                 :        834 :         n = k * 3;
    2675                 :            : 
    2676                 :        834 :         bvf->evst_sr_pool.ent = calloc(n, sizeof(bvf->evst_sr_pool.ent[0]));
    2677         [ +  - ]:        834 :         if (bvf->evst_sr_pool.ent == NULL)
    2678                 :            :                 return -ENOMEM;
    2679                 :            : 
    2680                 :        834 :         bvf->evst_sr_pool.num = k;
    2681                 :            :         bvf->evst_sr_pool.cur = 0;
    2682                 :            : 
    2683                 :        834 :         bvf->evst_tp_pool.ent = bvf->evst_sr_pool.ent + k;
    2684                 :        834 :         bvf->evst_tp_pool.num = n - k;
    2685                 :        834 :         bvf->evst_tp_pool.cur = 0;
    2686                 :            : 
    2687                 :        834 :         bvf->evst = pull_eval_state(&bvf->evst_sr_pool);
    2688                 :        834 :         return 0;
    2689                 :            : }
    2690                 :            : 
    2691                 :            : /*
    2692                 :            :  * try to allocate and initialise new eval state for given node.
    2693                 :            :  * later if no errors will be encountered, this state will be accepted as
    2694                 :            :  * one of the possible 'safe' states for that node.
    2695                 :            :  */
    2696                 :            : static void
    2697                 :       5896 : save_start_eval_state(struct bpf_verifier *bvf, struct inst_node *node)
    2698                 :            : {
    2699                 :            :         RTE_ASSERT(node->evst.start == NULL);
    2700                 :            : 
    2701                 :            :         /* limit number of states for one node with some reasonable value */
    2702         [ +  - ]:       5896 :         if (node->evst.nb_safe >= NODE_EVST_MAX)
    2703                 :            :                 return;
    2704                 :            : 
    2705                 :            :         /* try to get new eval_state */
    2706                 :       5896 :         node->evst.start = pull_eval_state(&bvf->evst_tp_pool);
    2707                 :            : 
    2708                 :            :         /* make a copy of current state */
    2709         [ +  + ]:       5896 :         if (node->evst.start != NULL) {
    2710                 :       5590 :                 memcpy(node->evst.start, bvf->evst, sizeof(*node->evst.start));
    2711                 :       5590 :                 SLIST_NEXT(node->evst.start, next) = NULL;
    2712                 :            :         }
    2713                 :            : }
    2714                 :            : 
    2715                 :            : /*
    2716                 :            :  * add @start state to the list of @safe states.
    2717                 :            :  */
    2718                 :            : static void
    2719                 :      10539 : save_safe_eval_state(struct bpf_verifier *bvf, struct inst_node *node)
    2720                 :            : {
    2721         [ +  + ]:      10539 :         if (node->evst.start == NULL)
    2722                 :            :                 return;
    2723                 :            : 
    2724                 :       5588 :         SLIST_INSERT_HEAD(&node->evst.safe, node->evst.start, next);
    2725                 :       5588 :         node->evst.nb_safe++;
    2726                 :            : 
    2727                 :       5588 :         RTE_BPF_LOG_LINE(DEBUG, "%s(bvf=%p,node=%u,state=%p): nb_safe=%u;",
    2728                 :            :                 __func__, bvf, get_node_idx(bvf, node), node->evst.start,
    2729                 :            :                 node->evst.nb_safe);
    2730                 :            : 
    2731                 :       5588 :         node->evst.start = NULL;
    2732                 :            : }
    2733                 :            : 
    2734                 :            : /*
    2735                 :            :  * Save current eval state.
    2736                 :            :  */
    2737                 :            : static int
    2738         [ +  - ]:       3233 : save_cur_eval_state(struct bpf_verifier *bvf, struct inst_node *node)
    2739                 :            : {
    2740                 :            :         struct bpf_eval_state *st;
    2741                 :            : 
    2742                 :            :         /* get new eval_state for this node */
    2743                 :            :         st = pull_eval_state(&bvf->evst_sr_pool);
    2744         [ -  + ]:       3233 :         if (st == NULL) {
    2745                 :          0 :                 RTE_BPF_LOG_FUNC_LINE(ERR,
    2746                 :            :                         "internal error (out of space) at pc: %u",
    2747                 :            :                         get_node_idx(bvf, node));
    2748                 :          0 :                 return -ENOMEM;
    2749                 :            :         }
    2750                 :            : 
    2751                 :            :         /* make a copy of current state */
    2752                 :       3233 :         memcpy(st, bvf->evst, sizeof(*st));
    2753                 :            : 
    2754                 :            :         /* swap current state with new one */
    2755                 :            :         RTE_ASSERT(node->evst.cur == NULL);
    2756                 :       3233 :         node->evst.cur = bvf->evst;
    2757                 :       3233 :         bvf->evst = st;
    2758                 :            : 
    2759                 :       3233 :         RTE_BPF_LOG_LINE(DEBUG, "%s(bvf=%p,node=%u) old/new states: %p/%p;",
    2760                 :            :                 __func__, bvf, get_node_idx(bvf, node), node->evst.cur,
    2761                 :            :                 bvf->evst);
    2762                 :            : 
    2763                 :       3233 :         return 0;
    2764                 :            : }
    2765                 :            : 
    2766                 :            : /*
    2767                 :            :  * Restore previous eval state and mark current eval state as free.
    2768                 :            :  */
    2769                 :            : static void
    2770                 :       3233 : restore_cur_eval_state(struct bpf_verifier *bvf, struct inst_node *node)
    2771                 :            : {
    2772                 :       3233 :         RTE_BPF_LOG_LINE(DEBUG, "%s(bvf=%p,node=%u) old/new states: %p/%p;",
    2773                 :            :                 __func__, bvf, get_node_idx(bvf, node), bvf->evst,
    2774                 :            :                 node->evst.cur);
    2775                 :            : 
    2776                 :       3233 :         bvf->evst = node->evst.cur;
    2777                 :       3233 :         node->evst.cur = NULL;
    2778                 :            :         push_eval_state(&bvf->evst_sr_pool);
    2779                 :       3233 : }
    2780                 :            : 
    2781                 :            : static void
    2782                 :      10766 : log_dbg_eval_state(const struct bpf_verifier *bvf, const struct ebpf_insn *ins,
    2783                 :            :         uint32_t pc)
    2784                 :            : {
    2785                 :            :         const struct bpf_eval_state *st;
    2786                 :            :         const struct bpf_reg_val *rv;
    2787                 :            : 
    2788                 :      10766 :         RTE_BPF_LOG_LINE(DEBUG, "%s(pc=%u):", __func__, pc);
    2789                 :            : 
    2790                 :      10766 :         st = bvf->evst;
    2791                 :      10766 :         rv = st->rv + ins->dst_reg;
    2792                 :            : 
    2793                 :      10766 :         RTE_LOG(DEBUG, BPF,
    2794                 :            :                 "r%u={\n"
    2795                 :            :                 "\tv={type=%u, size=%zu, buf_size=%zu},\n"
    2796                 :            :                 "\tmask=0x%" PRIx64 ",\n"
    2797                 :            :                 "\tu={min=0x%" PRIx64 ", max=0x%" PRIx64 "},\n"
    2798                 :            :                 "\ts={min=%" PRId64 ", max=%" PRId64 "},\n"
    2799                 :            :                 "};\n",
    2800                 :            :                 ins->dst_reg,
    2801                 :            :                 rv->v.type, rv->v.size, rv->v.buf_size,
    2802                 :            :                 rv->mask,
    2803                 :            :                 rv->u.min, rv->u.max,
    2804                 :            :                 rv->s.min, rv->s.max);
    2805                 :      10766 : }
    2806                 :            : 
    2807                 :            : /*
    2808                 :            :  * compare two evaluation states.
    2809                 :            :  * returns zero if @lv is more conservative (safer) then @rv.
    2810                 :            :  * returns non-zero value otherwise.
    2811                 :            :  */
    2812                 :            : static int
    2813                 :       7186 : cmp_reg_val_within(const struct bpf_reg_val *lv, const struct bpf_reg_val *rv)
    2814                 :            : {
    2815                 :            :         /* expect @v and @mask to be identical */
    2816   [ +  +  +  + ]:       7186 :         if (memcmp(&lv->v, &rv->v, sizeof(lv->v)) != 0 || lv->mask != rv->mask)
    2817                 :            :                 return -1;
    2818                 :            : 
    2819                 :            :         /* exact match only for mbuf and stack pointers */
    2820         [ +  - ]:       6860 :         if (lv->v.type == RTE_BPF_ARG_PTR_MBUF ||
    2821                 :            :                         lv->v.type == BPF_ARG_PTR_STACK)
    2822                 :            :                 return -1;
    2823                 :            : 
    2824   [ +  +  +  + ]:       6860 :         if (lv->u.min <= rv->u.min && lv->u.max >= rv->u.max &&
    2825   [ +  +  +  + ]:       2086 :                         lv->s.min <= rv->s.min && lv->s.max >= rv->s.max)
    2826                 :         28 :                 return 0;
    2827                 :            : 
    2828                 :            :         return -1;
    2829                 :            : }
    2830                 :            : 
    2831                 :            : /*
    2832                 :            :  * compare two evaluation states.
    2833                 :            :  * returns zero if they are identical.
    2834                 :            :  * returns positive value if @lv is more conservative (safer) then @rv.
    2835                 :            :  * returns negative value otherwise.
    2836                 :            :  */
    2837                 :            : static int
    2838                 :       7530 : cmp_eval_state(const struct bpf_eval_state *lv, const struct bpf_eval_state *rv)
    2839                 :            : {
    2840                 :            :         int32_t rc;
    2841                 :            :         uint32_t i, k;
    2842                 :            : 
    2843                 :            :         /* for stack expect identical values */
    2844                 :       7530 :         rc = memcmp(lv->sv, rv->sv, sizeof(lv->sv));
    2845         [ +  - ]:       7530 :         if (rc != 0)
    2846                 :            :                 return -(2 * EBPF_REG_NUM);
    2847                 :            : 
    2848                 :            :         k = 0;
    2849                 :            :         /* check register values */
    2850         [ +  + ]:      25704 :         for (i = 0; i != RTE_DIM(lv->rv); i++) {
    2851                 :      25332 :                 rc = memcmp(&lv->rv[i], &rv->rv[i], sizeof(lv->rv[i]));
    2852   [ +  +  +  + ]:      25332 :                 if (rc != 0 && cmp_reg_val_within(&lv->rv[i], &rv->rv[i]) != 0)
    2853                 :       7158 :                         return -(i + 1);
    2854                 :      18174 :                 k += (rc != 0);
    2855                 :            :         }
    2856                 :            : 
    2857                 :        372 :         return k;
    2858                 :            : }
    2859                 :            : 
    2860                 :            : /*
    2861                 :            :  * check did we already evaluated that path and can it be pruned that time.
    2862                 :            :  */
    2863                 :            : static int
    2864                 :       6268 : prune_eval_state(struct bpf_verifier *bvf, const struct inst_node *node,
    2865                 :            :         struct inst_node *next)
    2866                 :            : {
    2867                 :            :         int32_t rc;
    2868                 :            :         struct bpf_eval_state *safe;
    2869                 :            : 
    2870                 :            :         rc = INT32_MIN;
    2871         [ +  + ]:      13426 :         SLIST_FOREACH(safe, &next->evst.safe, next) {
    2872                 :       7530 :                 rc = cmp_eval_state(safe, bvf->evst);
    2873         [ +  + ]:       7530 :                 if (rc >= 0)
    2874                 :            :                         break;
    2875                 :            :         }
    2876                 :            : 
    2877         [ +  + ]:       6268 :         rc = (rc >= 0) ? 0 : -1;
    2878                 :            : 
    2879                 :            :         /*
    2880                 :            :          * current state doesn't match any safe states,
    2881                 :            :          * so no prunning is possible right now,
    2882                 :            :          * track current state for future references.
    2883                 :            :          */
    2884                 :            :         if (rc != 0)
    2885                 :       5896 :                 save_start_eval_state(bvf, next);
    2886                 :            : 
    2887                 :       6268 :         RTE_BPF_LOG_LINE(DEBUG, "%s(bvf=%p,node=%u,next=%u) returns %d, "
    2888                 :            :                 "next->evst.start=%p, next->evst.nb_safe=%u",
    2889                 :            :                 __func__, bvf, get_node_idx(bvf, node),
    2890                 :            :                 get_node_idx(bvf, next), rc,
    2891                 :            :                 next->evst.start, next->evst.nb_safe);
    2892                 :       6268 :         return rc;
    2893                 :            : }
    2894                 :            : 
    2895                 :            : /* Do second pass through CFG and try to evaluate instructions
    2896                 :            :  * via each possible path. The verifier will try all paths, tracking types of
    2897                 :            :  * registers used as input to instructions, and updating resulting type via
    2898                 :            :  * register state values. Plus for each register and possible stack value it
    2899                 :            :  * tries to estimate possible max/min value.
    2900                 :            :  * For conditional jumps, a stack is used to save evaluation state, so one
    2901                 :            :  * path is explored while the state for the other path is pushed onto the stack.
    2902                 :            :  * Then later, we backtrack to the first pushed instruction and repeat the cycle
    2903                 :            :  * until the stack is empty and we're done.
    2904                 :            :  * For program with many conditional branches walking through all possible path
    2905                 :            :  * could be very excessive. So to minimize number of evaluations we use
    2906                 :            :  * heuristic similar to what Linux kernel does - state pruning:
    2907                 :            :  * If from given instruction for given program state we explore all possible
    2908                 :            :  * paths and for each of them reach _exit() without any complaints and a valid
    2909                 :            :  * R0 value, then for that instruction, that program state can be marked as
    2910                 :            :  * 'safe'. When we later arrive at the same instruction with a state
    2911                 :            :  * equivalent to an earlier instruction's 'safe' state, we can prune the search.
    2912                 :            :  * For now, only states for JCC  targets are saved/examined.
    2913                 :            :  */
    2914                 :            : static int
    2915                 :        834 : evaluate(struct bpf_verifier *bvf)
    2916                 :            : {
    2917                 :            :         uint32_t idx, op;
    2918                 :            :         const char *err;
    2919                 :            :         const struct ebpf_insn *ins;
    2920                 :            :         struct inst_node *next, *node;
    2921                 :            :         int prev_nb_edge;  /* branching number of the previous instruction */
    2922                 :            :         int rc, debug_rc;
    2923                 :        834 :         struct rte_bpf_validate_debug *const debug = bvf->prm->debug;
    2924                 :            : 
    2925                 :            :         struct {
    2926                 :            :                 uint32_t nb_eval;
    2927                 :            :                 uint32_t nb_prune;
    2928                 :            :                 uint32_t nb_save;
    2929                 :            :                 uint32_t nb_restore;
    2930                 :            :         } stats;
    2931                 :            : 
    2932                 :            :         /* initial state of frame pointer */
    2933                 :            :         static const struct bpf_reg_val rvfp = {
    2934                 :            :                 .v = {
    2935                 :            :                         .type = BPF_ARG_PTR_STACK,
    2936                 :            :                         .size = MAX_BPF_STACK_SIZE,
    2937                 :            :                 },
    2938                 :            :                 .mask = UINT64_MAX,
    2939                 :            :                 .u = {.min = MAX_BPF_STACK_SIZE, .max = MAX_BPF_STACK_SIZE},
    2940                 :            :                 .s = {.min = MAX_BPF_STACK_SIZE, .max = MAX_BPF_STACK_SIZE},
    2941                 :            :         };
    2942                 :            : 
    2943         [ +  + ]:       1669 :         for (uint32_t pai = 0; pai != bvf->prm->nb_prog_arg; ++pai) {
    2944                 :        835 :                 struct bpf_reg_val *reg = &bvf->evst->rv[EBPF_REG_1 + pai];
    2945                 :            : 
    2946                 :        835 :                 reg->v = bvf->prm->prog_arg[pai];
    2947                 :        835 :                 reg->mask = UINT64_MAX;
    2948         [ +  + ]:        835 :                 if (reg->v.type == RTE_BPF_ARG_RAW)
    2949                 :            :                         eval_max_bound(reg, UINT64_MAX);
    2950                 :            :         }
    2951                 :            : 
    2952                 :        834 :         bvf->evst->rv[EBPF_REG_10] = rvfp;
    2953                 :            : 
    2954                 :        834 :         ins = bvf->prm->raw.ins;
    2955                 :        834 :         node = bvf->in;
    2956                 :            :         next = node;
    2957                 :            :         prev_nb_edge = 1;
    2958                 :            : 
    2959                 :            :         memset(&stats, 0, sizeof(stats));
    2960                 :            : 
    2961                 :        834 :         rc = __rte_bpf_validate_debug_evaluate_start(debug, bvf, bvf->prm);
    2962         [ +  - ]:        834 :         if (rc < 0)
    2963                 :            :                 return rc;
    2964                 :            : 
    2965         [ +  + ]:      22102 :         while (node != NULL) {
    2966                 :            :                 /*
    2967                 :            :                  * current node evaluation, make sure we evaluate
    2968                 :            :                  * each node only once.
    2969                 :            :                  */
    2970         [ +  + ]:      21495 :                 if (next != NULL) {
    2971                 :            :                         /* just started or stepped down the tree, node == next */
    2972                 :            : 
    2973                 :      10993 :                         bvf->evin = node;
    2974                 :            :                         idx = get_node_idx(bvf, node);
    2975                 :      10993 :                         op = ins[idx].code;
    2976                 :            : 
    2977                 :            :                         /* for jcc node make a copy of evaluation state */
    2978         [ +  + ]:      10993 :                         if (node->nb_edge > 1) {
    2979                 :       3233 :                                 rc = save_cur_eval_state(bvf, node);
    2980         [ +  - ]:       3233 :                                 if (rc < 0)
    2981                 :            :                                         break;
    2982                 :       3233 :                                 stats.nb_save++;
    2983                 :            :                         }
    2984                 :            : 
    2985         [ -  + ]:      10993 :                         if (ins_chk[op].eval == NULL) {
    2986                 :          0 :                                 RTE_BPF_LOG_FUNC_LINE(ERR,
    2987                 :            :                                         "Unrecognized instruction at pc: %u", idx);
    2988                 :            :                                 rc = -EINVAL;
    2989                 :          0 :                                 break;
    2990                 :            :                         }
    2991                 :            : 
    2992         [ +  + ]:      16090 :                         rc = __rte_bpf_validate_debug_evaluate_step(debug, idx,
    2993                 :            :                                 prev_nb_edge > 1 ?
    2994                 :            :                                         RTE_BPF_VALIDATE_DEBUG_EVENT_BRANCH_ENTER :
    2995                 :            :                                         RTE_BPF_VALIDATE_DEBUG_EVENT_STEP);
    2996         [ +  - ]:      10993 :                         if (rc < 0)
    2997                 :            :                                 break;
    2998                 :            : 
    2999                 :      10993 :                         err = ins_chk[op].eval(bvf, ins + idx);
    3000                 :      10993 :                         stats.nb_eval++;
    3001         [ +  + ]:      10993 :                         if (err != NULL) {
    3002                 :        227 :                                 RTE_BPF_LOG_FUNC_LINE(ERR,
    3003                 :            :                                         "%s at pc: %u", err, idx);
    3004                 :            :                                 rc = -EINVAL;
    3005                 :        227 :                                 break;
    3006                 :            :                         }
    3007                 :            : 
    3008                 :      10766 :                         log_dbg_eval_state(bvf, ins + idx, idx);
    3009                 :      10766 :                         bvf->evin = NULL;
    3010                 :            :                 }
    3011                 :            : 
    3012                 :            :                 /* proceed through CFG */
    3013                 :            :                 next = get_next_node(bvf, node);
    3014                 :            : 
    3015         [ +  - ]:      10729 :                 if (next != NULL) {
    3016                 :            :                         /*
    3017                 :            :                          * proceed with next child
    3018                 :            :                          * next points to an unwalked subtree of node
    3019                 :            :                          */
    3020         [ +  + ]:      10729 :                         if (node->cur_edge == node->nb_edge &&
    3021         [ +  + ]:       7496 :                                         node->evst.cur != NULL) {
    3022                 :       3233 :                                 restore_cur_eval_state(bvf, node);
    3023                 :       3233 :                                 stats.nb_restore++;
    3024                 :            :                         }
    3025                 :            : 
    3026         [ +  + ]:      10729 :                         if (bvf->evst->unreachable) {
    3027                 :        198 :                                 rc = __rte_bpf_validate_debug_evaluate_step(
    3028                 :            :                                         debug, get_node_idx(bvf, next),
    3029                 :            :                                         RTE_BPF_VALIDATE_DEBUG_EVENT_BRANCH_UNREACHABLE);
    3030         [ +  - ]:        198 :                                 if (rc < 0)
    3031                 :            :                                         break;
    3032                 :            : 
    3033                 :            :                                 next = NULL;
    3034                 :            :                         /*
    3035                 :            :                          * for jcc targets: check did we already evaluated
    3036                 :            :                          * that path and can it's evaluation be skipped that
    3037                 :            :                          * time.
    3038                 :            :                          */
    3039   [ +  +  +  + ]:      16799 :                         } else if (node->nb_edge > 1 &&
    3040                 :       6268 :                                         prune_eval_state(bvf, node, next) == 0) {
    3041                 :        372 :                                 rc = __rte_bpf_validate_debug_evaluate_step(
    3042                 :            :                                         debug, get_node_idx(bvf, next),
    3043                 :            :                                         RTE_BPF_VALIDATE_DEBUG_EVENT_BRANCH_PRUNE);
    3044         [ +  - ]:        372 :                                 if (rc < 0)
    3045                 :            :                                         break;
    3046                 :            : 
    3047                 :            :                                 next = NULL;
    3048                 :        372 :                                 stats.nb_prune++;
    3049                 :            :                         } else {
    3050                 :      10159 :                                 next->prev_node = node;
    3051                 :      10159 :                                 prev_nb_edge = node->nb_edge;
    3052                 :            :                                 node = next;
    3053                 :            :                         }
    3054                 :            :                 } else {
    3055                 :            :                         /*
    3056                 :            :                          * finished with current node and all it's kids,
    3057                 :            :                          * mark it's @start state as safe for future references,
    3058                 :            :                          * and proceed with parent.
    3059                 :            :                          */
    3060                 :            : 
    3061         [ +  + ]:      10539 :                         if (prev_nb_edge != 0) {
    3062                 :       3356 :                                 rc = __rte_bpf_validate_debug_evaluate_step(
    3063                 :            :                                         debug, get_node_idx(bvf, node) + 1,
    3064                 :            :                                         RTE_BPF_VALIDATE_DEBUG_EVENT_BRANCH_RETURN);
    3065         [ +  - ]:       3356 :                                 if (rc < 0)
    3066                 :            :                                         break;
    3067                 :            :                         }
    3068                 :            : 
    3069                 :      10539 :                         node->cur_edge = 0;
    3070                 :      10539 :                         save_safe_eval_state(bvf, node);
    3071                 :            :                         prev_nb_edge = 0;
    3072                 :      10539 :                         node = node->prev_node;
    3073                 :            : 
    3074                 :            :                         /* first node will not have prev, signalling finish */
    3075                 :            :                 }
    3076                 :            : 
    3077                 :            :                 /*
    3078                 :            :                  * next != NULL: stepped down the tree, node == next;
    3079                 :            :                  * next == NULL: stepped up after processing or pruning subtree;
    3080                 :            :                  */
    3081                 :            :         }
    3082                 :            : 
    3083                 :        834 :         RTE_LOG(DEBUG, BPF, "%s(%p) returns %d, stats:\n"
    3084                 :            :                 "node evaluations=%u;\n"
    3085                 :            :                 "state pruned=%u;\n"
    3086                 :            :                 "state saves=%u;\n"
    3087                 :            :                 "state restores=%u;\n",
    3088                 :            :                 __func__, bvf, rc,
    3089                 :            :                 stats.nb_eval, stats.nb_prune, stats.nb_save, stats.nb_restore);
    3090                 :            : 
    3091                 :        834 :         debug_rc = __rte_bpf_validate_debug_evaluate_finish(debug, rc);
    3092         [ +  - ]:        834 :         rc = debug_rc < 0 ? debug_rc : rc;
    3093                 :            : 
    3094                 :            :         /* Caller does not expect positive values. */
    3095                 :        834 :         return RTE_MIN(0, rc);
    3096                 :            : }
    3097                 :            : 
    3098                 :            : static bool
    3099                 :        840 : prog_arg_is_valid(const struct rte_bpf_arg *prog_arg)
    3100                 :            : {
    3101                 :            :         /* check input argument type, don't allow mbuf ptr on 32-bit */
    3102         [ +  + ]:        840 :         if (prog_arg->type != RTE_BPF_ARG_RAW &&
    3103         [ -  + ]:         59 :                         prog_arg->type != RTE_BPF_ARG_PTR &&
    3104                 :            :                         (sizeof(uint64_t) != sizeof(uintptr_t) ||
    3105                 :            :                         prog_arg->type != RTE_BPF_ARG_PTR_MBUF)) {
    3106                 :          0 :                 RTE_BPF_LOG_FUNC_LINE(ERR, "unsupported argument type");
    3107                 :          0 :                 return false;
    3108                 :            :         }
    3109                 :            : 
    3110                 :            :         return true;
    3111                 :            : }
    3112                 :            : 
    3113                 :            : int
    3114                 :        839 : __rte_bpf_validate(const struct rte_bpf_prm_ex *prm, uint32_t *stack_sz)
    3115                 :            : {
    3116                 :            :         int32_t rc;
    3117                 :            :         struct bpf_verifier bvf;
    3118                 :            : 
    3119         [ -  + ]:        839 :         if (prm->nb_prog_arg > EBPF_FUNC_MAX_ARGS) {
    3120                 :          0 :                 RTE_BPF_LOG_FUNC_LINE(ERR,
    3121                 :            :                         "support up to %u arguments, found %u",
    3122                 :            :                         EBPF_FUNC_MAX_ARGS, prm->nb_prog_arg);
    3123                 :          0 :                 return -ENOTSUP;
    3124                 :            :         }
    3125                 :            : 
    3126         [ +  + ]:       1679 :         for (uint32_t pai = 0; pai != prm->nb_prog_arg; ++pai)
    3127         [ -  + ]:        840 :                 if (!prog_arg_is_valid(&prm->prog_arg[pai])) {
    3128                 :          0 :                         RTE_BPF_LOG_FUNC_LINE(ERR,
    3129                 :            :                                 "unsupported argument %d (r%d) type",
    3130                 :            :                                 pai, EBPF_REG_1 + pai);
    3131                 :          0 :                         return -ENOTSUP;
    3132                 :            :                 }
    3133                 :            : 
    3134                 :            :         memset(&bvf, 0, sizeof(bvf));
    3135                 :        839 :         bvf.prm = prm;
    3136                 :        839 :         bvf.in = calloc(prm->raw.nb_ins, sizeof(bvf.in[0]));
    3137         [ +  - ]:        839 :         if (bvf.in == NULL)
    3138                 :            :                 return -ENOMEM;
    3139                 :            : 
    3140                 :        839 :         rc = validate(&bvf);
    3141                 :            : 
    3142         [ +  + ]:        839 :         if (rc == 0) {
    3143                 :        834 :                 rc = evst_pool_init(&bvf);
    3144         [ +  - ]:        834 :                 if (rc == 0)
    3145                 :        834 :                         rc = evaluate(&bvf);
    3146                 :        834 :                 evst_pool_fini(&bvf);
    3147                 :            :         }
    3148                 :            : 
    3149                 :        839 :         free(bvf.in);
    3150                 :            : 
    3151                 :            :         /* copy collected info */
    3152         [ +  + ]:        839 :         if (rc == 0) {
    3153                 :        607 :                 *stack_sz = bvf.stack_sz;
    3154                 :            : 
    3155                 :            :                 /* for LD_ABS/LD_IND, we'll need extra space on the stack */
    3156         [ +  + ]:        607 :                 if (bvf.nb_ldmb_nodes != 0)
    3157                 :         57 :                         *stack_sz = RTE_ALIGN_CEIL(*stack_sz +
    3158                 :            :                                 sizeof(uint64_t), sizeof(uint64_t));
    3159                 :            :         }
    3160                 :            : 
    3161                 :            :         return rc;
    3162                 :            : }

Generated by: LCOV version 1.14