1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <errno.h> 8 #include <stdint.h> 9 10 #include <rte_log.h> 11 #include <rte_errno.h> 12 13 #include "bpf_impl.h" 14 15 static struct rte_bpf * 16 bpf_load(const struct rte_bpf_prm *prm) 17 { 18 uint8_t *buf; 19 struct rte_bpf *bpf; 20 size_t sz, bsz, insz, xsz; 21 22 xsz = prm->nb_xsym * sizeof(prm->xsym[0]); 23 insz = prm->nb_ins * sizeof(prm->ins[0]); 24 bsz = sizeof(bpf[0]); 25 sz = insz + xsz + bsz; 26 27 buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, 28 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 29 if (buf == MAP_FAILED) 30 return NULL; 31 32 bpf = (void *)buf; 33 bpf->sz = sz; 34 35 memcpy(&bpf->prm, prm, sizeof(bpf->prm)); 36 37 memcpy(buf + bsz, prm->xsym, xsz); 38 memcpy(buf + bsz + xsz, prm->ins, insz); 39 40 bpf->prm.xsym = (void *)(buf + bsz); 41 bpf->prm.ins = (void *)(buf + bsz + xsz); 42 43 return bpf; 44 } 45 46 /* 47 * Check that user provided external symbol. 48 */ 49 static int 50 bpf_check_xsym(const struct rte_bpf_xsym *xsym) 51 { 52 uint32_t i; 53 54 if (xsym->name == NULL) 55 return -EINVAL; 56 57 if (xsym->type == RTE_BPF_XTYPE_VAR) { 58 if (xsym->var.desc.type == RTE_BPF_ARG_UNDEF) 59 return -EINVAL; 60 } else if (xsym->type == RTE_BPF_XTYPE_FUNC) { 61 62 if (xsym->func.nb_args > EBPF_FUNC_MAX_ARGS) 63 return -EINVAL; 64 65 /* check function arguments */ 66 for (i = 0; i != xsym->func.nb_args; i++) { 67 if (xsym->func.args[i].type == RTE_BPF_ARG_UNDEF) 68 return -EINVAL; 69 } 70 71 /* check return value info */ 72 if (xsym->func.ret.type != RTE_BPF_ARG_UNDEF && 73 xsym->func.ret.size == 0) 74 return -EINVAL; 75 } else 76 return -EINVAL; 77 78 return 0; 79 } 80 81 struct rte_bpf * 82 rte_bpf_load(const struct rte_bpf_prm *prm) 83 { 84 struct rte_bpf *bpf; 85 int32_t rc; 86 uint32_t i; 87 88 if (prm == NULL || prm->ins == NULL || 89 (prm->nb_xsym != 0 && prm->xsym == NULL)) { 90 rte_errno = EINVAL; 91 return NULL; 92 } 93 94 rc = 0; 95 for (i = 0; i != prm->nb_xsym && rc == 0; i++) 96 rc = bpf_check_xsym(prm->xsym + i); 97 98 if (rc != 0) { 99 rte_errno = -rc; 100 RTE_BPF_LOG(ERR, "%s: %d-th xsym is invalid\n", __func__, i); 101 return NULL; 102 } 103 104 bpf = bpf_load(prm); 105 if (bpf == NULL) { 106 rte_errno = ENOMEM; 107 return NULL; 108 } 109 110 rc = bpf_validate(bpf); 111 if (rc == 0) { 112 bpf_jit(bpf); 113 if (mprotect(bpf, bpf->sz, PROT_READ) != 0) 114 rc = -ENOMEM; 115 } 116 117 if (rc != 0) { 118 rte_bpf_destroy(bpf); 119 rte_errno = -rc; 120 return NULL; 121 } 122 123 return bpf; 124 } 125