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