]> git.droids-corp.org - dpdk.git/commitdiff
bpf: add extra information for external symbol definitions
authorKonstantin Ananyev <konstantin.ananyev@intel.com>
Fri, 8 Jun 2018 08:42:33 +0000 (09:42 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Thu, 12 Jul 2018 07:37:16 +0000 (09:37 +0200)
Extend struct rte_bpf_xsym with new fields to provide information about:
 - for variables - type and size
 - for functions - number of arguments and type/size of each argument
   and return value

Such information would allow validate code to perform
more extensive checking on input BPF program and catch
misbehaving BPF code.

That change would cause ABI/API breakage for librte_bpf.

Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
app/test-pmd/bpf_cmd.c
lib/librte_bpf/bpf_def.h
lib/librte_bpf/bpf_exec.c
lib/librte_bpf/bpf_impl.h
lib/librte_bpf/bpf_jit_x86.c
lib/librte_bpf/bpf_load.c
lib/librte_bpf/bpf_load_elf.c
lib/librte_bpf/rte_bpf.h
test/test/test_bpf.c

index 584fad908cabcfabef7c540c43ed17d980f160a3..830bfc13a5208bbec84027471c5e8b3ee0076276 100644 (file)
@@ -19,12 +19,35 @@ static const struct rte_bpf_xsym bpf_xsym[] = {
        {
                .name = RTE_STR(stdout),
                .type = RTE_BPF_XTYPE_VAR,
-               .var = &stdout,
+               .var = {
+                       .val = &stdout,
+                       .desc = {
+                               .type = RTE_BPF_ARG_PTR,
+                               .size = sizeof(stdout),
+                       },
+               },
        },
        {
                .name = RTE_STR(rte_pktmbuf_dump),
                .type = RTE_BPF_XTYPE_FUNC,
-               .func = (void *)rte_pktmbuf_dump,
+               .func = {
+                       .val = (void *)rte_pktmbuf_dump,
+                       .nb_args = 3,
+                       .args = {
+                               [0] = {
+                                       .type = RTE_BPF_ARG_RAW,
+                                       .size = sizeof(uintptr_t),
+                               },
+                               [1] = {
+                                       .type = RTE_BPF_ARG_PTR_MBUF,
+                                       .size = sizeof(struct rte_mbuf),
+                               },
+                               [2] = {
+                                       .type = RTE_BPF_ARG_RAW,
+                                       .size = sizeof(uint32_t),
+                               },
+                       },
+               },
        },
 };
 
index 6b69de345618caa08d2d933a0b986b803118982d..c10f3aec46e7de877696b0b09257333cbd0e4d28 100644 (file)
@@ -131,6 +131,11 @@ struct ebpf_insn {
        int32_t imm;
 };
 
+/*
+ * eBPF allows functions with R1-R5 as arguments.
+ */
+#define        EBPF_FUNC_MAX_ARGS      (EBPF_REG_6 - EBPF_REG_1)
+
 #ifdef __cplusplus
 }
 #endif
index e373b1f3dc03bd3d12567f3f475d81e588b2a760..6a79139c0d07fbc7030159c985e38d71572c18be 100644 (file)
@@ -402,7 +402,7 @@ bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
                        break;
                /* call instructions */
                case (BPF_JMP | EBPF_CALL):
-                       reg[EBPF_REG_0] = bpf->prm.xsym[ins->imm].func(
+                       reg[EBPF_REG_0] = bpf->prm.xsym[ins->imm].func.val(
                                reg[EBPF_REG_1], reg[EBPF_REG_2],
                                reg[EBPF_REG_3], reg[EBPF_REG_4],
                                reg[EBPF_REG_5]);
index 5d7e65c310ce9bf73cb0a22c62f06008dcf4e350..b577e2cbe9b2d540910cf782da40cb8f92590c53 100644 (file)
@@ -34,6 +34,20 @@ extern int rte_bpf_logtype;
 #define        RTE_BPF_LOG(lvl, fmt, args...) \
        rte_log(RTE_LOG_## lvl, rte_bpf_logtype, fmt, ##args)
 
+static inline size_t
+bpf_size(uint32_t bpf_op_sz)
+{
+       if (bpf_op_sz == BPF_B)
+               return sizeof(uint8_t);
+       else if (bpf_op_sz == BPF_H)
+               return sizeof(uint16_t);
+       else if (bpf_op_sz == BPF_W)
+               return sizeof(uint32_t);
+       else if (bpf_op_sz == EBPF_DW)
+               return sizeof(uint64_t);
+       return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
index 111e028d213bd13b47c4862f7281b58157ecb191..68ea389f23ac5e02c2ef431a48227dd388d1f935 100644 (file)
@@ -113,20 +113,6 @@ union bpf_jit_imm {
        uint8_t u8[4];
 };
 
-static size_t
-bpf_size(uint32_t bpf_op_sz)
-{
-       if (bpf_op_sz == BPF_B)
-               return sizeof(uint8_t);
-       else if (bpf_op_sz == BPF_H)
-               return sizeof(uint16_t);
-       else if (bpf_op_sz == BPF_W)
-               return sizeof(uint32_t);
-       else if (bpf_op_sz == EBPF_DW)
-               return sizeof(uint64_t);
-       return 0;
-}
-
 /*
  * In many cases for imm8 we can produce shorter code.
  */
@@ -1294,7 +1280,8 @@ emit(struct bpf_jit_state *st, const struct rte_bpf *bpf)
                        break;
                /* call instructions */
                case (BPF_JMP | EBPF_CALL):
-                       emit_call(st, (uintptr_t)bpf->prm.xsym[ins->imm].func);
+                       emit_call(st,
+                               (uintptr_t)bpf->prm.xsym[ins->imm].func.val);
                        break;
                /* return instruction */
                case (BPF_JMP | EBPF_EXIT):
index d1c9abd7f0b4f2e9154d851dcffb56d3bd73928b..2b84fe7244597f9aef7ae1e8ef8a5f61ee13cd77 100644 (file)
@@ -51,17 +51,64 @@ bpf_load(const struct rte_bpf_prm *prm)
        return bpf;
 }
 
+/*
+ * Check that user provided external symbol.
+ */
+static int
+bpf_check_xsym(const struct rte_bpf_xsym *xsym)
+{
+       uint32_t i;
+
+       if (xsym->name == NULL)
+               return -EINVAL;
+
+       if (xsym->type == RTE_BPF_XTYPE_VAR) {
+               if (xsym->var.desc.type == RTE_BPF_ARG_UNDEF)
+                       return -EINVAL;
+       } else if (xsym->type == RTE_BPF_XTYPE_FUNC) {
+
+               if (xsym->func.nb_args > EBPF_FUNC_MAX_ARGS)
+                       return -EINVAL;
+
+               /* check function arguments */
+               for (i = 0; i != xsym->func.nb_args; i++) {
+                       if (xsym->func.args[i].type == RTE_BPF_ARG_UNDEF)
+                               return -EINVAL;
+               }
+
+               /* check return value info */
+               if (xsym->func.ret.type != RTE_BPF_ARG_UNDEF &&
+                               xsym->func.ret.size == 0)
+                       return -EINVAL;
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
 __rte_experimental struct rte_bpf *
 rte_bpf_load(const struct rte_bpf_prm *prm)
 {
        struct rte_bpf *bpf;
        int32_t rc;
+       uint32_t i;
 
-       if (prm == NULL || prm->ins == NULL) {
+       if (prm == NULL || prm->ins == NULL ||
+                       (prm->nb_xsym != 0 && prm->xsym == NULL)) {
                rte_errno = EINVAL;
                return NULL;
        }
 
+       rc = 0;
+       for (i = 0; i != prm->nb_xsym && rc == 0; i++)
+               rc = bpf_check_xsym(prm->xsym + i);
+
+       if (rc != 0) {
+               rte_errno = -rc;
+               RTE_BPF_LOG(ERR, "%s: %d-th xsym is invalid\n", __func__, i);
+               return NULL;
+       }
+
        bpf = bpf_load(prm);
        if (bpf == NULL) {
                rte_errno = ENOMEM;
index 6ab03d86e3e91a83d71e309e6a658bd10849c8b2..96d3630fe75bc361e0d8c20380df7562651b4bf2 100644 (file)
@@ -81,9 +81,9 @@ resolve_xsym(const char *sn, size_t ofs, struct ebpf_insn *ins, size_t ins_sz,
                ins[idx].imm = fidx;
        /* for variable we need to store its absolute address */
        else {
-               ins[idx].imm = (uintptr_t)prm->xsym[fidx].var;
+               ins[idx].imm = (uintptr_t)prm->xsym[fidx].var.val;
                ins[idx + 1].imm =
-                       (uint64_t)(uintptr_t)prm->xsym[fidx].var >> 32;
+                       (uint64_t)(uintptr_t)prm->xsym[fidx].var.val >> 32;
        }
 
        return 0;
index 1249a992c539a67441a70c9fca26c9aedcf4de46..ad62ef2c65cadfb705eac51f2b47fb8f42721ec0 100644 (file)
@@ -40,7 +40,11 @@ enum rte_bpf_arg_type {
  */
 struct rte_bpf_arg {
        enum rte_bpf_arg_type type;
-       size_t size;     /**< for pointer types, size of data it points to */
+       /**
+        * for ptr type - max size of data buffer it points to
+        * for raw type - the size (in bytes) of the value
+        */
+       size_t size;
        size_t buf_size;
        /**< for mbuf ptr type, max size of rte_mbuf data buffer */
 };
@@ -66,10 +70,19 @@ struct rte_bpf_xsym {
        const char *name;        /**< name */
        enum rte_bpf_xtype type; /**< type */
        union {
-               uint64_t (*func)(uint64_t, uint64_t, uint64_t,
+               struct {
+                       uint64_t (*val)(uint64_t, uint64_t, uint64_t,
                                uint64_t, uint64_t);
-               void *var;
-       }; /**< value */
+                       uint32_t nb_args;
+                       struct rte_bpf_arg args[EBPF_FUNC_MAX_ARGS];
+                       /**< Function arguments descriptions. */
+                       struct rte_bpf_arg ret; /**< function return value. */
+               } func;
+               struct {
+                       void *val; /**< actual memory location */
+                       struct rte_bpf_arg desc; /**< type, size, etc. */
+               } var; /**< external variable */
+       };
 };
 
 /**
index cbd6be63d7ebd016d920f32efc76bf8dee376e09..1e9caef95a6257974a989a4d56da534ffbff2c87 100644 (file)
@@ -1530,7 +1530,24 @@ static const struct rte_bpf_xsym test_call1_xsym[] = {
        {
                .name = RTE_STR(dummy_func1),
                .type = RTE_BPF_XTYPE_FUNC,
-               .func = (void *)dummy_func1,
+               .func = {
+                       .val = (void *)dummy_func1,
+                       .nb_args = 3,
+                       .args = {
+                               [0] = {
+                                       .type = RTE_BPF_ARG_PTR,
+                                       .size = sizeof(struct dummy_offset),
+                               },
+                               [1] = {
+                                       .type = RTE_BPF_ARG_PTR,
+                                       .size = sizeof(uint32_t),
+                               },
+                               [2] = {
+                                       .type = RTE_BPF_ARG_PTR,
+                                       .size = sizeof(uint64_t),
+                               },
+                       },
+               },
        },
 };