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 *
bpf_load(const struct rte_bpf_prm * prm)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
bpf_check_xsym(const struct rte_bpf_xsym * xsym)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 *
rte_bpf_load(const struct rte_bpf_prm * prm)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_LINE(ERR, "%s: %d-th xsym is invalid", __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 = __rte_bpf_validate(bpf);
112 if (rc == 0) {
113 __rte_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