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 if (xsz > 0) 38 memcpy(buf + bsz, prm->xsym, xsz); 39 memcpy(buf + bsz + xsz, prm->ins, insz); 40 41 bpf->prm.xsym = (void *)(buf + bsz); 42 bpf->prm.ins = (void *)(buf + bsz + xsz); 43 44 return bpf; 45 } 46 47 /* 48 * Check that user provided external symbol. 49 */ 50 static int 51 bpf_check_xsym(const struct rte_bpf_xsym *xsym) 52 { 53 uint32_t i; 54 55 if (xsym->name == NULL) 56 return -EINVAL; 57 58 if (xsym->type == RTE_BPF_XTYPE_VAR) { 59 if (xsym->var.desc.type == RTE_BPF_ARG_UNDEF) 60 return -EINVAL; 61 } else if (xsym->type == RTE_BPF_XTYPE_FUNC) { 62 63 if (xsym->func.nb_args > EBPF_FUNC_MAX_ARGS) 64 return -EINVAL; 65 66 /* check function arguments */ 67 for (i = 0; i != xsym->func.nb_args; i++) { 68 if (xsym->func.args[i].type == RTE_BPF_ARG_UNDEF) 69 return -EINVAL; 70 } 71 72 /* check return value info */ 73 if (xsym->func.ret.type != RTE_BPF_ARG_UNDEF && 74 xsym->func.ret.size == 0) 75 return -EINVAL; 76 } else 77 return -EINVAL; 78 79 return 0; 80 } 81 82 struct rte_bpf * 83 rte_bpf_load(const struct rte_bpf_prm *prm) 84 { 85 struct rte_bpf *bpf; 86 int32_t rc; 87 uint32_t i; 88 89 if (prm == NULL || prm->ins == NULL || 90 (prm->nb_xsym != 0 && prm->xsym == NULL)) { 91 rte_errno = EINVAL; 92 return NULL; 93 } 94 95 rc = 0; 96 for (i = 0; i != prm->nb_xsym && rc == 0; i++) 97 rc = bpf_check_xsym(prm->xsym + i); 98 99 if (rc != 0) { 100 rte_errno = -rc; 101 RTE_BPF_LOG(ERR, "%s: %d-th xsym is invalid\n", __func__, i); 102 return NULL; 103 } 104 105 bpf = bpf_load(prm); 106 if (bpf == NULL) { 107 rte_errno = ENOMEM; 108 return NULL; 109 } 110 111 rc = bpf_validate(bpf); 112 if (rc == 0) { 113 bpf_jit(bpf); 114 if (mprotect(bpf, bpf->sz, PROT_READ) != 0) 115 rc = -ENOMEM; 116 } 117 118 if (rc != 0) { 119 rte_bpf_destroy(bpf); 120 rte_errno = -rc; 121 return NULL; 122 } 123 124 return bpf; 125 } 126