199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2018 Intel Corporation
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson
599a2dd95SBruce Richardson #include <stdio.h>
699a2dd95SBruce Richardson #include <string.h>
799a2dd95SBruce Richardson #include <errno.h>
899a2dd95SBruce Richardson #include <stdint.h>
999a2dd95SBruce Richardson
1099a2dd95SBruce Richardson #include <rte_log.h>
1199a2dd95SBruce Richardson #include <rte_errno.h>
1299a2dd95SBruce Richardson
1399a2dd95SBruce Richardson #include "bpf_impl.h"
1499a2dd95SBruce Richardson
1599a2dd95SBruce Richardson static struct rte_bpf *
bpf_load(const struct rte_bpf_prm * prm)1699a2dd95SBruce Richardson bpf_load(const struct rte_bpf_prm *prm)
1799a2dd95SBruce Richardson {
1899a2dd95SBruce Richardson uint8_t *buf;
1999a2dd95SBruce Richardson struct rte_bpf *bpf;
2099a2dd95SBruce Richardson size_t sz, bsz, insz, xsz;
2199a2dd95SBruce Richardson
2299a2dd95SBruce Richardson xsz = prm->nb_xsym * sizeof(prm->xsym[0]);
2399a2dd95SBruce Richardson insz = prm->nb_ins * sizeof(prm->ins[0]);
2499a2dd95SBruce Richardson bsz = sizeof(bpf[0]);
2599a2dd95SBruce Richardson sz = insz + xsz + bsz;
2699a2dd95SBruce Richardson
2799a2dd95SBruce Richardson buf = mmap(NULL, sz, PROT_READ | PROT_WRITE,
2899a2dd95SBruce Richardson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2999a2dd95SBruce Richardson if (buf == MAP_FAILED)
3099a2dd95SBruce Richardson return NULL;
3199a2dd95SBruce Richardson
3299a2dd95SBruce Richardson bpf = (void *)buf;
3399a2dd95SBruce Richardson bpf->sz = sz;
3499a2dd95SBruce Richardson
3599a2dd95SBruce Richardson memcpy(&bpf->prm, prm, sizeof(bpf->prm));
3699a2dd95SBruce Richardson
3708329596SHenning Schild if (xsz > 0)
3899a2dd95SBruce Richardson memcpy(buf + bsz, prm->xsym, xsz);
3999a2dd95SBruce Richardson memcpy(buf + bsz + xsz, prm->ins, insz);
4099a2dd95SBruce Richardson
4199a2dd95SBruce Richardson bpf->prm.xsym = (void *)(buf + bsz);
4299a2dd95SBruce Richardson bpf->prm.ins = (void *)(buf + bsz + xsz);
4399a2dd95SBruce Richardson
4499a2dd95SBruce Richardson return bpf;
4599a2dd95SBruce Richardson }
4699a2dd95SBruce Richardson
4799a2dd95SBruce Richardson /*
4899a2dd95SBruce Richardson * Check that user provided external symbol.
4999a2dd95SBruce Richardson */
5099a2dd95SBruce Richardson static int
bpf_check_xsym(const struct rte_bpf_xsym * xsym)5199a2dd95SBruce Richardson bpf_check_xsym(const struct rte_bpf_xsym *xsym)
5299a2dd95SBruce Richardson {
5399a2dd95SBruce Richardson uint32_t i;
5499a2dd95SBruce Richardson
5599a2dd95SBruce Richardson if (xsym->name == NULL)
5699a2dd95SBruce Richardson return -EINVAL;
5799a2dd95SBruce Richardson
5899a2dd95SBruce Richardson if (xsym->type == RTE_BPF_XTYPE_VAR) {
5999a2dd95SBruce Richardson if (xsym->var.desc.type == RTE_BPF_ARG_UNDEF)
6099a2dd95SBruce Richardson return -EINVAL;
6199a2dd95SBruce Richardson } else if (xsym->type == RTE_BPF_XTYPE_FUNC) {
6299a2dd95SBruce Richardson
6399a2dd95SBruce Richardson if (xsym->func.nb_args > EBPF_FUNC_MAX_ARGS)
6499a2dd95SBruce Richardson return -EINVAL;
6599a2dd95SBruce Richardson
6699a2dd95SBruce Richardson /* check function arguments */
6799a2dd95SBruce Richardson for (i = 0; i != xsym->func.nb_args; i++) {
6899a2dd95SBruce Richardson if (xsym->func.args[i].type == RTE_BPF_ARG_UNDEF)
6999a2dd95SBruce Richardson return -EINVAL;
7099a2dd95SBruce Richardson }
7199a2dd95SBruce Richardson
7299a2dd95SBruce Richardson /* check return value info */
7399a2dd95SBruce Richardson if (xsym->func.ret.type != RTE_BPF_ARG_UNDEF &&
7499a2dd95SBruce Richardson xsym->func.ret.size == 0)
7599a2dd95SBruce Richardson return -EINVAL;
7699a2dd95SBruce Richardson } else
7799a2dd95SBruce Richardson return -EINVAL;
7899a2dd95SBruce Richardson
7999a2dd95SBruce Richardson return 0;
8099a2dd95SBruce Richardson }
8199a2dd95SBruce Richardson
8299a2dd95SBruce Richardson struct rte_bpf *
rte_bpf_load(const struct rte_bpf_prm * prm)8399a2dd95SBruce Richardson rte_bpf_load(const struct rte_bpf_prm *prm)
8499a2dd95SBruce Richardson {
8599a2dd95SBruce Richardson struct rte_bpf *bpf;
8699a2dd95SBruce Richardson int32_t rc;
8799a2dd95SBruce Richardson uint32_t i;
8899a2dd95SBruce Richardson
8999a2dd95SBruce Richardson if (prm == NULL || prm->ins == NULL ||
9099a2dd95SBruce Richardson (prm->nb_xsym != 0 && prm->xsym == NULL)) {
9199a2dd95SBruce Richardson rte_errno = EINVAL;
9299a2dd95SBruce Richardson return NULL;
9399a2dd95SBruce Richardson }
9499a2dd95SBruce Richardson
9599a2dd95SBruce Richardson rc = 0;
9699a2dd95SBruce Richardson for (i = 0; i != prm->nb_xsym && rc == 0; i++)
9799a2dd95SBruce Richardson rc = bpf_check_xsym(prm->xsym + i);
9899a2dd95SBruce Richardson
9999a2dd95SBruce Richardson if (rc != 0) {
10099a2dd95SBruce Richardson rte_errno = -rc;
101*0e21c7c0SDavid Marchand RTE_BPF_LOG_LINE(ERR, "%s: %d-th xsym is invalid", __func__, i);
10299a2dd95SBruce Richardson return NULL;
10399a2dd95SBruce Richardson }
10499a2dd95SBruce Richardson
10599a2dd95SBruce Richardson bpf = bpf_load(prm);
10699a2dd95SBruce Richardson if (bpf == NULL) {
10799a2dd95SBruce Richardson rte_errno = ENOMEM;
10899a2dd95SBruce Richardson return NULL;
10999a2dd95SBruce Richardson }
11099a2dd95SBruce Richardson
111cf095b1eSJ.J. Martzki rc = __rte_bpf_validate(bpf);
11299a2dd95SBruce Richardson if (rc == 0) {
113cf095b1eSJ.J. Martzki __rte_bpf_jit(bpf);
11499a2dd95SBruce Richardson if (mprotect(bpf, bpf->sz, PROT_READ) != 0)
11599a2dd95SBruce Richardson rc = -ENOMEM;
11699a2dd95SBruce Richardson }
11799a2dd95SBruce Richardson
11899a2dd95SBruce Richardson if (rc != 0) {
11999a2dd95SBruce Richardson rte_bpf_destroy(bpf);
12099a2dd95SBruce Richardson rte_errno = -rc;
12199a2dd95SBruce Richardson return NULL;
12299a2dd95SBruce Richardson }
12399a2dd95SBruce Richardson
12499a2dd95SBruce Richardson return bpf;
12599a2dd95SBruce Richardson }
126