xref: /dpdk/lib/bpf/bpf_load.c (revision 0e21c7c07d623719d61cc7e2e85613e8c71d9a57)
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