xref: /aosp_15_r20/external/iproute2/lib/bpf.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * bpf.c	BPF common code
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Daniel Borkmann <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  *		Jiri Pirko <[email protected]>
11*de1e4e89SAndroid Build Coastguard Worker  *		Alexei Starovoitov <[email protected]>
12*de1e4e89SAndroid Build Coastguard Worker  */
13*de1e4e89SAndroid Build Coastguard Worker 
14*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <stdbool.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <stdint.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <stdarg.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <limits.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <assert.h>
25*de1e4e89SAndroid Build Coastguard Worker 
26*de1e4e89SAndroid Build Coastguard Worker #ifdef HAVE_ELF
27*de1e4e89SAndroid Build Coastguard Worker #include <libelf.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <gelf.h>
29*de1e4e89SAndroid Build Coastguard Worker #endif
30*de1e4e89SAndroid Build Coastguard Worker 
31*de1e4e89SAndroid Build Coastguard Worker #include <sys/types.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <sys/stat.h>
33*de1e4e89SAndroid Build Coastguard Worker #include <sys/un.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <sys/vfs.h>
35*de1e4e89SAndroid Build Coastguard Worker #include <sys/mount.h>
36*de1e4e89SAndroid Build Coastguard Worker #include <sys/syscall.h>
37*de1e4e89SAndroid Build Coastguard Worker #include <sys/sendfile.h>
38*de1e4e89SAndroid Build Coastguard Worker #include <sys/resource.h>
39*de1e4e89SAndroid Build Coastguard Worker 
40*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
41*de1e4e89SAndroid Build Coastguard Worker 
42*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
43*de1e4e89SAndroid Build Coastguard Worker #include "json_print.h"
44*de1e4e89SAndroid Build Coastguard Worker 
45*de1e4e89SAndroid Build Coastguard Worker #include "bpf_util.h"
46*de1e4e89SAndroid Build Coastguard Worker #include "bpf_elf.h"
47*de1e4e89SAndroid Build Coastguard Worker #include "bpf_scm.h"
48*de1e4e89SAndroid Build Coastguard Worker 
49*de1e4e89SAndroid Build Coastguard Worker struct bpf_prog_meta {
50*de1e4e89SAndroid Build Coastguard Worker 	const char *type;
51*de1e4e89SAndroid Build Coastguard Worker 	const char *subdir;
52*de1e4e89SAndroid Build Coastguard Worker 	const char *section;
53*de1e4e89SAndroid Build Coastguard Worker 	bool may_uds_export;
54*de1e4e89SAndroid Build Coastguard Worker };
55*de1e4e89SAndroid Build Coastguard Worker 
56*de1e4e89SAndroid Build Coastguard Worker static const enum bpf_prog_type __bpf_types[] = {
57*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_SCHED_CLS,
58*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_SCHED_ACT,
59*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_XDP,
60*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_LWT_IN,
61*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_LWT_OUT,
62*de1e4e89SAndroid Build Coastguard Worker 	BPF_PROG_TYPE_LWT_XMIT,
63*de1e4e89SAndroid Build Coastguard Worker };
64*de1e4e89SAndroid Build Coastguard Worker 
65*de1e4e89SAndroid Build Coastguard Worker static const struct bpf_prog_meta __bpf_prog_meta[] = {
66*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_SCHED_CLS] = {
67*de1e4e89SAndroid Build Coastguard Worker 		.type		= "cls",
68*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "tc",
69*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_CLASSIFIER,
70*de1e4e89SAndroid Build Coastguard Worker 		.may_uds_export	= true,
71*de1e4e89SAndroid Build Coastguard Worker 	},
72*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_SCHED_ACT] = {
73*de1e4e89SAndroid Build Coastguard Worker 		.type		= "act",
74*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "tc",
75*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_ACTION,
76*de1e4e89SAndroid Build Coastguard Worker 		.may_uds_export	= true,
77*de1e4e89SAndroid Build Coastguard Worker 	},
78*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_XDP] = {
79*de1e4e89SAndroid Build Coastguard Worker 		.type		= "xdp",
80*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "xdp",
81*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_PROG,
82*de1e4e89SAndroid Build Coastguard Worker 	},
83*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_LWT_IN] = {
84*de1e4e89SAndroid Build Coastguard Worker 		.type		= "lwt_in",
85*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "ip",
86*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_PROG,
87*de1e4e89SAndroid Build Coastguard Worker 	},
88*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_LWT_OUT] = {
89*de1e4e89SAndroid Build Coastguard Worker 		.type		= "lwt_out",
90*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "ip",
91*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_PROG,
92*de1e4e89SAndroid Build Coastguard Worker 	},
93*de1e4e89SAndroid Build Coastguard Worker 	[BPF_PROG_TYPE_LWT_XMIT] = {
94*de1e4e89SAndroid Build Coastguard Worker 		.type		= "lwt_xmit",
95*de1e4e89SAndroid Build Coastguard Worker 		.subdir		= "ip",
96*de1e4e89SAndroid Build Coastguard Worker 		.section	= ELF_SECTION_PROG,
97*de1e4e89SAndroid Build Coastguard Worker 	},
98*de1e4e89SAndroid Build Coastguard Worker };
99*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_to_subdir(enum bpf_prog_type type)100*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_prog_to_subdir(enum bpf_prog_type type)
101*de1e4e89SAndroid Build Coastguard Worker {
102*de1e4e89SAndroid Build Coastguard Worker 	assert(type < ARRAY_SIZE(__bpf_prog_meta) &&
103*de1e4e89SAndroid Build Coastguard Worker 	       __bpf_prog_meta[type].subdir);
104*de1e4e89SAndroid Build Coastguard Worker 	return __bpf_prog_meta[type].subdir;
105*de1e4e89SAndroid Build Coastguard Worker }
106*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_to_default_section(enum bpf_prog_type type)107*de1e4e89SAndroid Build Coastguard Worker const char *bpf_prog_to_default_section(enum bpf_prog_type type)
108*de1e4e89SAndroid Build Coastguard Worker {
109*de1e4e89SAndroid Build Coastguard Worker 	assert(type < ARRAY_SIZE(__bpf_prog_meta) &&
110*de1e4e89SAndroid Build Coastguard Worker 	       __bpf_prog_meta[type].section);
111*de1e4e89SAndroid Build Coastguard Worker 	return __bpf_prog_meta[type].section;
112*de1e4e89SAndroid Build Coastguard Worker }
113*de1e4e89SAndroid Build Coastguard Worker 
114*de1e4e89SAndroid Build Coastguard Worker #ifdef HAVE_ELF
115*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_open(const char *path, enum bpf_prog_type type,
116*de1e4e89SAndroid Build Coastguard Worker 			const char *sec, bool verbose);
117*de1e4e89SAndroid Build Coastguard Worker #else
bpf_obj_open(const char * path,enum bpf_prog_type type,const char * sec,bool verbose)118*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_open(const char *path, enum bpf_prog_type type,
119*de1e4e89SAndroid Build Coastguard Worker 			const char *sec, bool verbose)
120*de1e4e89SAndroid Build Coastguard Worker {
121*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "No ELF library support compiled in.\n");
122*de1e4e89SAndroid Build Coastguard Worker 	errno = ENOSYS;
123*de1e4e89SAndroid Build Coastguard Worker 	return -1;
124*de1e4e89SAndroid Build Coastguard Worker }
125*de1e4e89SAndroid Build Coastguard Worker #endif
126*de1e4e89SAndroid Build Coastguard Worker 
bpf_ptr_to_u64(const void * ptr)127*de1e4e89SAndroid Build Coastguard Worker static inline __u64 bpf_ptr_to_u64(const void *ptr)
128*de1e4e89SAndroid Build Coastguard Worker {
129*de1e4e89SAndroid Build Coastguard Worker 	return (__u64)(unsigned long)ptr;
130*de1e4e89SAndroid Build Coastguard Worker }
131*de1e4e89SAndroid Build Coastguard Worker 
bpf(int cmd,union bpf_attr * attr,unsigned int size)132*de1e4e89SAndroid Build Coastguard Worker static int bpf(int cmd, union bpf_attr *attr, unsigned int size)
133*de1e4e89SAndroid Build Coastguard Worker {
134*de1e4e89SAndroid Build Coastguard Worker #ifdef __NR_bpf
135*de1e4e89SAndroid Build Coastguard Worker 	return syscall(__NR_bpf, cmd, attr, size);
136*de1e4e89SAndroid Build Coastguard Worker #else
137*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
138*de1e4e89SAndroid Build Coastguard Worker 	errno = ENOSYS;
139*de1e4e89SAndroid Build Coastguard Worker 	return -1;
140*de1e4e89SAndroid Build Coastguard Worker #endif
141*de1e4e89SAndroid Build Coastguard Worker }
142*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_update(int fd,const void * key,const void * value,uint64_t flags)143*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_update(int fd, const void *key, const void *value,
144*de1e4e89SAndroid Build Coastguard Worker 			  uint64_t flags)
145*de1e4e89SAndroid Build Coastguard Worker {
146*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
147*de1e4e89SAndroid Build Coastguard Worker 
148*de1e4e89SAndroid Build Coastguard Worker 	attr.map_fd = fd;
149*de1e4e89SAndroid Build Coastguard Worker 	attr.key = bpf_ptr_to_u64(key);
150*de1e4e89SAndroid Build Coastguard Worker 	attr.value = bpf_ptr_to_u64(value);
151*de1e4e89SAndroid Build Coastguard Worker 	attr.flags = flags;
152*de1e4e89SAndroid Build Coastguard Worker 
153*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
154*de1e4e89SAndroid Build Coastguard Worker }
155*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_fd_by_id(uint32_t id)156*de1e4e89SAndroid Build Coastguard Worker static int bpf_prog_fd_by_id(uint32_t id)
157*de1e4e89SAndroid Build Coastguard Worker {
158*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
159*de1e4e89SAndroid Build Coastguard Worker 
160*de1e4e89SAndroid Build Coastguard Worker 	attr.prog_id = id;
161*de1e4e89SAndroid Build Coastguard Worker 
162*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
163*de1e4e89SAndroid Build Coastguard Worker }
164*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_info_by_fd(int fd,struct bpf_prog_info * info,uint32_t * info_len)165*de1e4e89SAndroid Build Coastguard Worker static int bpf_prog_info_by_fd(int fd, struct bpf_prog_info *info,
166*de1e4e89SAndroid Build Coastguard Worker 			       uint32_t *info_len)
167*de1e4e89SAndroid Build Coastguard Worker {
168*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
169*de1e4e89SAndroid Build Coastguard Worker 	int ret;
170*de1e4e89SAndroid Build Coastguard Worker 
171*de1e4e89SAndroid Build Coastguard Worker 	attr.info.bpf_fd = fd;
172*de1e4e89SAndroid Build Coastguard Worker 	attr.info.info = bpf_ptr_to_u64(info);
173*de1e4e89SAndroid Build Coastguard Worker 	attr.info.info_len = *info_len;
174*de1e4e89SAndroid Build Coastguard Worker 
175*de1e4e89SAndroid Build Coastguard Worker 	*info_len = 0;
176*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
177*de1e4e89SAndroid Build Coastguard Worker 	if (!ret)
178*de1e4e89SAndroid Build Coastguard Worker 		*info_len = attr.info.info_len;
179*de1e4e89SAndroid Build Coastguard Worker 
180*de1e4e89SAndroid Build Coastguard Worker 	return ret;
181*de1e4e89SAndroid Build Coastguard Worker }
182*de1e4e89SAndroid Build Coastguard Worker 
bpf_dump_prog_info(FILE * f,uint32_t id)183*de1e4e89SAndroid Build Coastguard Worker int bpf_dump_prog_info(FILE *f, uint32_t id)
184*de1e4e89SAndroid Build Coastguard Worker {
185*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_prog_info info = {};
186*de1e4e89SAndroid Build Coastguard Worker 	uint32_t len = sizeof(info);
187*de1e4e89SAndroid Build Coastguard Worker 	int fd, ret, dump_ok = 0;
188*de1e4e89SAndroid Build Coastguard Worker 	SPRINT_BUF(tmp);
189*de1e4e89SAndroid Build Coastguard Worker 
190*de1e4e89SAndroid Build Coastguard Worker 	open_json_object("prog");
191*de1e4e89SAndroid Build Coastguard Worker 	print_uint(PRINT_ANY, "id", "id %u ", id);
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	fd = bpf_prog_fd_by_id(id);
194*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0)
195*de1e4e89SAndroid Build Coastguard Worker 		goto out;
196*de1e4e89SAndroid Build Coastguard Worker 
197*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_prog_info_by_fd(fd, &info, &len);
198*de1e4e89SAndroid Build Coastguard Worker 	if (!ret && len) {
199*de1e4e89SAndroid Build Coastguard Worker 		int jited = !!info.jited_prog_len;
200*de1e4e89SAndroid Build Coastguard Worker 
201*de1e4e89SAndroid Build Coastguard Worker 		print_string(PRINT_ANY, "tag", "tag %s ",
202*de1e4e89SAndroid Build Coastguard Worker 			     hexstring_n2a(info.tag, sizeof(info.tag),
203*de1e4e89SAndroid Build Coastguard Worker 					   tmp, sizeof(tmp)));
204*de1e4e89SAndroid Build Coastguard Worker 		print_uint(PRINT_JSON, "jited", NULL, jited);
205*de1e4e89SAndroid Build Coastguard Worker 		if (jited && !is_json_context())
206*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "jited ");
207*de1e4e89SAndroid Build Coastguard Worker 		dump_ok = 1;
208*de1e4e89SAndroid Build Coastguard Worker 	}
209*de1e4e89SAndroid Build Coastguard Worker 
210*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
211*de1e4e89SAndroid Build Coastguard Worker out:
212*de1e4e89SAndroid Build Coastguard Worker 	close_json_object();
213*de1e4e89SAndroid Build Coastguard Worker 	return dump_ok;
214*de1e4e89SAndroid Build Coastguard Worker }
215*de1e4e89SAndroid Build Coastguard Worker 
bpf_parse_string(char * arg,bool from_file,__u16 * bpf_len,char ** bpf_string,bool * need_release,const char separator)216*de1e4e89SAndroid Build Coastguard Worker static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
217*de1e4e89SAndroid Build Coastguard Worker 			    char **bpf_string, bool *need_release,
218*de1e4e89SAndroid Build Coastguard Worker 			    const char separator)
219*de1e4e89SAndroid Build Coastguard Worker {
220*de1e4e89SAndroid Build Coastguard Worker 	char sp;
221*de1e4e89SAndroid Build Coastguard Worker 
222*de1e4e89SAndroid Build Coastguard Worker 	if (from_file) {
223*de1e4e89SAndroid Build Coastguard Worker 		size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
224*de1e4e89SAndroid Build Coastguard Worker 		char *tmp_string, *pos, c_prev = ' ';
225*de1e4e89SAndroid Build Coastguard Worker 		FILE *fp;
226*de1e4e89SAndroid Build Coastguard Worker 		int c;
227*de1e4e89SAndroid Build Coastguard Worker 
228*de1e4e89SAndroid Build Coastguard Worker 		tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
229*de1e4e89SAndroid Build Coastguard Worker 		tmp_string = pos = calloc(1, tmp_len);
230*de1e4e89SAndroid Build Coastguard Worker 		if (tmp_string == NULL)
231*de1e4e89SAndroid Build Coastguard Worker 			return -ENOMEM;
232*de1e4e89SAndroid Build Coastguard Worker 
233*de1e4e89SAndroid Build Coastguard Worker 		fp = fopen(arg, "r");
234*de1e4e89SAndroid Build Coastguard Worker 		if (fp == NULL) {
235*de1e4e89SAndroid Build Coastguard Worker 			perror("Cannot fopen");
236*de1e4e89SAndroid Build Coastguard Worker 			free(tmp_string);
237*de1e4e89SAndroid Build Coastguard Worker 			return -ENOENT;
238*de1e4e89SAndroid Build Coastguard Worker 		}
239*de1e4e89SAndroid Build Coastguard Worker 
240*de1e4e89SAndroid Build Coastguard Worker 		while ((c = fgetc(fp)) != EOF) {
241*de1e4e89SAndroid Build Coastguard Worker 			switch (c) {
242*de1e4e89SAndroid Build Coastguard Worker 			case '\n':
243*de1e4e89SAndroid Build Coastguard Worker 				if (c_prev != ',')
244*de1e4e89SAndroid Build Coastguard Worker 					*(pos++) = ',';
245*de1e4e89SAndroid Build Coastguard Worker 				c_prev = ',';
246*de1e4e89SAndroid Build Coastguard Worker 				break;
247*de1e4e89SAndroid Build Coastguard Worker 			case ' ':
248*de1e4e89SAndroid Build Coastguard Worker 			case '\t':
249*de1e4e89SAndroid Build Coastguard Worker 				if (c_prev != ' ')
250*de1e4e89SAndroid Build Coastguard Worker 					*(pos++) = c;
251*de1e4e89SAndroid Build Coastguard Worker 				c_prev = ' ';
252*de1e4e89SAndroid Build Coastguard Worker 				break;
253*de1e4e89SAndroid Build Coastguard Worker 			default:
254*de1e4e89SAndroid Build Coastguard Worker 				*(pos++) = c;
255*de1e4e89SAndroid Build Coastguard Worker 				c_prev = c;
256*de1e4e89SAndroid Build Coastguard Worker 			}
257*de1e4e89SAndroid Build Coastguard Worker 			if (pos - tmp_string == tmp_len)
258*de1e4e89SAndroid Build Coastguard Worker 				break;
259*de1e4e89SAndroid Build Coastguard Worker 		}
260*de1e4e89SAndroid Build Coastguard Worker 
261*de1e4e89SAndroid Build Coastguard Worker 		if (!feof(fp)) {
262*de1e4e89SAndroid Build Coastguard Worker 			free(tmp_string);
263*de1e4e89SAndroid Build Coastguard Worker 			fclose(fp);
264*de1e4e89SAndroid Build Coastguard Worker 			return -E2BIG;
265*de1e4e89SAndroid Build Coastguard Worker 		}
266*de1e4e89SAndroid Build Coastguard Worker 
267*de1e4e89SAndroid Build Coastguard Worker 		fclose(fp);
268*de1e4e89SAndroid Build Coastguard Worker 		*pos = 0;
269*de1e4e89SAndroid Build Coastguard Worker 
270*de1e4e89SAndroid Build Coastguard Worker 		*need_release = true;
271*de1e4e89SAndroid Build Coastguard Worker 		*bpf_string = tmp_string;
272*de1e4e89SAndroid Build Coastguard Worker 	} else {
273*de1e4e89SAndroid Build Coastguard Worker 		*need_release = false;
274*de1e4e89SAndroid Build Coastguard Worker 		*bpf_string = arg;
275*de1e4e89SAndroid Build Coastguard Worker 	}
276*de1e4e89SAndroid Build Coastguard Worker 
277*de1e4e89SAndroid Build Coastguard Worker 	if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
278*de1e4e89SAndroid Build Coastguard Worker 	    sp != separator) {
279*de1e4e89SAndroid Build Coastguard Worker 		if (*need_release)
280*de1e4e89SAndroid Build Coastguard Worker 			free(*bpf_string);
281*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
282*de1e4e89SAndroid Build Coastguard Worker 	}
283*de1e4e89SAndroid Build Coastguard Worker 
284*de1e4e89SAndroid Build Coastguard Worker 	return 0;
285*de1e4e89SAndroid Build Coastguard Worker }
286*de1e4e89SAndroid Build Coastguard Worker 
bpf_ops_parse(int argc,char ** argv,struct sock_filter * bpf_ops,bool from_file)287*de1e4e89SAndroid Build Coastguard Worker static int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops,
288*de1e4e89SAndroid Build Coastguard Worker 			 bool from_file)
289*de1e4e89SAndroid Build Coastguard Worker {
290*de1e4e89SAndroid Build Coastguard Worker 	char *bpf_string, *token, separator = ',';
291*de1e4e89SAndroid Build Coastguard Worker 	int ret = 0, i = 0;
292*de1e4e89SAndroid Build Coastguard Worker 	bool need_release;
293*de1e4e89SAndroid Build Coastguard Worker 	__u16 bpf_len = 0;
294*de1e4e89SAndroid Build Coastguard Worker 
295*de1e4e89SAndroid Build Coastguard Worker 	if (argc < 1)
296*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
297*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
298*de1e4e89SAndroid Build Coastguard Worker 			     &need_release, separator))
299*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
300*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
301*de1e4e89SAndroid Build Coastguard Worker 		ret = -EINVAL;
302*de1e4e89SAndroid Build Coastguard Worker 		goto out;
303*de1e4e89SAndroid Build Coastguard Worker 	}
304*de1e4e89SAndroid Build Coastguard Worker 
305*de1e4e89SAndroid Build Coastguard Worker 	token = bpf_string;
306*de1e4e89SAndroid Build Coastguard Worker 	while ((token = strchr(token, separator)) && (++token)[0]) {
307*de1e4e89SAndroid Build Coastguard Worker 		if (i >= bpf_len) {
308*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Real program length exceeds encoded length parameter!\n");
309*de1e4e89SAndroid Build Coastguard Worker 			ret = -EINVAL;
310*de1e4e89SAndroid Build Coastguard Worker 			goto out;
311*de1e4e89SAndroid Build Coastguard Worker 		}
312*de1e4e89SAndroid Build Coastguard Worker 
313*de1e4e89SAndroid Build Coastguard Worker 		if (sscanf(token, "%hu %hhu %hhu %u,",
314*de1e4e89SAndroid Build Coastguard Worker 			   &bpf_ops[i].code, &bpf_ops[i].jt,
315*de1e4e89SAndroid Build Coastguard Worker 			   &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
316*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Error at instruction %d!\n", i);
317*de1e4e89SAndroid Build Coastguard Worker 			ret = -EINVAL;
318*de1e4e89SAndroid Build Coastguard Worker 			goto out;
319*de1e4e89SAndroid Build Coastguard Worker 		}
320*de1e4e89SAndroid Build Coastguard Worker 
321*de1e4e89SAndroid Build Coastguard Worker 		i++;
322*de1e4e89SAndroid Build Coastguard Worker 	}
323*de1e4e89SAndroid Build Coastguard Worker 
324*de1e4e89SAndroid Build Coastguard Worker 	if (i != bpf_len) {
325*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Parsed program length is less than encoded length parameter!\n");
326*de1e4e89SAndroid Build Coastguard Worker 		ret = -EINVAL;
327*de1e4e89SAndroid Build Coastguard Worker 		goto out;
328*de1e4e89SAndroid Build Coastguard Worker 	}
329*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_len;
330*de1e4e89SAndroid Build Coastguard Worker out:
331*de1e4e89SAndroid Build Coastguard Worker 	if (need_release)
332*de1e4e89SAndroid Build Coastguard Worker 		free(bpf_string);
333*de1e4e89SAndroid Build Coastguard Worker 
334*de1e4e89SAndroid Build Coastguard Worker 	return ret;
335*de1e4e89SAndroid Build Coastguard Worker }
336*de1e4e89SAndroid Build Coastguard Worker 
bpf_print_ops(FILE * f,struct rtattr * bpf_ops,__u16 len)337*de1e4e89SAndroid Build Coastguard Worker void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
338*de1e4e89SAndroid Build Coastguard Worker {
339*de1e4e89SAndroid Build Coastguard Worker 	struct sock_filter *ops = RTA_DATA(bpf_ops);
340*de1e4e89SAndroid Build Coastguard Worker 	int i;
341*de1e4e89SAndroid Build Coastguard Worker 
342*de1e4e89SAndroid Build Coastguard Worker 	if (len == 0)
343*de1e4e89SAndroid Build Coastguard Worker 		return;
344*de1e4e89SAndroid Build Coastguard Worker 
345*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "bytecode \'%u,", len);
346*de1e4e89SAndroid Build Coastguard Worker 
347*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < len - 1; i++)
348*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
349*de1e4e89SAndroid Build Coastguard Worker 			ops[i].jf, ops[i].k);
350*de1e4e89SAndroid Build Coastguard Worker 
351*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt,
352*de1e4e89SAndroid Build Coastguard Worker 		ops[i].jf, ops[i].k);
353*de1e4e89SAndroid Build Coastguard Worker }
354*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_pin_report(const struct bpf_elf_map * pin,const struct bpf_elf_map * obj)355*de1e4e89SAndroid Build Coastguard Worker static void bpf_map_pin_report(const struct bpf_elf_map *pin,
356*de1e4e89SAndroid Build Coastguard Worker 			       const struct bpf_elf_map *obj)
357*de1e4e89SAndroid Build Coastguard Worker {
358*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Map specification differs from pinned file!\n");
359*de1e4e89SAndroid Build Coastguard Worker 
360*de1e4e89SAndroid Build Coastguard Worker 	if (obj->type != pin->type)
361*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " - Type:         %u (obj) != %u (pin)\n",
362*de1e4e89SAndroid Build Coastguard Worker 			obj->type, pin->type);
363*de1e4e89SAndroid Build Coastguard Worker 	if (obj->size_key != pin->size_key)
364*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " - Size key:     %u (obj) != %u (pin)\n",
365*de1e4e89SAndroid Build Coastguard Worker 			obj->size_key, pin->size_key);
366*de1e4e89SAndroid Build Coastguard Worker 	if (obj->size_value != pin->size_value)
367*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " - Size value:   %u (obj) != %u (pin)\n",
368*de1e4e89SAndroid Build Coastguard Worker 			obj->size_value, pin->size_value);
369*de1e4e89SAndroid Build Coastguard Worker 	if (obj->max_elem != pin->max_elem)
370*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " - Max elems:    %u (obj) != %u (pin)\n",
371*de1e4e89SAndroid Build Coastguard Worker 			obj->max_elem, pin->max_elem);
372*de1e4e89SAndroid Build Coastguard Worker 	if (obj->flags != pin->flags)
373*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " - Flags:        %#x (obj) != %#x (pin)\n",
374*de1e4e89SAndroid Build Coastguard Worker 			obj->flags, pin->flags);
375*de1e4e89SAndroid Build Coastguard Worker 
376*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
377*de1e4e89SAndroid Build Coastguard Worker }
378*de1e4e89SAndroid Build Coastguard Worker 
379*de1e4e89SAndroid Build Coastguard Worker struct bpf_prog_data {
380*de1e4e89SAndroid Build Coastguard Worker 	unsigned int type;
381*de1e4e89SAndroid Build Coastguard Worker 	unsigned int jited;
382*de1e4e89SAndroid Build Coastguard Worker };
383*de1e4e89SAndroid Build Coastguard Worker 
384*de1e4e89SAndroid Build Coastguard Worker struct bpf_map_ext {
385*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_prog_data owner;
386*de1e4e89SAndroid Build Coastguard Worker };
387*de1e4e89SAndroid Build Coastguard Worker 
bpf_derive_elf_map_from_fdinfo(int fd,struct bpf_elf_map * map,struct bpf_map_ext * ext)388*de1e4e89SAndroid Build Coastguard Worker static int bpf_derive_elf_map_from_fdinfo(int fd, struct bpf_elf_map *map,
389*de1e4e89SAndroid Build Coastguard Worker 					  struct bpf_map_ext *ext)
390*de1e4e89SAndroid Build Coastguard Worker {
391*de1e4e89SAndroid Build Coastguard Worker 	unsigned int val, owner_type = 0, owner_jited = 0;
392*de1e4e89SAndroid Build Coastguard Worker 	char file[PATH_MAX], buff[4096];
393*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp;
394*de1e4e89SAndroid Build Coastguard Worker 
395*de1e4e89SAndroid Build Coastguard Worker 	snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
396*de1e4e89SAndroid Build Coastguard Worker 	memset(map, 0, sizeof(*map));
397*de1e4e89SAndroid Build Coastguard Worker 
398*de1e4e89SAndroid Build Coastguard Worker 	fp = fopen(file, "r");
399*de1e4e89SAndroid Build Coastguard Worker 	if (!fp) {
400*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "No procfs support?!\n");
401*de1e4e89SAndroid Build Coastguard Worker 		return -EIO;
402*de1e4e89SAndroid Build Coastguard Worker 	}
403*de1e4e89SAndroid Build Coastguard Worker 
404*de1e4e89SAndroid Build Coastguard Worker 	while (fgets(buff, sizeof(buff), fp)) {
405*de1e4e89SAndroid Build Coastguard Worker 		if (sscanf(buff, "map_type:\t%u", &val) == 1)
406*de1e4e89SAndroid Build Coastguard Worker 			map->type = val;
407*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "key_size:\t%u", &val) == 1)
408*de1e4e89SAndroid Build Coastguard Worker 			map->size_key = val;
409*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "value_size:\t%u", &val) == 1)
410*de1e4e89SAndroid Build Coastguard Worker 			map->size_value = val;
411*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
412*de1e4e89SAndroid Build Coastguard Worker 			map->max_elem = val;
413*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "map_flags:\t%i", &val) == 1)
414*de1e4e89SAndroid Build Coastguard Worker 			map->flags = val;
415*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "owner_prog_type:\t%i", &val) == 1)
416*de1e4e89SAndroid Build Coastguard Worker 			owner_type = val;
417*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "owner_jited:\t%i", &val) == 1)
418*de1e4e89SAndroid Build Coastguard Worker 			owner_jited = val;
419*de1e4e89SAndroid Build Coastguard Worker 	}
420*de1e4e89SAndroid Build Coastguard Worker 
421*de1e4e89SAndroid Build Coastguard Worker 	fclose(fp);
422*de1e4e89SAndroid Build Coastguard Worker 	if (ext) {
423*de1e4e89SAndroid Build Coastguard Worker 		memset(ext, 0, sizeof(*ext));
424*de1e4e89SAndroid Build Coastguard Worker 		ext->owner.type  = owner_type;
425*de1e4e89SAndroid Build Coastguard Worker 		ext->owner.jited = owner_jited;
426*de1e4e89SAndroid Build Coastguard Worker 	}
427*de1e4e89SAndroid Build Coastguard Worker 
428*de1e4e89SAndroid Build Coastguard Worker 	return 0;
429*de1e4e89SAndroid Build Coastguard Worker }
430*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_selfcheck_pinned(int fd,const struct bpf_elf_map * map,struct bpf_map_ext * ext,int length,enum bpf_prog_type type)431*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
432*de1e4e89SAndroid Build Coastguard Worker 				    struct bpf_map_ext *ext, int length,
433*de1e4e89SAndroid Build Coastguard Worker 				    enum bpf_prog_type type)
434*de1e4e89SAndroid Build Coastguard Worker {
435*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map tmp, zero = {};
436*de1e4e89SAndroid Build Coastguard Worker 	int ret;
437*de1e4e89SAndroid Build Coastguard Worker 
438*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_derive_elf_map_from_fdinfo(fd, &tmp, ext);
439*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
440*de1e4e89SAndroid Build Coastguard Worker 		return ret;
441*de1e4e89SAndroid Build Coastguard Worker 
442*de1e4e89SAndroid Build Coastguard Worker 	/* The decision to reject this is on kernel side eventually, but
443*de1e4e89SAndroid Build Coastguard Worker 	 * at least give the user a chance to know what's wrong.
444*de1e4e89SAndroid Build Coastguard Worker 	 */
445*de1e4e89SAndroid Build Coastguard Worker 	if (ext->owner.type && ext->owner.type != type)
446*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Program array map owner types differ: %u (obj) != %u (pin)\n",
447*de1e4e89SAndroid Build Coastguard Worker 			type, ext->owner.type);
448*de1e4e89SAndroid Build Coastguard Worker 
449*de1e4e89SAndroid Build Coastguard Worker 	if (!memcmp(&tmp, map, length)) {
450*de1e4e89SAndroid Build Coastguard Worker 		return 0;
451*de1e4e89SAndroid Build Coastguard Worker 	} else {
452*de1e4e89SAndroid Build Coastguard Worker 		/* If kernel doesn't have eBPF-related fdinfo, we cannot do much,
453*de1e4e89SAndroid Build Coastguard Worker 		 * so just accept it. We know we do have an eBPF fd and in this
454*de1e4e89SAndroid Build Coastguard Worker 		 * case, everything is 0. It is guaranteed that no such map exists
455*de1e4e89SAndroid Build Coastguard Worker 		 * since map type of 0 is unloadable BPF_MAP_TYPE_UNSPEC.
456*de1e4e89SAndroid Build Coastguard Worker 		 */
457*de1e4e89SAndroid Build Coastguard Worker 		if (!memcmp(&tmp, &zero, length))
458*de1e4e89SAndroid Build Coastguard Worker 			return 0;
459*de1e4e89SAndroid Build Coastguard Worker 
460*de1e4e89SAndroid Build Coastguard Worker 		bpf_map_pin_report(&tmp, map);
461*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
462*de1e4e89SAndroid Build Coastguard Worker 	}
463*de1e4e89SAndroid Build Coastguard Worker }
464*de1e4e89SAndroid Build Coastguard Worker 
bpf_mnt_fs(const char * target)465*de1e4e89SAndroid Build Coastguard Worker static int bpf_mnt_fs(const char *target)
466*de1e4e89SAndroid Build Coastguard Worker {
467*de1e4e89SAndroid Build Coastguard Worker 	bool bind_done = false;
468*de1e4e89SAndroid Build Coastguard Worker 
469*de1e4e89SAndroid Build Coastguard Worker 	while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
470*de1e4e89SAndroid Build Coastguard Worker 		if (errno != EINVAL || bind_done) {
471*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "mount --make-private %s failed: %s\n",
472*de1e4e89SAndroid Build Coastguard Worker 				target,	strerror(errno));
473*de1e4e89SAndroid Build Coastguard Worker 			return -1;
474*de1e4e89SAndroid Build Coastguard Worker 		}
475*de1e4e89SAndroid Build Coastguard Worker 
476*de1e4e89SAndroid Build Coastguard Worker 		if (mount(target, target, "none", MS_BIND, NULL)) {
477*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "mount --bind %s %s failed: %s\n",
478*de1e4e89SAndroid Build Coastguard Worker 				target,	target, strerror(errno));
479*de1e4e89SAndroid Build Coastguard Worker 			return -1;
480*de1e4e89SAndroid Build Coastguard Worker 		}
481*de1e4e89SAndroid Build Coastguard Worker 
482*de1e4e89SAndroid Build Coastguard Worker 		bind_done = true;
483*de1e4e89SAndroid Build Coastguard Worker 	}
484*de1e4e89SAndroid Build Coastguard Worker 
485*de1e4e89SAndroid Build Coastguard Worker 	if (mount("bpf", target, "bpf", 0, "mode=0700")) {
486*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mount -t bpf bpf %s failed: %s\n",
487*de1e4e89SAndroid Build Coastguard Worker 			target,	strerror(errno));
488*de1e4e89SAndroid Build Coastguard Worker 		return -1;
489*de1e4e89SAndroid Build Coastguard Worker 	}
490*de1e4e89SAndroid Build Coastguard Worker 
491*de1e4e89SAndroid Build Coastguard Worker 	return 0;
492*de1e4e89SAndroid Build Coastguard Worker }
493*de1e4e89SAndroid Build Coastguard Worker 
bpf_mnt_check_target(const char * target)494*de1e4e89SAndroid Build Coastguard Worker static int bpf_mnt_check_target(const char *target)
495*de1e4e89SAndroid Build Coastguard Worker {
496*de1e4e89SAndroid Build Coastguard Worker 	struct stat sb = {};
497*de1e4e89SAndroid Build Coastguard Worker 	int ret;
498*de1e4e89SAndroid Build Coastguard Worker 
499*de1e4e89SAndroid Build Coastguard Worker 	ret = stat(target, &sb);
500*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
501*de1e4e89SAndroid Build Coastguard Worker 		ret = mkdir(target, S_IRWXU);
502*de1e4e89SAndroid Build Coastguard Worker 		if (ret) {
503*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "mkdir %s failed: %s\n", target,
504*de1e4e89SAndroid Build Coastguard Worker 				strerror(errno));
505*de1e4e89SAndroid Build Coastguard Worker 			return ret;
506*de1e4e89SAndroid Build Coastguard Worker 		}
507*de1e4e89SAndroid Build Coastguard Worker 	}
508*de1e4e89SAndroid Build Coastguard Worker 
509*de1e4e89SAndroid Build Coastguard Worker 	return 0;
510*de1e4e89SAndroid Build Coastguard Worker }
511*de1e4e89SAndroid Build Coastguard Worker 
bpf_valid_mntpt(const char * mnt,unsigned long magic)512*de1e4e89SAndroid Build Coastguard Worker static int bpf_valid_mntpt(const char *mnt, unsigned long magic)
513*de1e4e89SAndroid Build Coastguard Worker {
514*de1e4e89SAndroid Build Coastguard Worker 	struct statfs st_fs;
515*de1e4e89SAndroid Build Coastguard Worker 
516*de1e4e89SAndroid Build Coastguard Worker 	if (statfs(mnt, &st_fs) < 0)
517*de1e4e89SAndroid Build Coastguard Worker 		return -ENOENT;
518*de1e4e89SAndroid Build Coastguard Worker 	if ((unsigned long)st_fs.f_type != magic)
519*de1e4e89SAndroid Build Coastguard Worker 		return -ENOENT;
520*de1e4e89SAndroid Build Coastguard Worker 
521*de1e4e89SAndroid Build Coastguard Worker 	return 0;
522*de1e4e89SAndroid Build Coastguard Worker }
523*de1e4e89SAndroid Build Coastguard Worker 
bpf_find_mntpt_single(unsigned long magic,char * mnt,int len,const char * mntpt)524*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_find_mntpt_single(unsigned long magic, char *mnt,
525*de1e4e89SAndroid Build Coastguard Worker 					 int len, const char *mntpt)
526*de1e4e89SAndroid Build Coastguard Worker {
527*de1e4e89SAndroid Build Coastguard Worker 	int ret;
528*de1e4e89SAndroid Build Coastguard Worker 
529*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_valid_mntpt(mntpt, magic);
530*de1e4e89SAndroid Build Coastguard Worker 	if (!ret) {
531*de1e4e89SAndroid Build Coastguard Worker 		strlcpy(mnt, mntpt, len);
532*de1e4e89SAndroid Build Coastguard Worker 		return mnt;
533*de1e4e89SAndroid Build Coastguard Worker 	}
534*de1e4e89SAndroid Build Coastguard Worker 
535*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
536*de1e4e89SAndroid Build Coastguard Worker }
537*de1e4e89SAndroid Build Coastguard Worker 
bpf_find_mntpt(const char * fstype,unsigned long magic,char * mnt,int len,const char * const * known_mnts)538*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_find_mntpt(const char *fstype, unsigned long magic,
539*de1e4e89SAndroid Build Coastguard Worker 				  char *mnt, int len,
540*de1e4e89SAndroid Build Coastguard Worker 				  const char * const *known_mnts)
541*de1e4e89SAndroid Build Coastguard Worker {
542*de1e4e89SAndroid Build Coastguard Worker 	const char * const *ptr;
543*de1e4e89SAndroid Build Coastguard Worker 	char type[100];
544*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp;
545*de1e4e89SAndroid Build Coastguard Worker 
546*de1e4e89SAndroid Build Coastguard Worker 	if (known_mnts) {
547*de1e4e89SAndroid Build Coastguard Worker 		ptr = known_mnts;
548*de1e4e89SAndroid Build Coastguard Worker 		while (*ptr) {
549*de1e4e89SAndroid Build Coastguard Worker 			if (bpf_find_mntpt_single(magic, mnt, len, *ptr))
550*de1e4e89SAndroid Build Coastguard Worker 				return mnt;
551*de1e4e89SAndroid Build Coastguard Worker 			ptr++;
552*de1e4e89SAndroid Build Coastguard Worker 		}
553*de1e4e89SAndroid Build Coastguard Worker 	}
554*de1e4e89SAndroid Build Coastguard Worker 
555*de1e4e89SAndroid Build Coastguard Worker 	if (len != PATH_MAX)
556*de1e4e89SAndroid Build Coastguard Worker 		return NULL;
557*de1e4e89SAndroid Build Coastguard Worker 
558*de1e4e89SAndroid Build Coastguard Worker 	fp = fopen("/proc/mounts", "r");
559*de1e4e89SAndroid Build Coastguard Worker 	if (fp == NULL)
560*de1e4e89SAndroid Build Coastguard Worker 		return NULL;
561*de1e4e89SAndroid Build Coastguard Worker 
562*de1e4e89SAndroid Build Coastguard Worker 	while (fscanf(fp, "%*s %" textify(PATH_MAX) "s %99s %*s %*d %*d\n",
563*de1e4e89SAndroid Build Coastguard Worker 		      mnt, type) == 2) {
564*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(type, fstype) == 0)
565*de1e4e89SAndroid Build Coastguard Worker 			break;
566*de1e4e89SAndroid Build Coastguard Worker 	}
567*de1e4e89SAndroid Build Coastguard Worker 
568*de1e4e89SAndroid Build Coastguard Worker 	fclose(fp);
569*de1e4e89SAndroid Build Coastguard Worker 	if (strcmp(type, fstype) != 0)
570*de1e4e89SAndroid Build Coastguard Worker 		return NULL;
571*de1e4e89SAndroid Build Coastguard Worker 
572*de1e4e89SAndroid Build Coastguard Worker 	return mnt;
573*de1e4e89SAndroid Build Coastguard Worker }
574*de1e4e89SAndroid Build Coastguard Worker 
bpf_trace_pipe(void)575*de1e4e89SAndroid Build Coastguard Worker int bpf_trace_pipe(void)
576*de1e4e89SAndroid Build Coastguard Worker {
577*de1e4e89SAndroid Build Coastguard Worker 	char tracefs_mnt[PATH_MAX] = TRACE_DIR_MNT;
578*de1e4e89SAndroid Build Coastguard Worker 	static const char * const tracefs_known_mnts[] = {
579*de1e4e89SAndroid Build Coastguard Worker 		TRACE_DIR_MNT,
580*de1e4e89SAndroid Build Coastguard Worker 		"/sys/kernel/debug/tracing",
581*de1e4e89SAndroid Build Coastguard Worker 		"/tracing",
582*de1e4e89SAndroid Build Coastguard Worker 		"/trace",
583*de1e4e89SAndroid Build Coastguard Worker 		0,
584*de1e4e89SAndroid Build Coastguard Worker 	};
585*de1e4e89SAndroid Build Coastguard Worker 	int fd_in, fd_out = STDERR_FILENO;
586*de1e4e89SAndroid Build Coastguard Worker 	char tpipe[PATH_MAX];
587*de1e4e89SAndroid Build Coastguard Worker 	const char *mnt;
588*de1e4e89SAndroid Build Coastguard Worker 
589*de1e4e89SAndroid Build Coastguard Worker 	mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt,
590*de1e4e89SAndroid Build Coastguard Worker 			     sizeof(tracefs_mnt), tracefs_known_mnts);
591*de1e4e89SAndroid Build Coastguard Worker 	if (!mnt) {
592*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "tracefs not mounted?\n");
593*de1e4e89SAndroid Build Coastguard Worker 		return -1;
594*de1e4e89SAndroid Build Coastguard Worker 	}
595*de1e4e89SAndroid Build Coastguard Worker 
596*de1e4e89SAndroid Build Coastguard Worker 	snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt);
597*de1e4e89SAndroid Build Coastguard Worker 
598*de1e4e89SAndroid Build Coastguard Worker 	fd_in = open(tpipe, O_RDONLY);
599*de1e4e89SAndroid Build Coastguard Worker 	if (fd_in < 0)
600*de1e4e89SAndroid Build Coastguard Worker 		return -1;
601*de1e4e89SAndroid Build Coastguard Worker 
602*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Running! Hang up with ^C!\n\n");
603*de1e4e89SAndroid Build Coastguard Worker 	while (1) {
604*de1e4e89SAndroid Build Coastguard Worker 		static char buff[4096];
605*de1e4e89SAndroid Build Coastguard Worker 		ssize_t ret;
606*de1e4e89SAndroid Build Coastguard Worker 
607*de1e4e89SAndroid Build Coastguard Worker 		ret = read(fd_in, buff, sizeof(buff));
608*de1e4e89SAndroid Build Coastguard Worker 		if (ret > 0 && write(fd_out, buff, ret) == ret)
609*de1e4e89SAndroid Build Coastguard Worker 			continue;
610*de1e4e89SAndroid Build Coastguard Worker 		break;
611*de1e4e89SAndroid Build Coastguard Worker 	}
612*de1e4e89SAndroid Build Coastguard Worker 
613*de1e4e89SAndroid Build Coastguard Worker 	close(fd_in);
614*de1e4e89SAndroid Build Coastguard Worker 	return -1;
615*de1e4e89SAndroid Build Coastguard Worker }
616*de1e4e89SAndroid Build Coastguard Worker 
bpf_gen_global(const char * bpf_sub_dir)617*de1e4e89SAndroid Build Coastguard Worker static int bpf_gen_global(const char *bpf_sub_dir)
618*de1e4e89SAndroid Build Coastguard Worker {
619*de1e4e89SAndroid Build Coastguard Worker 	char bpf_glo_dir[PATH_MAX];
620*de1e4e89SAndroid Build Coastguard Worker 	int ret;
621*de1e4e89SAndroid Build Coastguard Worker 
622*de1e4e89SAndroid Build Coastguard Worker 	snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s/",
623*de1e4e89SAndroid Build Coastguard Worker 		 bpf_sub_dir, BPF_DIR_GLOBALS);
624*de1e4e89SAndroid Build Coastguard Worker 
625*de1e4e89SAndroid Build Coastguard Worker 	ret = mkdir(bpf_glo_dir, S_IRWXU);
626*de1e4e89SAndroid Build Coastguard Worker 	if (ret && errno != EEXIST) {
627*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir,
628*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
629*de1e4e89SAndroid Build Coastguard Worker 		return ret;
630*de1e4e89SAndroid Build Coastguard Worker 	}
631*de1e4e89SAndroid Build Coastguard Worker 
632*de1e4e89SAndroid Build Coastguard Worker 	return 0;
633*de1e4e89SAndroid Build Coastguard Worker }
634*de1e4e89SAndroid Build Coastguard Worker 
bpf_gen_master(const char * base,const char * name)635*de1e4e89SAndroid Build Coastguard Worker static int bpf_gen_master(const char *base, const char *name)
636*de1e4e89SAndroid Build Coastguard Worker {
637*de1e4e89SAndroid Build Coastguard Worker 	char bpf_sub_dir[PATH_MAX];
638*de1e4e89SAndroid Build Coastguard Worker 	int ret;
639*de1e4e89SAndroid Build Coastguard Worker 
640*de1e4e89SAndroid Build Coastguard Worker 	snprintf(bpf_sub_dir, sizeof(bpf_sub_dir), "%s%s/", base, name);
641*de1e4e89SAndroid Build Coastguard Worker 
642*de1e4e89SAndroid Build Coastguard Worker 	ret = mkdir(bpf_sub_dir, S_IRWXU);
643*de1e4e89SAndroid Build Coastguard Worker 	if (ret && errno != EEXIST) {
644*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mkdir %s failed: %s\n", bpf_sub_dir,
645*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
646*de1e4e89SAndroid Build Coastguard Worker 		return ret;
647*de1e4e89SAndroid Build Coastguard Worker 	}
648*de1e4e89SAndroid Build Coastguard Worker 
649*de1e4e89SAndroid Build Coastguard Worker 	return bpf_gen_global(bpf_sub_dir);
650*de1e4e89SAndroid Build Coastguard Worker }
651*de1e4e89SAndroid Build Coastguard Worker 
bpf_slave_via_bind_mnt(const char * full_name,const char * full_link)652*de1e4e89SAndroid Build Coastguard Worker static int bpf_slave_via_bind_mnt(const char *full_name,
653*de1e4e89SAndroid Build Coastguard Worker 				  const char *full_link)
654*de1e4e89SAndroid Build Coastguard Worker {
655*de1e4e89SAndroid Build Coastguard Worker 	int ret;
656*de1e4e89SAndroid Build Coastguard Worker 
657*de1e4e89SAndroid Build Coastguard Worker 	ret = mkdir(full_name, S_IRWXU);
658*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
659*de1e4e89SAndroid Build Coastguard Worker 		assert(errno != EEXIST);
660*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mkdir %s failed: %s\n", full_name,
661*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
662*de1e4e89SAndroid Build Coastguard Worker 		return ret;
663*de1e4e89SAndroid Build Coastguard Worker 	}
664*de1e4e89SAndroid Build Coastguard Worker 
665*de1e4e89SAndroid Build Coastguard Worker 	ret = mount(full_link, full_name, "none", MS_BIND, NULL);
666*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
667*de1e4e89SAndroid Build Coastguard Worker 		rmdir(full_name);
668*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mount --bind %s %s failed: %s\n",
669*de1e4e89SAndroid Build Coastguard Worker 			full_link, full_name, strerror(errno));
670*de1e4e89SAndroid Build Coastguard Worker 	}
671*de1e4e89SAndroid Build Coastguard Worker 
672*de1e4e89SAndroid Build Coastguard Worker 	return ret;
673*de1e4e89SAndroid Build Coastguard Worker }
674*de1e4e89SAndroid Build Coastguard Worker 
bpf_gen_slave(const char * base,const char * name,const char * link)675*de1e4e89SAndroid Build Coastguard Worker static int bpf_gen_slave(const char *base, const char *name,
676*de1e4e89SAndroid Build Coastguard Worker 			 const char *link)
677*de1e4e89SAndroid Build Coastguard Worker {
678*de1e4e89SAndroid Build Coastguard Worker 	char bpf_lnk_dir[PATH_MAX];
679*de1e4e89SAndroid Build Coastguard Worker 	char bpf_sub_dir[PATH_MAX];
680*de1e4e89SAndroid Build Coastguard Worker 	struct stat sb = {};
681*de1e4e89SAndroid Build Coastguard Worker 	int ret;
682*de1e4e89SAndroid Build Coastguard Worker 
683*de1e4e89SAndroid Build Coastguard Worker 	snprintf(bpf_lnk_dir, sizeof(bpf_lnk_dir), "%s%s/", base, link);
684*de1e4e89SAndroid Build Coastguard Worker 	snprintf(bpf_sub_dir, sizeof(bpf_sub_dir), "%s%s",  base, name);
685*de1e4e89SAndroid Build Coastguard Worker 
686*de1e4e89SAndroid Build Coastguard Worker 	ret = symlink(bpf_lnk_dir, bpf_sub_dir);
687*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
688*de1e4e89SAndroid Build Coastguard Worker 		if (errno != EEXIST) {
689*de1e4e89SAndroid Build Coastguard Worker 			if (errno != EPERM) {
690*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "symlink %s failed: %s\n",
691*de1e4e89SAndroid Build Coastguard Worker 					bpf_sub_dir, strerror(errno));
692*de1e4e89SAndroid Build Coastguard Worker 				return ret;
693*de1e4e89SAndroid Build Coastguard Worker 			}
694*de1e4e89SAndroid Build Coastguard Worker 
695*de1e4e89SAndroid Build Coastguard Worker 			return bpf_slave_via_bind_mnt(bpf_sub_dir,
696*de1e4e89SAndroid Build Coastguard Worker 						      bpf_lnk_dir);
697*de1e4e89SAndroid Build Coastguard Worker 		}
698*de1e4e89SAndroid Build Coastguard Worker 
699*de1e4e89SAndroid Build Coastguard Worker 		ret = lstat(bpf_sub_dir, &sb);
700*de1e4e89SAndroid Build Coastguard Worker 		if (ret) {
701*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "lstat %s failed: %s\n",
702*de1e4e89SAndroid Build Coastguard Worker 				bpf_sub_dir, strerror(errno));
703*de1e4e89SAndroid Build Coastguard Worker 			return ret;
704*de1e4e89SAndroid Build Coastguard Worker 		}
705*de1e4e89SAndroid Build Coastguard Worker 
706*de1e4e89SAndroid Build Coastguard Worker 		if ((sb.st_mode & S_IFMT) != S_IFLNK)
707*de1e4e89SAndroid Build Coastguard Worker 			return bpf_gen_global(bpf_sub_dir);
708*de1e4e89SAndroid Build Coastguard Worker 	}
709*de1e4e89SAndroid Build Coastguard Worker 
710*de1e4e89SAndroid Build Coastguard Worker 	return 0;
711*de1e4e89SAndroid Build Coastguard Worker }
712*de1e4e89SAndroid Build Coastguard Worker 
bpf_gen_hierarchy(const char * base)713*de1e4e89SAndroid Build Coastguard Worker static int bpf_gen_hierarchy(const char *base)
714*de1e4e89SAndroid Build Coastguard Worker {
715*de1e4e89SAndroid Build Coastguard Worker 	int ret, i;
716*de1e4e89SAndroid Build Coastguard Worker 
717*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_gen_master(base, bpf_prog_to_subdir(__bpf_types[0]));
718*de1e4e89SAndroid Build Coastguard Worker 	for (i = 1; i < ARRAY_SIZE(__bpf_types) && !ret; i++)
719*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_gen_slave(base,
720*de1e4e89SAndroid Build Coastguard Worker 				    bpf_prog_to_subdir(__bpf_types[i]),
721*de1e4e89SAndroid Build Coastguard Worker 				    bpf_prog_to_subdir(__bpf_types[0]));
722*de1e4e89SAndroid Build Coastguard Worker 	return ret;
723*de1e4e89SAndroid Build Coastguard Worker }
724*de1e4e89SAndroid Build Coastguard Worker 
bpf_get_work_dir(enum bpf_prog_type type)725*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_get_work_dir(enum bpf_prog_type type)
726*de1e4e89SAndroid Build Coastguard Worker {
727*de1e4e89SAndroid Build Coastguard Worker 	static char bpf_tmp[PATH_MAX] = BPF_DIR_MNT;
728*de1e4e89SAndroid Build Coastguard Worker 	static char bpf_wrk_dir[PATH_MAX];
729*de1e4e89SAndroid Build Coastguard Worker 	static const char *mnt;
730*de1e4e89SAndroid Build Coastguard Worker 	static bool bpf_mnt_cached;
731*de1e4e89SAndroid Build Coastguard Worker 	const char *mnt_env = getenv(BPF_ENV_MNT);
732*de1e4e89SAndroid Build Coastguard Worker 	static const char * const bpf_known_mnts[] = {
733*de1e4e89SAndroid Build Coastguard Worker 		BPF_DIR_MNT,
734*de1e4e89SAndroid Build Coastguard Worker 		"/bpf",
735*de1e4e89SAndroid Build Coastguard Worker 		0,
736*de1e4e89SAndroid Build Coastguard Worker 	};
737*de1e4e89SAndroid Build Coastguard Worker 	int ret;
738*de1e4e89SAndroid Build Coastguard Worker 
739*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_mnt_cached) {
740*de1e4e89SAndroid Build Coastguard Worker 		const char *out = mnt;
741*de1e4e89SAndroid Build Coastguard Worker 
742*de1e4e89SAndroid Build Coastguard Worker 		if (out && type) {
743*de1e4e89SAndroid Build Coastguard Worker 			snprintf(bpf_tmp, sizeof(bpf_tmp), "%s%s/",
744*de1e4e89SAndroid Build Coastguard Worker 				 out, bpf_prog_to_subdir(type));
745*de1e4e89SAndroid Build Coastguard Worker 			out = bpf_tmp;
746*de1e4e89SAndroid Build Coastguard Worker 		}
747*de1e4e89SAndroid Build Coastguard Worker 		return out;
748*de1e4e89SAndroid Build Coastguard Worker 	}
749*de1e4e89SAndroid Build Coastguard Worker 
750*de1e4e89SAndroid Build Coastguard Worker 	if (mnt_env)
751*de1e4e89SAndroid Build Coastguard Worker 		mnt = bpf_find_mntpt_single(BPF_FS_MAGIC, bpf_tmp,
752*de1e4e89SAndroid Build Coastguard Worker 					    sizeof(bpf_tmp), mnt_env);
753*de1e4e89SAndroid Build Coastguard Worker 	else
754*de1e4e89SAndroid Build Coastguard Worker 		mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_tmp,
755*de1e4e89SAndroid Build Coastguard Worker 				     sizeof(bpf_tmp), bpf_known_mnts);
756*de1e4e89SAndroid Build Coastguard Worker 	if (!mnt) {
757*de1e4e89SAndroid Build Coastguard Worker 		mnt = mnt_env ? : BPF_DIR_MNT;
758*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_mnt_check_target(mnt);
759*de1e4e89SAndroid Build Coastguard Worker 		if (!ret)
760*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_mnt_fs(mnt);
761*de1e4e89SAndroid Build Coastguard Worker 		if (ret) {
762*de1e4e89SAndroid Build Coastguard Worker 			mnt = NULL;
763*de1e4e89SAndroid Build Coastguard Worker 			goto out;
764*de1e4e89SAndroid Build Coastguard Worker 		}
765*de1e4e89SAndroid Build Coastguard Worker 	}
766*de1e4e89SAndroid Build Coastguard Worker 
767*de1e4e89SAndroid Build Coastguard Worker 	snprintf(bpf_wrk_dir, sizeof(bpf_wrk_dir), "%s/", mnt);
768*de1e4e89SAndroid Build Coastguard Worker 
769*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_gen_hierarchy(bpf_wrk_dir);
770*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
771*de1e4e89SAndroid Build Coastguard Worker 		mnt = NULL;
772*de1e4e89SAndroid Build Coastguard Worker 		goto out;
773*de1e4e89SAndroid Build Coastguard Worker 	}
774*de1e4e89SAndroid Build Coastguard Worker 
775*de1e4e89SAndroid Build Coastguard Worker 	mnt = bpf_wrk_dir;
776*de1e4e89SAndroid Build Coastguard Worker out:
777*de1e4e89SAndroid Build Coastguard Worker 	bpf_mnt_cached = true;
778*de1e4e89SAndroid Build Coastguard Worker 	return mnt;
779*de1e4e89SAndroid Build Coastguard Worker }
780*de1e4e89SAndroid Build Coastguard Worker 
bpf_obj_get(const char * pathname,enum bpf_prog_type type)781*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_get(const char *pathname, enum bpf_prog_type type)
782*de1e4e89SAndroid Build Coastguard Worker {
783*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
784*de1e4e89SAndroid Build Coastguard Worker 	char tmp[PATH_MAX];
785*de1e4e89SAndroid Build Coastguard Worker 
786*de1e4e89SAndroid Build Coastguard Worker 	if (strlen(pathname) > 2 && pathname[0] == 'm' &&
787*de1e4e89SAndroid Build Coastguard Worker 	    pathname[1] == ':' && bpf_get_work_dir(type)) {
788*de1e4e89SAndroid Build Coastguard Worker 		snprintf(tmp, sizeof(tmp), "%s/%s",
789*de1e4e89SAndroid Build Coastguard Worker 			 bpf_get_work_dir(type), pathname + 2);
790*de1e4e89SAndroid Build Coastguard Worker 		pathname = tmp;
791*de1e4e89SAndroid Build Coastguard Worker 	}
792*de1e4e89SAndroid Build Coastguard Worker 
793*de1e4e89SAndroid Build Coastguard Worker 	attr.pathname = bpf_ptr_to_u64(pathname);
794*de1e4e89SAndroid Build Coastguard Worker 
795*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_OBJ_GET, &attr, sizeof(attr));
796*de1e4e89SAndroid Build Coastguard Worker }
797*de1e4e89SAndroid Build Coastguard Worker 
bpf_obj_pinned(const char * pathname,enum bpf_prog_type type)798*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_pinned(const char *pathname, enum bpf_prog_type type)
799*de1e4e89SAndroid Build Coastguard Worker {
800*de1e4e89SAndroid Build Coastguard Worker 	int prog_fd = bpf_obj_get(pathname, type);
801*de1e4e89SAndroid Build Coastguard Worker 
802*de1e4e89SAndroid Build Coastguard Worker 	if (prog_fd < 0)
803*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn\'t retrieve pinned program \'%s\': %s\n",
804*de1e4e89SAndroid Build Coastguard Worker 			pathname, strerror(errno));
805*de1e4e89SAndroid Build Coastguard Worker 	return prog_fd;
806*de1e4e89SAndroid Build Coastguard Worker }
807*de1e4e89SAndroid Build Coastguard Worker 
808*de1e4e89SAndroid Build Coastguard Worker enum bpf_mode {
809*de1e4e89SAndroid Build Coastguard Worker 	CBPF_BYTECODE,
810*de1e4e89SAndroid Build Coastguard Worker 	CBPF_FILE,
811*de1e4e89SAndroid Build Coastguard Worker 	EBPF_OBJECT,
812*de1e4e89SAndroid Build Coastguard Worker 	EBPF_PINNED,
813*de1e4e89SAndroid Build Coastguard Worker 	BPF_MODE_MAX,
814*de1e4e89SAndroid Build Coastguard Worker };
815*de1e4e89SAndroid Build Coastguard Worker 
bpf_parse(enum bpf_prog_type * type,enum bpf_mode * mode,struct bpf_cfg_in * cfg,const bool * opt_tbl)816*de1e4e89SAndroid Build Coastguard Worker static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
817*de1e4e89SAndroid Build Coastguard Worker 		     struct bpf_cfg_in *cfg, const bool *opt_tbl)
818*de1e4e89SAndroid Build Coastguard Worker {
819*de1e4e89SAndroid Build Coastguard Worker 	const char *file, *section, *uds_name;
820*de1e4e89SAndroid Build Coastguard Worker 	bool verbose = false;
821*de1e4e89SAndroid Build Coastguard Worker 	int i, ret, argc;
822*de1e4e89SAndroid Build Coastguard Worker 	char **argv;
823*de1e4e89SAndroid Build Coastguard Worker 
824*de1e4e89SAndroid Build Coastguard Worker 	argv = cfg->argv;
825*de1e4e89SAndroid Build Coastguard Worker 	argc = cfg->argc;
826*de1e4e89SAndroid Build Coastguard Worker 
827*de1e4e89SAndroid Build Coastguard Worker 	if (opt_tbl[CBPF_BYTECODE] &&
828*de1e4e89SAndroid Build Coastguard Worker 	    (matches(*argv, "bytecode") == 0 ||
829*de1e4e89SAndroid Build Coastguard Worker 	     strcmp(*argv, "bc") == 0)) {
830*de1e4e89SAndroid Build Coastguard Worker 		*mode = CBPF_BYTECODE;
831*de1e4e89SAndroid Build Coastguard Worker 	} else if (opt_tbl[CBPF_FILE] &&
832*de1e4e89SAndroid Build Coastguard Worker 		   (matches(*argv, "bytecode-file") == 0 ||
833*de1e4e89SAndroid Build Coastguard Worker 		    strcmp(*argv, "bcf") == 0)) {
834*de1e4e89SAndroid Build Coastguard Worker 		*mode = CBPF_FILE;
835*de1e4e89SAndroid Build Coastguard Worker 	} else if (opt_tbl[EBPF_OBJECT] &&
836*de1e4e89SAndroid Build Coastguard Worker 		   (matches(*argv, "object-file") == 0 ||
837*de1e4e89SAndroid Build Coastguard Worker 		    strcmp(*argv, "obj") == 0)) {
838*de1e4e89SAndroid Build Coastguard Worker 		*mode = EBPF_OBJECT;
839*de1e4e89SAndroid Build Coastguard Worker 	} else if (opt_tbl[EBPF_PINNED] &&
840*de1e4e89SAndroid Build Coastguard Worker 		   (matches(*argv, "object-pinned") == 0 ||
841*de1e4e89SAndroid Build Coastguard Worker 		    matches(*argv, "pinned") == 0 ||
842*de1e4e89SAndroid Build Coastguard Worker 		    matches(*argv, "fd") == 0)) {
843*de1e4e89SAndroid Build Coastguard Worker 		*mode = EBPF_PINNED;
844*de1e4e89SAndroid Build Coastguard Worker 	} else {
845*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "What mode is \"%s\"?\n", *argv);
846*de1e4e89SAndroid Build Coastguard Worker 		return -1;
847*de1e4e89SAndroid Build Coastguard Worker 	}
848*de1e4e89SAndroid Build Coastguard Worker 
849*de1e4e89SAndroid Build Coastguard Worker 	NEXT_ARG();
850*de1e4e89SAndroid Build Coastguard Worker 	file = section = uds_name = NULL;
851*de1e4e89SAndroid Build Coastguard Worker 	if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) {
852*de1e4e89SAndroid Build Coastguard Worker 		file = *argv;
853*de1e4e89SAndroid Build Coastguard Worker 		NEXT_ARG_FWD();
854*de1e4e89SAndroid Build Coastguard Worker 
855*de1e4e89SAndroid Build Coastguard Worker 		if (*type == BPF_PROG_TYPE_UNSPEC) {
856*de1e4e89SAndroid Build Coastguard Worker 			if (argc > 0 && matches(*argv, "type") == 0) {
857*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
858*de1e4e89SAndroid Build Coastguard Worker 				for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta);
859*de1e4e89SAndroid Build Coastguard Worker 				     i++) {
860*de1e4e89SAndroid Build Coastguard Worker 					if (!__bpf_prog_meta[i].type)
861*de1e4e89SAndroid Build Coastguard Worker 						continue;
862*de1e4e89SAndroid Build Coastguard Worker 					if (!matches(*argv,
863*de1e4e89SAndroid Build Coastguard Worker 						     __bpf_prog_meta[i].type)) {
864*de1e4e89SAndroid Build Coastguard Worker 						*type = i;
865*de1e4e89SAndroid Build Coastguard Worker 						break;
866*de1e4e89SAndroid Build Coastguard Worker 					}
867*de1e4e89SAndroid Build Coastguard Worker 				}
868*de1e4e89SAndroid Build Coastguard Worker 
869*de1e4e89SAndroid Build Coastguard Worker 				if (*type == BPF_PROG_TYPE_UNSPEC) {
870*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "What type is \"%s\"?\n",
871*de1e4e89SAndroid Build Coastguard Worker 						*argv);
872*de1e4e89SAndroid Build Coastguard Worker 					return -1;
873*de1e4e89SAndroid Build Coastguard Worker 				}
874*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG_FWD();
875*de1e4e89SAndroid Build Coastguard Worker 			} else {
876*de1e4e89SAndroid Build Coastguard Worker 				*type = BPF_PROG_TYPE_SCHED_CLS;
877*de1e4e89SAndroid Build Coastguard Worker 			}
878*de1e4e89SAndroid Build Coastguard Worker 		}
879*de1e4e89SAndroid Build Coastguard Worker 
880*de1e4e89SAndroid Build Coastguard Worker 		section = bpf_prog_to_default_section(*type);
881*de1e4e89SAndroid Build Coastguard Worker 		if (argc > 0 && matches(*argv, "section") == 0) {
882*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
883*de1e4e89SAndroid Build Coastguard Worker 			section = *argv;
884*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG_FWD();
885*de1e4e89SAndroid Build Coastguard Worker 		}
886*de1e4e89SAndroid Build Coastguard Worker 
887*de1e4e89SAndroid Build Coastguard Worker 		if (__bpf_prog_meta[*type].may_uds_export) {
888*de1e4e89SAndroid Build Coastguard Worker 			uds_name = getenv(BPF_ENV_UDS);
889*de1e4e89SAndroid Build Coastguard Worker 			if (argc > 0 && !uds_name &&
890*de1e4e89SAndroid Build Coastguard Worker 			    matches(*argv, "export") == 0) {
891*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
892*de1e4e89SAndroid Build Coastguard Worker 				uds_name = *argv;
893*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG_FWD();
894*de1e4e89SAndroid Build Coastguard Worker 			}
895*de1e4e89SAndroid Build Coastguard Worker 		}
896*de1e4e89SAndroid Build Coastguard Worker 
897*de1e4e89SAndroid Build Coastguard Worker 		if (argc > 0 && matches(*argv, "verbose") == 0) {
898*de1e4e89SAndroid Build Coastguard Worker 			verbose = true;
899*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG_FWD();
900*de1e4e89SAndroid Build Coastguard Worker 		}
901*de1e4e89SAndroid Build Coastguard Worker 
902*de1e4e89SAndroid Build Coastguard Worker 		PREV_ARG();
903*de1e4e89SAndroid Build Coastguard Worker 	}
904*de1e4e89SAndroid Build Coastguard Worker 
905*de1e4e89SAndroid Build Coastguard Worker 	if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE)
906*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE);
907*de1e4e89SAndroid Build Coastguard Worker 	else if (*mode == EBPF_OBJECT)
908*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_obj_open(file, *type, section, verbose);
909*de1e4e89SAndroid Build Coastguard Worker 	else if (*mode == EBPF_PINNED)
910*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_obj_pinned(file, *type);
911*de1e4e89SAndroid Build Coastguard Worker 	else
912*de1e4e89SAndroid Build Coastguard Worker 		return -1;
913*de1e4e89SAndroid Build Coastguard Worker 
914*de1e4e89SAndroid Build Coastguard Worker 	cfg->object  = file;
915*de1e4e89SAndroid Build Coastguard Worker 	cfg->section = section;
916*de1e4e89SAndroid Build Coastguard Worker 	cfg->uds     = uds_name;
917*de1e4e89SAndroid Build Coastguard Worker 	cfg->argc    = argc;
918*de1e4e89SAndroid Build Coastguard Worker 	cfg->argv    = argv;
919*de1e4e89SAndroid Build Coastguard Worker 
920*de1e4e89SAndroid Build Coastguard Worker 	return ret;
921*de1e4e89SAndroid Build Coastguard Worker }
922*de1e4e89SAndroid Build Coastguard Worker 
bpf_parse_opt_tbl(enum bpf_prog_type type,struct bpf_cfg_in * cfg,const struct bpf_cfg_ops * ops,void * nl,const bool * opt_tbl)923*de1e4e89SAndroid Build Coastguard Worker static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
924*de1e4e89SAndroid Build Coastguard Worker 			     const struct bpf_cfg_ops *ops, void *nl,
925*de1e4e89SAndroid Build Coastguard Worker 			     const bool *opt_tbl)
926*de1e4e89SAndroid Build Coastguard Worker {
927*de1e4e89SAndroid Build Coastguard Worker 	struct sock_filter opcodes[BPF_MAXINSNS];
928*de1e4e89SAndroid Build Coastguard Worker 	char annotation[256];
929*de1e4e89SAndroid Build Coastguard Worker 	enum bpf_mode mode;
930*de1e4e89SAndroid Build Coastguard Worker 	int ret;
931*de1e4e89SAndroid Build Coastguard Worker 
932*de1e4e89SAndroid Build Coastguard Worker 	cfg->ops = opcodes;
933*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_parse(&type, &mode, cfg, opt_tbl);
934*de1e4e89SAndroid Build Coastguard Worker 	cfg->ops = NULL;
935*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
936*de1e4e89SAndroid Build Coastguard Worker 		return ret;
937*de1e4e89SAndroid Build Coastguard Worker 
938*de1e4e89SAndroid Build Coastguard Worker 	if (mode == CBPF_BYTECODE || mode == CBPF_FILE)
939*de1e4e89SAndroid Build Coastguard Worker 		ops->cbpf_cb(nl, opcodes, ret);
940*de1e4e89SAndroid Build Coastguard Worker 	if (mode == EBPF_OBJECT || mode == EBPF_PINNED) {
941*de1e4e89SAndroid Build Coastguard Worker 		snprintf(annotation, sizeof(annotation), "%s:[%s]",
942*de1e4e89SAndroid Build Coastguard Worker 			 basename(cfg->object), mode == EBPF_PINNED ?
943*de1e4e89SAndroid Build Coastguard Worker 			 "*fsobj" : cfg->section);
944*de1e4e89SAndroid Build Coastguard Worker 		ops->ebpf_cb(nl, ret, annotation);
945*de1e4e89SAndroid Build Coastguard Worker 	}
946*de1e4e89SAndroid Build Coastguard Worker 
947*de1e4e89SAndroid Build Coastguard Worker 	return 0;
948*de1e4e89SAndroid Build Coastguard Worker }
949*de1e4e89SAndroid Build Coastguard Worker 
bpf_parse_common(enum bpf_prog_type type,struct bpf_cfg_in * cfg,const struct bpf_cfg_ops * ops,void * nl)950*de1e4e89SAndroid Build Coastguard Worker int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
951*de1e4e89SAndroid Build Coastguard Worker 		     const struct bpf_cfg_ops *ops, void *nl)
952*de1e4e89SAndroid Build Coastguard Worker {
953*de1e4e89SAndroid Build Coastguard Worker 	bool opt_tbl[BPF_MODE_MAX] = {};
954*de1e4e89SAndroid Build Coastguard Worker 
955*de1e4e89SAndroid Build Coastguard Worker 	if (ops->cbpf_cb) {
956*de1e4e89SAndroid Build Coastguard Worker 		opt_tbl[CBPF_BYTECODE] = true;
957*de1e4e89SAndroid Build Coastguard Worker 		opt_tbl[CBPF_FILE]     = true;
958*de1e4e89SAndroid Build Coastguard Worker 	}
959*de1e4e89SAndroid Build Coastguard Worker 
960*de1e4e89SAndroid Build Coastguard Worker 	if (ops->ebpf_cb) {
961*de1e4e89SAndroid Build Coastguard Worker 		opt_tbl[EBPF_OBJECT]   = true;
962*de1e4e89SAndroid Build Coastguard Worker 		opt_tbl[EBPF_PINNED]   = true;
963*de1e4e89SAndroid Build Coastguard Worker 	}
964*de1e4e89SAndroid Build Coastguard Worker 
965*de1e4e89SAndroid Build Coastguard Worker 	return bpf_parse_opt_tbl(type, cfg, ops, nl, opt_tbl);
966*de1e4e89SAndroid Build Coastguard Worker }
967*de1e4e89SAndroid Build Coastguard Worker 
bpf_graft_map(const char * map_path,uint32_t * key,int argc,char ** argv)968*de1e4e89SAndroid Build Coastguard Worker int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
969*de1e4e89SAndroid Build Coastguard Worker {
970*de1e4e89SAndroid Build Coastguard Worker 	enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC;
971*de1e4e89SAndroid Build Coastguard Worker 	const bool opt_tbl[BPF_MODE_MAX] = {
972*de1e4e89SAndroid Build Coastguard Worker 		[EBPF_OBJECT]	= true,
973*de1e4e89SAndroid Build Coastguard Worker 		[EBPF_PINNED]	= true,
974*de1e4e89SAndroid Build Coastguard Worker 	};
975*de1e4e89SAndroid Build Coastguard Worker 	const struct bpf_elf_map test = {
976*de1e4e89SAndroid Build Coastguard Worker 		.type		= BPF_MAP_TYPE_PROG_ARRAY,
977*de1e4e89SAndroid Build Coastguard Worker 		.size_key	= sizeof(int),
978*de1e4e89SAndroid Build Coastguard Worker 		.size_value	= sizeof(int),
979*de1e4e89SAndroid Build Coastguard Worker 	};
980*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_cfg_in cfg = {
981*de1e4e89SAndroid Build Coastguard Worker 		.argc		= argc,
982*de1e4e89SAndroid Build Coastguard Worker 		.argv		= argv,
983*de1e4e89SAndroid Build Coastguard Worker 	};
984*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_ext ext = {};
985*de1e4e89SAndroid Build Coastguard Worker 	int ret, prog_fd, map_fd;
986*de1e4e89SAndroid Build Coastguard Worker 	enum bpf_mode mode;
987*de1e4e89SAndroid Build Coastguard Worker 	uint32_t map_key;
988*de1e4e89SAndroid Build Coastguard Worker 
989*de1e4e89SAndroid Build Coastguard Worker 	prog_fd = bpf_parse(&type, &mode, &cfg, opt_tbl);
990*de1e4e89SAndroid Build Coastguard Worker 	if (prog_fd < 0)
991*de1e4e89SAndroid Build Coastguard Worker 		return prog_fd;
992*de1e4e89SAndroid Build Coastguard Worker 	if (key) {
993*de1e4e89SAndroid Build Coastguard Worker 		map_key = *key;
994*de1e4e89SAndroid Build Coastguard Worker 	} else {
995*de1e4e89SAndroid Build Coastguard Worker 		ret = sscanf(cfg.section, "%*i/%i", &map_key);
996*de1e4e89SAndroid Build Coastguard Worker 		if (ret != 1) {
997*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Couldn\'t infer map key from section name! Please provide \'key\' argument!\n");
998*de1e4e89SAndroid Build Coastguard Worker 			ret = -EINVAL;
999*de1e4e89SAndroid Build Coastguard Worker 			goto out_prog;
1000*de1e4e89SAndroid Build Coastguard Worker 		}
1001*de1e4e89SAndroid Build Coastguard Worker 	}
1002*de1e4e89SAndroid Build Coastguard Worker 
1003*de1e4e89SAndroid Build Coastguard Worker 	map_fd = bpf_obj_get(map_path, type);
1004*de1e4e89SAndroid Build Coastguard Worker 	if (map_fd < 0) {
1005*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
1006*de1e4e89SAndroid Build Coastguard Worker 			map_path, strerror(errno));
1007*de1e4e89SAndroid Build Coastguard Worker 		ret = map_fd;
1008*de1e4e89SAndroid Build Coastguard Worker 		goto out_prog;
1009*de1e4e89SAndroid Build Coastguard Worker 	}
1010*de1e4e89SAndroid Build Coastguard Worker 
1011*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext,
1012*de1e4e89SAndroid Build Coastguard Worker 				       offsetof(struct bpf_elf_map, max_elem),
1013*de1e4e89SAndroid Build Coastguard Worker 				       type);
1014*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
1015*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
1016*de1e4e89SAndroid Build Coastguard Worker 		goto out_map;
1017*de1e4e89SAndroid Build Coastguard Worker 	}
1018*de1e4e89SAndroid Build Coastguard Worker 
1019*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_map_update(map_fd, &map_key, &prog_fd, BPF_ANY);
1020*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
1021*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Map update failed: %s\n", strerror(errno));
1022*de1e4e89SAndroid Build Coastguard Worker out_map:
1023*de1e4e89SAndroid Build Coastguard Worker 	close(map_fd);
1024*de1e4e89SAndroid Build Coastguard Worker out_prog:
1025*de1e4e89SAndroid Build Coastguard Worker 	close(prog_fd);
1026*de1e4e89SAndroid Build Coastguard Worker 	return ret;
1027*de1e4e89SAndroid Build Coastguard Worker }
1028*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_attach_fd(int prog_fd,int target_fd,enum bpf_attach_type type)1029*de1e4e89SAndroid Build Coastguard Worker int bpf_prog_attach_fd(int prog_fd, int target_fd, enum bpf_attach_type type)
1030*de1e4e89SAndroid Build Coastguard Worker {
1031*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
1032*de1e4e89SAndroid Build Coastguard Worker 
1033*de1e4e89SAndroid Build Coastguard Worker 	attr.target_fd = target_fd;
1034*de1e4e89SAndroid Build Coastguard Worker 	attr.attach_bpf_fd = prog_fd;
1035*de1e4e89SAndroid Build Coastguard Worker 	attr.attach_type = type;
1036*de1e4e89SAndroid Build Coastguard Worker 
1037*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
1038*de1e4e89SAndroid Build Coastguard Worker }
1039*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_detach_fd(int target_fd,enum bpf_attach_type type)1040*de1e4e89SAndroid Build Coastguard Worker int bpf_prog_detach_fd(int target_fd, enum bpf_attach_type type)
1041*de1e4e89SAndroid Build Coastguard Worker {
1042*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
1043*de1e4e89SAndroid Build Coastguard Worker 
1044*de1e4e89SAndroid Build Coastguard Worker 	attr.target_fd = target_fd;
1045*de1e4e89SAndroid Build Coastguard Worker 	attr.attach_type = type;
1046*de1e4e89SAndroid Build Coastguard Worker 
1047*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
1048*de1e4e89SAndroid Build Coastguard Worker }
1049*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_load(enum bpf_prog_type type,const struct bpf_insn * insns,size_t size_insns,const char * license,char * log,size_t size_log)1050*de1e4e89SAndroid Build Coastguard Worker int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
1051*de1e4e89SAndroid Build Coastguard Worker 		  size_t size_insns, const char *license, char *log,
1052*de1e4e89SAndroid Build Coastguard Worker 		  size_t size_log)
1053*de1e4e89SAndroid Build Coastguard Worker {
1054*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
1055*de1e4e89SAndroid Build Coastguard Worker 
1056*de1e4e89SAndroid Build Coastguard Worker 	attr.prog_type = type;
1057*de1e4e89SAndroid Build Coastguard Worker 	attr.insns = bpf_ptr_to_u64(insns);
1058*de1e4e89SAndroid Build Coastguard Worker 	attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
1059*de1e4e89SAndroid Build Coastguard Worker 	attr.license = bpf_ptr_to_u64(license);
1060*de1e4e89SAndroid Build Coastguard Worker 
1061*de1e4e89SAndroid Build Coastguard Worker 	if (size_log > 0) {
1062*de1e4e89SAndroid Build Coastguard Worker 		attr.log_buf = bpf_ptr_to_u64(log);
1063*de1e4e89SAndroid Build Coastguard Worker 		attr.log_size = size_log;
1064*de1e4e89SAndroid Build Coastguard Worker 		attr.log_level = 1;
1065*de1e4e89SAndroid Build Coastguard Worker 	}
1066*de1e4e89SAndroid Build Coastguard Worker 
1067*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
1068*de1e4e89SAndroid Build Coastguard Worker }
1069*de1e4e89SAndroid Build Coastguard Worker 
1070*de1e4e89SAndroid Build Coastguard Worker #ifdef HAVE_ELF
1071*de1e4e89SAndroid Build Coastguard Worker struct bpf_elf_prog {
1072*de1e4e89SAndroid Build Coastguard Worker 	enum bpf_prog_type	type;
1073*de1e4e89SAndroid Build Coastguard Worker 	const struct bpf_insn	*insns;
1074*de1e4e89SAndroid Build Coastguard Worker 	size_t			size;
1075*de1e4e89SAndroid Build Coastguard Worker 	const char		*license;
1076*de1e4e89SAndroid Build Coastguard Worker };
1077*de1e4e89SAndroid Build Coastguard Worker 
1078*de1e4e89SAndroid Build Coastguard Worker struct bpf_hash_entry {
1079*de1e4e89SAndroid Build Coastguard Worker 	unsigned int		pinning;
1080*de1e4e89SAndroid Build Coastguard Worker 	const char		*subpath;
1081*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_hash_entry	*next;
1082*de1e4e89SAndroid Build Coastguard Worker };
1083*de1e4e89SAndroid Build Coastguard Worker 
1084*de1e4e89SAndroid Build Coastguard Worker struct bpf_config {
1085*de1e4e89SAndroid Build Coastguard Worker 	unsigned int		jit_enabled;
1086*de1e4e89SAndroid Build Coastguard Worker };
1087*de1e4e89SAndroid Build Coastguard Worker 
1088*de1e4e89SAndroid Build Coastguard Worker struct bpf_elf_ctx {
1089*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_config	cfg;
1090*de1e4e89SAndroid Build Coastguard Worker 	Elf			*elf_fd;
1091*de1e4e89SAndroid Build Coastguard Worker 	GElf_Ehdr		elf_hdr;
1092*de1e4e89SAndroid Build Coastguard Worker 	Elf_Data		*sym_tab;
1093*de1e4e89SAndroid Build Coastguard Worker 	Elf_Data		*str_tab;
1094*de1e4e89SAndroid Build Coastguard Worker 	int			obj_fd;
1095*de1e4e89SAndroid Build Coastguard Worker 	int			map_fds[ELF_MAX_MAPS];
1096*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map	maps[ELF_MAX_MAPS];
1097*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_ext	maps_ext[ELF_MAX_MAPS];
1098*de1e4e89SAndroid Build Coastguard Worker 	int			sym_num;
1099*de1e4e89SAndroid Build Coastguard Worker 	int			map_num;
1100*de1e4e89SAndroid Build Coastguard Worker 	int			map_len;
1101*de1e4e89SAndroid Build Coastguard Worker 	bool			*sec_done;
1102*de1e4e89SAndroid Build Coastguard Worker 	int			sec_maps;
1103*de1e4e89SAndroid Build Coastguard Worker 	char			license[ELF_MAX_LICENSE_LEN];
1104*de1e4e89SAndroid Build Coastguard Worker 	enum bpf_prog_type	type;
1105*de1e4e89SAndroid Build Coastguard Worker 	bool			verbose;
1106*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_st	stat;
1107*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_hash_entry	*ht[256];
1108*de1e4e89SAndroid Build Coastguard Worker 	char			*log;
1109*de1e4e89SAndroid Build Coastguard Worker 	size_t			log_size;
1110*de1e4e89SAndroid Build Coastguard Worker };
1111*de1e4e89SAndroid Build Coastguard Worker 
1112*de1e4e89SAndroid Build Coastguard Worker struct bpf_elf_sec_data {
1113*de1e4e89SAndroid Build Coastguard Worker 	GElf_Shdr		sec_hdr;
1114*de1e4e89SAndroid Build Coastguard Worker 	Elf_Data		*sec_data;
1115*de1e4e89SAndroid Build Coastguard Worker 	const char		*sec_name;
1116*de1e4e89SAndroid Build Coastguard Worker };
1117*de1e4e89SAndroid Build Coastguard Worker 
1118*de1e4e89SAndroid Build Coastguard Worker struct bpf_map_data {
1119*de1e4e89SAndroid Build Coastguard Worker 	int			*fds;
1120*de1e4e89SAndroid Build Coastguard Worker 	const char		*obj;
1121*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_st	*st;
1122*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map	*ent;
1123*de1e4e89SAndroid Build Coastguard Worker };
1124*de1e4e89SAndroid Build Coastguard Worker 
1125*de1e4e89SAndroid Build Coastguard Worker static __check_format_string(2, 3) void
bpf_dump_error(struct bpf_elf_ctx * ctx,const char * format,...)1126*de1e4e89SAndroid Build Coastguard Worker bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...)
1127*de1e4e89SAndroid Build Coastguard Worker {
1128*de1e4e89SAndroid Build Coastguard Worker 	va_list vl;
1129*de1e4e89SAndroid Build Coastguard Worker 
1130*de1e4e89SAndroid Build Coastguard Worker 	va_start(vl, format);
1131*de1e4e89SAndroid Build Coastguard Worker 	vfprintf(stderr, format, vl);
1132*de1e4e89SAndroid Build Coastguard Worker 	va_end(vl);
1133*de1e4e89SAndroid Build Coastguard Worker 
1134*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->log && ctx->log[0]) {
1135*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->verbose) {
1136*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "%s\n", ctx->log);
1137*de1e4e89SAndroid Build Coastguard Worker 		} else {
1138*de1e4e89SAndroid Build Coastguard Worker 			unsigned int off = 0, len = strlen(ctx->log);
1139*de1e4e89SAndroid Build Coastguard Worker 
1140*de1e4e89SAndroid Build Coastguard Worker 			if (len > BPF_MAX_LOG) {
1141*de1e4e89SAndroid Build Coastguard Worker 				off = len - BPF_MAX_LOG;
1142*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Skipped %u bytes, use \'verb\' option for the full verbose log.\n[...]\n",
1143*de1e4e89SAndroid Build Coastguard Worker 					off);
1144*de1e4e89SAndroid Build Coastguard Worker 			}
1145*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "%s\n", ctx->log + off);
1146*de1e4e89SAndroid Build Coastguard Worker 		}
1147*de1e4e89SAndroid Build Coastguard Worker 
1148*de1e4e89SAndroid Build Coastguard Worker 		memset(ctx->log, 0, ctx->log_size);
1149*de1e4e89SAndroid Build Coastguard Worker 	}
1150*de1e4e89SAndroid Build Coastguard Worker }
1151*de1e4e89SAndroid Build Coastguard Worker 
bpf_log_realloc(struct bpf_elf_ctx * ctx)1152*de1e4e89SAndroid Build Coastguard Worker static int bpf_log_realloc(struct bpf_elf_ctx *ctx)
1153*de1e4e89SAndroid Build Coastguard Worker {
1154*de1e4e89SAndroid Build Coastguard Worker 	const size_t log_max = UINT_MAX >> 8;
1155*de1e4e89SAndroid Build Coastguard Worker 	size_t log_size = ctx->log_size;
1156*de1e4e89SAndroid Build Coastguard Worker 	void *ptr;
1157*de1e4e89SAndroid Build Coastguard Worker 
1158*de1e4e89SAndroid Build Coastguard Worker 	if (!ctx->log) {
1159*de1e4e89SAndroid Build Coastguard Worker 		log_size = 65536;
1160*de1e4e89SAndroid Build Coastguard Worker 	} else if (log_size < log_max) {
1161*de1e4e89SAndroid Build Coastguard Worker 		log_size <<= 1;
1162*de1e4e89SAndroid Build Coastguard Worker 		if (log_size > log_max)
1163*de1e4e89SAndroid Build Coastguard Worker 			log_size = log_max;
1164*de1e4e89SAndroid Build Coastguard Worker 	} else {
1165*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1166*de1e4e89SAndroid Build Coastguard Worker 	}
1167*de1e4e89SAndroid Build Coastguard Worker 
1168*de1e4e89SAndroid Build Coastguard Worker 	ptr = realloc(ctx->log, log_size);
1169*de1e4e89SAndroid Build Coastguard Worker 	if (!ptr)
1170*de1e4e89SAndroid Build Coastguard Worker 		return -ENOMEM;
1171*de1e4e89SAndroid Build Coastguard Worker 
1172*de1e4e89SAndroid Build Coastguard Worker 	ctx->log = ptr;
1173*de1e4e89SAndroid Build Coastguard Worker 	ctx->log_size = log_size;
1174*de1e4e89SAndroid Build Coastguard Worker 
1175*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1176*de1e4e89SAndroid Build Coastguard Worker }
1177*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_create(enum bpf_map_type type,uint32_t size_key,uint32_t size_value,uint32_t max_elem,uint32_t flags,int inner_fd)1178*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_create(enum bpf_map_type type, uint32_t size_key,
1179*de1e4e89SAndroid Build Coastguard Worker 			  uint32_t size_value, uint32_t max_elem,
1180*de1e4e89SAndroid Build Coastguard Worker 			  uint32_t flags, int inner_fd)
1181*de1e4e89SAndroid Build Coastguard Worker {
1182*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
1183*de1e4e89SAndroid Build Coastguard Worker 
1184*de1e4e89SAndroid Build Coastguard Worker 	attr.map_type = type;
1185*de1e4e89SAndroid Build Coastguard Worker 	attr.key_size = size_key;
1186*de1e4e89SAndroid Build Coastguard Worker 	attr.value_size = inner_fd ? sizeof(int) : size_value;
1187*de1e4e89SAndroid Build Coastguard Worker 	attr.max_entries = max_elem;
1188*de1e4e89SAndroid Build Coastguard Worker 	attr.map_flags = flags;
1189*de1e4e89SAndroid Build Coastguard Worker 	attr.inner_map_fd = inner_fd;
1190*de1e4e89SAndroid Build Coastguard Worker 
1191*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
1192*de1e4e89SAndroid Build Coastguard Worker }
1193*de1e4e89SAndroid Build Coastguard Worker 
bpf_obj_pin(int fd,const char * pathname)1194*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_pin(int fd, const char *pathname)
1195*de1e4e89SAndroid Build Coastguard Worker {
1196*de1e4e89SAndroid Build Coastguard Worker 	union bpf_attr attr = {};
1197*de1e4e89SAndroid Build Coastguard Worker 
1198*de1e4e89SAndroid Build Coastguard Worker 	attr.pathname = bpf_ptr_to_u64(pathname);
1199*de1e4e89SAndroid Build Coastguard Worker 	attr.bpf_fd = fd;
1200*de1e4e89SAndroid Build Coastguard Worker 
1201*de1e4e89SAndroid Build Coastguard Worker 	return bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
1202*de1e4e89SAndroid Build Coastguard Worker }
1203*de1e4e89SAndroid Build Coastguard Worker 
bpf_obj_hash(const char * object,uint8_t * out,size_t len)1204*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_hash(const char *object, uint8_t *out, size_t len)
1205*de1e4e89SAndroid Build Coastguard Worker {
1206*de1e4e89SAndroid Build Coastguard Worker 	struct sockaddr_alg alg = {
1207*de1e4e89SAndroid Build Coastguard Worker 		.salg_family	= AF_ALG,
1208*de1e4e89SAndroid Build Coastguard Worker 		.salg_type	= "hash",
1209*de1e4e89SAndroid Build Coastguard Worker 		.salg_name	= "sha1",
1210*de1e4e89SAndroid Build Coastguard Worker 	};
1211*de1e4e89SAndroid Build Coastguard Worker 	int ret, cfd, ofd, ffd;
1212*de1e4e89SAndroid Build Coastguard Worker 	struct stat stbuff;
1213*de1e4e89SAndroid Build Coastguard Worker 	ssize_t size;
1214*de1e4e89SAndroid Build Coastguard Worker 
1215*de1e4e89SAndroid Build Coastguard Worker 	if (!object || len != 20)
1216*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1217*de1e4e89SAndroid Build Coastguard Worker 
1218*de1e4e89SAndroid Build Coastguard Worker 	cfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
1219*de1e4e89SAndroid Build Coastguard Worker 	if (cfd < 0) {
1220*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot get AF_ALG socket: %s\n",
1221*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
1222*de1e4e89SAndroid Build Coastguard Worker 		return cfd;
1223*de1e4e89SAndroid Build Coastguard Worker 	}
1224*de1e4e89SAndroid Build Coastguard Worker 
1225*de1e4e89SAndroid Build Coastguard Worker 	ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg));
1226*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
1227*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error binding socket: %s\n", strerror(errno));
1228*de1e4e89SAndroid Build Coastguard Worker 		goto out_cfd;
1229*de1e4e89SAndroid Build Coastguard Worker 	}
1230*de1e4e89SAndroid Build Coastguard Worker 
1231*de1e4e89SAndroid Build Coastguard Worker 	ofd = accept(cfd, NULL, 0);
1232*de1e4e89SAndroid Build Coastguard Worker 	if (ofd < 0) {
1233*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error accepting socket: %s\n",
1234*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
1235*de1e4e89SAndroid Build Coastguard Worker 		ret = ofd;
1236*de1e4e89SAndroid Build Coastguard Worker 		goto out_cfd;
1237*de1e4e89SAndroid Build Coastguard Worker 	}
1238*de1e4e89SAndroid Build Coastguard Worker 
1239*de1e4e89SAndroid Build Coastguard Worker 	ffd = open(object, O_RDONLY);
1240*de1e4e89SAndroid Build Coastguard Worker 	if (ffd < 0) {
1241*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error opening object %s: %s\n",
1242*de1e4e89SAndroid Build Coastguard Worker 			object, strerror(errno));
1243*de1e4e89SAndroid Build Coastguard Worker 		ret = ffd;
1244*de1e4e89SAndroid Build Coastguard Worker 		goto out_ofd;
1245*de1e4e89SAndroid Build Coastguard Worker 	}
1246*de1e4e89SAndroid Build Coastguard Worker 
1247*de1e4e89SAndroid Build Coastguard Worker 	ret = fstat(ffd, &stbuff);
1248*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
1249*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error doing fstat: %s\n",
1250*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
1251*de1e4e89SAndroid Build Coastguard Worker 		goto out_ffd;
1252*de1e4e89SAndroid Build Coastguard Worker 	}
1253*de1e4e89SAndroid Build Coastguard Worker 
1254*de1e4e89SAndroid Build Coastguard Worker 	size = sendfile(ofd, ffd, NULL, stbuff.st_size);
1255*de1e4e89SAndroid Build Coastguard Worker 	if (size != stbuff.st_size) {
1256*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n",
1257*de1e4e89SAndroid Build Coastguard Worker 			size, stbuff.st_size, strerror(errno));
1258*de1e4e89SAndroid Build Coastguard Worker 		ret = -1;
1259*de1e4e89SAndroid Build Coastguard Worker 		goto out_ffd;
1260*de1e4e89SAndroid Build Coastguard Worker 	}
1261*de1e4e89SAndroid Build Coastguard Worker 
1262*de1e4e89SAndroid Build Coastguard Worker 	size = read(ofd, out, len);
1263*de1e4e89SAndroid Build Coastguard Worker 	if (size != len) {
1264*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n",
1265*de1e4e89SAndroid Build Coastguard Worker 			size, len, strerror(errno));
1266*de1e4e89SAndroid Build Coastguard Worker 		ret = -1;
1267*de1e4e89SAndroid Build Coastguard Worker 	} else {
1268*de1e4e89SAndroid Build Coastguard Worker 		ret = 0;
1269*de1e4e89SAndroid Build Coastguard Worker 	}
1270*de1e4e89SAndroid Build Coastguard Worker out_ffd:
1271*de1e4e89SAndroid Build Coastguard Worker 	close(ffd);
1272*de1e4e89SAndroid Build Coastguard Worker out_ofd:
1273*de1e4e89SAndroid Build Coastguard Worker 	close(ofd);
1274*de1e4e89SAndroid Build Coastguard Worker out_cfd:
1275*de1e4e89SAndroid Build Coastguard Worker 	close(cfd);
1276*de1e4e89SAndroid Build Coastguard Worker 	return ret;
1277*de1e4e89SAndroid Build Coastguard Worker }
1278*de1e4e89SAndroid Build Coastguard Worker 
bpf_get_obj_uid(const char * pathname)1279*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_get_obj_uid(const char *pathname)
1280*de1e4e89SAndroid Build Coastguard Worker {
1281*de1e4e89SAndroid Build Coastguard Worker 	static bool bpf_uid_cached;
1282*de1e4e89SAndroid Build Coastguard Worker 	static char bpf_uid[64];
1283*de1e4e89SAndroid Build Coastguard Worker 	uint8_t tmp[20];
1284*de1e4e89SAndroid Build Coastguard Worker 	int ret;
1285*de1e4e89SAndroid Build Coastguard Worker 
1286*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_uid_cached)
1287*de1e4e89SAndroid Build Coastguard Worker 		goto done;
1288*de1e4e89SAndroid Build Coastguard Worker 
1289*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_obj_hash(pathname, tmp, sizeof(tmp));
1290*de1e4e89SAndroid Build Coastguard Worker 	if (ret) {
1291*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Object hashing failed!\n");
1292*de1e4e89SAndroid Build Coastguard Worker 		return NULL;
1293*de1e4e89SAndroid Build Coastguard Worker 	}
1294*de1e4e89SAndroid Build Coastguard Worker 
1295*de1e4e89SAndroid Build Coastguard Worker 	hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid));
1296*de1e4e89SAndroid Build Coastguard Worker 	bpf_uid_cached = true;
1297*de1e4e89SAndroid Build Coastguard Worker done:
1298*de1e4e89SAndroid Build Coastguard Worker 	return bpf_uid;
1299*de1e4e89SAndroid Build Coastguard Worker }
1300*de1e4e89SAndroid Build Coastguard Worker 
bpf_init_env(const char * pathname)1301*de1e4e89SAndroid Build Coastguard Worker static int bpf_init_env(const char *pathname)
1302*de1e4e89SAndroid Build Coastguard Worker {
1303*de1e4e89SAndroid Build Coastguard Worker 	struct rlimit limit = {
1304*de1e4e89SAndroid Build Coastguard Worker 		.rlim_cur = RLIM_INFINITY,
1305*de1e4e89SAndroid Build Coastguard Worker 		.rlim_max = RLIM_INFINITY,
1306*de1e4e89SAndroid Build Coastguard Worker 	};
1307*de1e4e89SAndroid Build Coastguard Worker 
1308*de1e4e89SAndroid Build Coastguard Worker 	/* Don't bother in case we fail! */
1309*de1e4e89SAndroid Build Coastguard Worker 	setrlimit(RLIMIT_MEMLOCK, &limit);
1310*de1e4e89SAndroid Build Coastguard Worker 
1311*de1e4e89SAndroid Build Coastguard Worker 	if (!bpf_get_work_dir(BPF_PROG_TYPE_UNSPEC)) {
1312*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Continuing without mounted eBPF fs. Too old kernel?\n");
1313*de1e4e89SAndroid Build Coastguard Worker 		return 0;
1314*de1e4e89SAndroid Build Coastguard Worker 	}
1315*de1e4e89SAndroid Build Coastguard Worker 
1316*de1e4e89SAndroid Build Coastguard Worker 	if (!bpf_get_obj_uid(pathname))
1317*de1e4e89SAndroid Build Coastguard Worker 		return -1;
1318*de1e4e89SAndroid Build Coastguard Worker 
1319*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1320*de1e4e89SAndroid Build Coastguard Worker }
1321*de1e4e89SAndroid Build Coastguard Worker 
bpf_custom_pinning(const struct bpf_elf_ctx * ctx,uint32_t pinning)1322*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_custom_pinning(const struct bpf_elf_ctx *ctx,
1323*de1e4e89SAndroid Build Coastguard Worker 				      uint32_t pinning)
1324*de1e4e89SAndroid Build Coastguard Worker {
1325*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_hash_entry *entry;
1326*de1e4e89SAndroid Build Coastguard Worker 
1327*de1e4e89SAndroid Build Coastguard Worker 	entry = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)];
1328*de1e4e89SAndroid Build Coastguard Worker 	while (entry && entry->pinning != pinning)
1329*de1e4e89SAndroid Build Coastguard Worker 		entry = entry->next;
1330*de1e4e89SAndroid Build Coastguard Worker 
1331*de1e4e89SAndroid Build Coastguard Worker 	return entry ? entry->subpath : NULL;
1332*de1e4e89SAndroid Build Coastguard Worker }
1333*de1e4e89SAndroid Build Coastguard Worker 
bpf_no_pinning(const struct bpf_elf_ctx * ctx,uint32_t pinning)1334*de1e4e89SAndroid Build Coastguard Worker static bool bpf_no_pinning(const struct bpf_elf_ctx *ctx,
1335*de1e4e89SAndroid Build Coastguard Worker 			   uint32_t pinning)
1336*de1e4e89SAndroid Build Coastguard Worker {
1337*de1e4e89SAndroid Build Coastguard Worker 	switch (pinning) {
1338*de1e4e89SAndroid Build Coastguard Worker 	case PIN_OBJECT_NS:
1339*de1e4e89SAndroid Build Coastguard Worker 	case PIN_GLOBAL_NS:
1340*de1e4e89SAndroid Build Coastguard Worker 		return false;
1341*de1e4e89SAndroid Build Coastguard Worker 	case PIN_NONE:
1342*de1e4e89SAndroid Build Coastguard Worker 		return true;
1343*de1e4e89SAndroid Build Coastguard Worker 	default:
1344*de1e4e89SAndroid Build Coastguard Worker 		return !bpf_custom_pinning(ctx, pinning);
1345*de1e4e89SAndroid Build Coastguard Worker 	}
1346*de1e4e89SAndroid Build Coastguard Worker }
1347*de1e4e89SAndroid Build Coastguard Worker 
bpf_make_pathname(char * pathname,size_t len,const char * name,const struct bpf_elf_ctx * ctx,uint32_t pinning)1348*de1e4e89SAndroid Build Coastguard Worker static void bpf_make_pathname(char *pathname, size_t len, const char *name,
1349*de1e4e89SAndroid Build Coastguard Worker 			      const struct bpf_elf_ctx *ctx, uint32_t pinning)
1350*de1e4e89SAndroid Build Coastguard Worker {
1351*de1e4e89SAndroid Build Coastguard Worker 	switch (pinning) {
1352*de1e4e89SAndroid Build Coastguard Worker 	case PIN_OBJECT_NS:
1353*de1e4e89SAndroid Build Coastguard Worker 		snprintf(pathname, len, "%s/%s/%s",
1354*de1e4e89SAndroid Build Coastguard Worker 			 bpf_get_work_dir(ctx->type),
1355*de1e4e89SAndroid Build Coastguard Worker 			 bpf_get_obj_uid(NULL), name);
1356*de1e4e89SAndroid Build Coastguard Worker 		break;
1357*de1e4e89SAndroid Build Coastguard Worker 	case PIN_GLOBAL_NS:
1358*de1e4e89SAndroid Build Coastguard Worker 		snprintf(pathname, len, "%s/%s/%s",
1359*de1e4e89SAndroid Build Coastguard Worker 			 bpf_get_work_dir(ctx->type),
1360*de1e4e89SAndroid Build Coastguard Worker 			 BPF_DIR_GLOBALS, name);
1361*de1e4e89SAndroid Build Coastguard Worker 		break;
1362*de1e4e89SAndroid Build Coastguard Worker 	default:
1363*de1e4e89SAndroid Build Coastguard Worker 		snprintf(pathname, len, "%s/../%s/%s",
1364*de1e4e89SAndroid Build Coastguard Worker 			 bpf_get_work_dir(ctx->type),
1365*de1e4e89SAndroid Build Coastguard Worker 			 bpf_custom_pinning(ctx, pinning), name);
1366*de1e4e89SAndroid Build Coastguard Worker 		break;
1367*de1e4e89SAndroid Build Coastguard Worker 	}
1368*de1e4e89SAndroid Build Coastguard Worker }
1369*de1e4e89SAndroid Build Coastguard Worker 
bpf_probe_pinned(const char * name,const struct bpf_elf_ctx * ctx,uint32_t pinning)1370*de1e4e89SAndroid Build Coastguard Worker static int bpf_probe_pinned(const char *name, const struct bpf_elf_ctx *ctx,
1371*de1e4e89SAndroid Build Coastguard Worker 			    uint32_t pinning)
1372*de1e4e89SAndroid Build Coastguard Worker {
1373*de1e4e89SAndroid Build Coastguard Worker 	char pathname[PATH_MAX];
1374*de1e4e89SAndroid Build Coastguard Worker 
1375*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_no_pinning(ctx, pinning) || !bpf_get_work_dir(ctx->type))
1376*de1e4e89SAndroid Build Coastguard Worker 		return 0;
1377*de1e4e89SAndroid Build Coastguard Worker 
1378*de1e4e89SAndroid Build Coastguard Worker 	bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning);
1379*de1e4e89SAndroid Build Coastguard Worker 	return bpf_obj_get(pathname, ctx->type);
1380*de1e4e89SAndroid Build Coastguard Worker }
1381*de1e4e89SAndroid Build Coastguard Worker 
bpf_make_obj_path(const struct bpf_elf_ctx * ctx)1382*de1e4e89SAndroid Build Coastguard Worker static int bpf_make_obj_path(const struct bpf_elf_ctx *ctx)
1383*de1e4e89SAndroid Build Coastguard Worker {
1384*de1e4e89SAndroid Build Coastguard Worker 	char tmp[PATH_MAX];
1385*de1e4e89SAndroid Build Coastguard Worker 	int ret;
1386*de1e4e89SAndroid Build Coastguard Worker 
1387*de1e4e89SAndroid Build Coastguard Worker 	snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_work_dir(ctx->type),
1388*de1e4e89SAndroid Build Coastguard Worker 		 bpf_get_obj_uid(NULL));
1389*de1e4e89SAndroid Build Coastguard Worker 
1390*de1e4e89SAndroid Build Coastguard Worker 	ret = mkdir(tmp, S_IRWXU);
1391*de1e4e89SAndroid Build Coastguard Worker 	if (ret && errno != EEXIST) {
1392*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mkdir %s failed: %s\n", tmp, strerror(errno));
1393*de1e4e89SAndroid Build Coastguard Worker 		return ret;
1394*de1e4e89SAndroid Build Coastguard Worker 	}
1395*de1e4e89SAndroid Build Coastguard Worker 
1396*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1397*de1e4e89SAndroid Build Coastguard Worker }
1398*de1e4e89SAndroid Build Coastguard Worker 
bpf_make_custom_path(const struct bpf_elf_ctx * ctx,const char * todo)1399*de1e4e89SAndroid Build Coastguard Worker static int bpf_make_custom_path(const struct bpf_elf_ctx *ctx,
1400*de1e4e89SAndroid Build Coastguard Worker 				const char *todo)
1401*de1e4e89SAndroid Build Coastguard Worker {
1402*de1e4e89SAndroid Build Coastguard Worker 	char tmp[PATH_MAX], rem[PATH_MAX], *sub;
1403*de1e4e89SAndroid Build Coastguard Worker 	int ret;
1404*de1e4e89SAndroid Build Coastguard Worker 
1405*de1e4e89SAndroid Build Coastguard Worker 	snprintf(tmp, sizeof(tmp), "%s/../", bpf_get_work_dir(ctx->type));
1406*de1e4e89SAndroid Build Coastguard Worker 	snprintf(rem, sizeof(rem), "%s/", todo);
1407*de1e4e89SAndroid Build Coastguard Worker 	sub = strtok(rem, "/");
1408*de1e4e89SAndroid Build Coastguard Worker 
1409*de1e4e89SAndroid Build Coastguard Worker 	while (sub) {
1410*de1e4e89SAndroid Build Coastguard Worker 		if (strlen(tmp) + strlen(sub) + 2 > PATH_MAX)
1411*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
1412*de1e4e89SAndroid Build Coastguard Worker 
1413*de1e4e89SAndroid Build Coastguard Worker 		strcat(tmp, sub);
1414*de1e4e89SAndroid Build Coastguard Worker 		strcat(tmp, "/");
1415*de1e4e89SAndroid Build Coastguard Worker 
1416*de1e4e89SAndroid Build Coastguard Worker 		ret = mkdir(tmp, S_IRWXU);
1417*de1e4e89SAndroid Build Coastguard Worker 		if (ret && errno != EEXIST) {
1418*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "mkdir %s failed: %s\n", tmp,
1419*de1e4e89SAndroid Build Coastguard Worker 				strerror(errno));
1420*de1e4e89SAndroid Build Coastguard Worker 			return ret;
1421*de1e4e89SAndroid Build Coastguard Worker 		}
1422*de1e4e89SAndroid Build Coastguard Worker 
1423*de1e4e89SAndroid Build Coastguard Worker 		sub = strtok(NULL, "/");
1424*de1e4e89SAndroid Build Coastguard Worker 	}
1425*de1e4e89SAndroid Build Coastguard Worker 
1426*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1427*de1e4e89SAndroid Build Coastguard Worker }
1428*de1e4e89SAndroid Build Coastguard Worker 
bpf_place_pinned(int fd,const char * name,const struct bpf_elf_ctx * ctx,uint32_t pinning)1429*de1e4e89SAndroid Build Coastguard Worker static int bpf_place_pinned(int fd, const char *name,
1430*de1e4e89SAndroid Build Coastguard Worker 			    const struct bpf_elf_ctx *ctx, uint32_t pinning)
1431*de1e4e89SAndroid Build Coastguard Worker {
1432*de1e4e89SAndroid Build Coastguard Worker 	char pathname[PATH_MAX];
1433*de1e4e89SAndroid Build Coastguard Worker 	const char *tmp;
1434*de1e4e89SAndroid Build Coastguard Worker 	int ret = 0;
1435*de1e4e89SAndroid Build Coastguard Worker 
1436*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_no_pinning(ctx, pinning) || !bpf_get_work_dir(ctx->type))
1437*de1e4e89SAndroid Build Coastguard Worker 		return 0;
1438*de1e4e89SAndroid Build Coastguard Worker 
1439*de1e4e89SAndroid Build Coastguard Worker 	if (pinning == PIN_OBJECT_NS)
1440*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_make_obj_path(ctx);
1441*de1e4e89SAndroid Build Coastguard Worker 	else if ((tmp = bpf_custom_pinning(ctx, pinning)))
1442*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_make_custom_path(ctx, tmp);
1443*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
1444*de1e4e89SAndroid Build Coastguard Worker 		return ret;
1445*de1e4e89SAndroid Build Coastguard Worker 
1446*de1e4e89SAndroid Build Coastguard Worker 	bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning);
1447*de1e4e89SAndroid Build Coastguard Worker 	return bpf_obj_pin(fd, pathname);
1448*de1e4e89SAndroid Build Coastguard Worker }
1449*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_report(int fd,const char * section,const struct bpf_elf_prog * prog,struct bpf_elf_ctx * ctx)1450*de1e4e89SAndroid Build Coastguard Worker static void bpf_prog_report(int fd, const char *section,
1451*de1e4e89SAndroid Build Coastguard Worker 			    const struct bpf_elf_prog *prog,
1452*de1e4e89SAndroid Build Coastguard Worker 			    struct bpf_elf_ctx *ctx)
1453*de1e4e89SAndroid Build Coastguard Worker {
1454*de1e4e89SAndroid Build Coastguard Worker 	unsigned int insns = prog->size / sizeof(struct bpf_insn);
1455*de1e4e89SAndroid Build Coastguard Worker 
1456*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\nProg section \'%s\' %s%s (%d)!\n", section,
1457*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? "rejected: " : "loaded",
1458*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? strerror(errno) : "",
1459*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? errno : fd);
1460*de1e4e89SAndroid Build Coastguard Worker 
1461*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Type:         %u\n", prog->type);
1462*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Instructions: %u (%u over limit)\n",
1463*de1e4e89SAndroid Build Coastguard Worker 		insns, insns > BPF_MAXINSNS ? insns - BPF_MAXINSNS : 0);
1464*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - License:      %s\n\n", prog->license);
1465*de1e4e89SAndroid Build Coastguard Worker 
1466*de1e4e89SAndroid Build Coastguard Worker 	bpf_dump_error(ctx, "Verifier analysis:\n\n");
1467*de1e4e89SAndroid Build Coastguard Worker }
1468*de1e4e89SAndroid Build Coastguard Worker 
bpf_prog_attach(const char * section,const struct bpf_elf_prog * prog,struct bpf_elf_ctx * ctx)1469*de1e4e89SAndroid Build Coastguard Worker static int bpf_prog_attach(const char *section,
1470*de1e4e89SAndroid Build Coastguard Worker 			   const struct bpf_elf_prog *prog,
1471*de1e4e89SAndroid Build Coastguard Worker 			   struct bpf_elf_ctx *ctx)
1472*de1e4e89SAndroid Build Coastguard Worker {
1473*de1e4e89SAndroid Build Coastguard Worker 	int tries = 0, fd;
1474*de1e4e89SAndroid Build Coastguard Worker retry:
1475*de1e4e89SAndroid Build Coastguard Worker 	errno = 0;
1476*de1e4e89SAndroid Build Coastguard Worker 	fd = bpf_prog_load(prog->type, prog->insns, prog->size,
1477*de1e4e89SAndroid Build Coastguard Worker 			   prog->license, ctx->log, ctx->log_size);
1478*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0 || ctx->verbose) {
1479*de1e4e89SAndroid Build Coastguard Worker 		/* The verifier log is pretty chatty, sometimes so chatty
1480*de1e4e89SAndroid Build Coastguard Worker 		 * on larger programs, that we could fail to dump everything
1481*de1e4e89SAndroid Build Coastguard Worker 		 * into our buffer. Still, try to give a debuggable error
1482*de1e4e89SAndroid Build Coastguard Worker 		 * log for the user, so enlarge it and re-fail.
1483*de1e4e89SAndroid Build Coastguard Worker 		 */
1484*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0 && (errno == ENOSPC || !ctx->log_size)) {
1485*de1e4e89SAndroid Build Coastguard Worker 			if (tries++ < 10 && !bpf_log_realloc(ctx))
1486*de1e4e89SAndroid Build Coastguard Worker 				goto retry;
1487*de1e4e89SAndroid Build Coastguard Worker 
1488*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Log buffer too small to dump verifier log %zu bytes (%d tries)!\n",
1489*de1e4e89SAndroid Build Coastguard Worker 				ctx->log_size, tries);
1490*de1e4e89SAndroid Build Coastguard Worker 			return fd;
1491*de1e4e89SAndroid Build Coastguard Worker 		}
1492*de1e4e89SAndroid Build Coastguard Worker 
1493*de1e4e89SAndroid Build Coastguard Worker 		bpf_prog_report(fd, section, prog, ctx);
1494*de1e4e89SAndroid Build Coastguard Worker 	}
1495*de1e4e89SAndroid Build Coastguard Worker 
1496*de1e4e89SAndroid Build Coastguard Worker 	return fd;
1497*de1e4e89SAndroid Build Coastguard Worker }
1498*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_report(int fd,const char * name,const struct bpf_elf_map * map,struct bpf_elf_ctx * ctx,int inner_fd)1499*de1e4e89SAndroid Build Coastguard Worker static void bpf_map_report(int fd, const char *name,
1500*de1e4e89SAndroid Build Coastguard Worker 			   const struct bpf_elf_map *map,
1501*de1e4e89SAndroid Build Coastguard Worker 			   struct bpf_elf_ctx *ctx, int inner_fd)
1502*de1e4e89SAndroid Build Coastguard Worker {
1503*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Map object \'%s\' %s%s (%d)!\n", name,
1504*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? "rejected: " : "loaded",
1505*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? strerror(errno) : "",
1506*de1e4e89SAndroid Build Coastguard Worker 		fd < 0 ? errno : fd);
1507*de1e4e89SAndroid Build Coastguard Worker 
1508*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Type:         %u\n", map->type);
1509*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Identifier:   %u\n", map->id);
1510*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Pinning:      %u\n", map->pinning);
1511*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Size key:     %u\n", map->size_key);
1512*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Size value:   %u\n",
1513*de1e4e89SAndroid Build Coastguard Worker 		inner_fd ? (int)sizeof(int) : map->size_value);
1514*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Max elems:    %u\n", map->max_elem);
1515*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, " - Flags:        %#x\n\n", map->flags);
1516*de1e4e89SAndroid Build Coastguard Worker }
1517*de1e4e89SAndroid Build Coastguard Worker 
bpf_find_map_id(const struct bpf_elf_ctx * ctx,uint32_t id)1518*de1e4e89SAndroid Build Coastguard Worker static int bpf_find_map_id(const struct bpf_elf_ctx *ctx, uint32_t id)
1519*de1e4e89SAndroid Build Coastguard Worker {
1520*de1e4e89SAndroid Build Coastguard Worker 	int i;
1521*de1e4e89SAndroid Build Coastguard Worker 
1522*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ctx->map_num; i++) {
1523*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->maps[i].id != id)
1524*de1e4e89SAndroid Build Coastguard Worker 			continue;
1525*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->map_fds[i] < 0)
1526*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
1527*de1e4e89SAndroid Build Coastguard Worker 
1528*de1e4e89SAndroid Build Coastguard Worker 		return ctx->map_fds[i];
1529*de1e4e89SAndroid Build Coastguard Worker 	}
1530*de1e4e89SAndroid Build Coastguard Worker 
1531*de1e4e89SAndroid Build Coastguard Worker 	return -ENOENT;
1532*de1e4e89SAndroid Build Coastguard Worker }
1533*de1e4e89SAndroid Build Coastguard Worker 
bpf_report_map_in_map(int outer_fd,uint32_t idx)1534*de1e4e89SAndroid Build Coastguard Worker static void bpf_report_map_in_map(int outer_fd, uint32_t idx)
1535*de1e4e89SAndroid Build Coastguard Worker {
1536*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map outer_map;
1537*de1e4e89SAndroid Build Coastguard Worker 	int ret;
1538*de1e4e89SAndroid Build Coastguard Worker 
1539*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Cannot insert map into map! ");
1540*de1e4e89SAndroid Build Coastguard Worker 
1541*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_derive_elf_map_from_fdinfo(outer_fd, &outer_map, NULL);
1542*de1e4e89SAndroid Build Coastguard Worker 	if (!ret) {
1543*de1e4e89SAndroid Build Coastguard Worker 		if (idx >= outer_map.max_elem &&
1544*de1e4e89SAndroid Build Coastguard Worker 		    outer_map.type == BPF_MAP_TYPE_ARRAY_OF_MAPS) {
1545*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Outer map has %u elements, index %u is invalid!\n",
1546*de1e4e89SAndroid Build Coastguard Worker 				outer_map.max_elem, idx);
1547*de1e4e89SAndroid Build Coastguard Worker 			return;
1548*de1e4e89SAndroid Build Coastguard Worker 		}
1549*de1e4e89SAndroid Build Coastguard Worker 	}
1550*de1e4e89SAndroid Build Coastguard Worker 
1551*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Different map specs used for outer and inner map?\n");
1552*de1e4e89SAndroid Build Coastguard Worker }
1553*de1e4e89SAndroid Build Coastguard Worker 
bpf_is_map_in_map_type(const struct bpf_elf_map * map)1554*de1e4e89SAndroid Build Coastguard Worker static bool bpf_is_map_in_map_type(const struct bpf_elf_map *map)
1555*de1e4e89SAndroid Build Coastguard Worker {
1556*de1e4e89SAndroid Build Coastguard Worker 	return map->type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
1557*de1e4e89SAndroid Build Coastguard Worker 	       map->type == BPF_MAP_TYPE_HASH_OF_MAPS;
1558*de1e4e89SAndroid Build Coastguard Worker }
1559*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_attach(const char * name,struct bpf_elf_ctx * ctx,const struct bpf_elf_map * map,struct bpf_map_ext * ext,int * have_map_in_map)1560*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_attach(const char *name, struct bpf_elf_ctx *ctx,
1561*de1e4e89SAndroid Build Coastguard Worker 			  const struct bpf_elf_map *map, struct bpf_map_ext *ext,
1562*de1e4e89SAndroid Build Coastguard Worker 			  int *have_map_in_map)
1563*de1e4e89SAndroid Build Coastguard Worker {
1564*de1e4e89SAndroid Build Coastguard Worker 	int fd, ret, map_inner_fd = 0;
1565*de1e4e89SAndroid Build Coastguard Worker 
1566*de1e4e89SAndroid Build Coastguard Worker 	fd = bpf_probe_pinned(name, ctx, map->pinning);
1567*de1e4e89SAndroid Build Coastguard Worker 	if (fd > 0) {
1568*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_map_selfcheck_pinned(fd, map, ext,
1569*de1e4e89SAndroid Build Coastguard Worker 					       offsetof(struct bpf_elf_map,
1570*de1e4e89SAndroid Build Coastguard Worker 							id), ctx->type);
1571*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
1572*de1e4e89SAndroid Build Coastguard Worker 			close(fd);
1573*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Map \'%s\' self-check failed!\n",
1574*de1e4e89SAndroid Build Coastguard Worker 				name);
1575*de1e4e89SAndroid Build Coastguard Worker 			return ret;
1576*de1e4e89SAndroid Build Coastguard Worker 		}
1577*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->verbose)
1578*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Map \'%s\' loaded as pinned!\n",
1579*de1e4e89SAndroid Build Coastguard Worker 				name);
1580*de1e4e89SAndroid Build Coastguard Worker 		return fd;
1581*de1e4e89SAndroid Build Coastguard Worker 	}
1582*de1e4e89SAndroid Build Coastguard Worker 
1583*de1e4e89SAndroid Build Coastguard Worker 	if (have_map_in_map && bpf_is_map_in_map_type(map)) {
1584*de1e4e89SAndroid Build Coastguard Worker 		(*have_map_in_map)++;
1585*de1e4e89SAndroid Build Coastguard Worker 		if (map->inner_id)
1586*de1e4e89SAndroid Build Coastguard Worker 			return 0;
1587*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Map \'%s\' cannot be created since no inner map ID defined!\n",
1588*de1e4e89SAndroid Build Coastguard Worker 			name);
1589*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1590*de1e4e89SAndroid Build Coastguard Worker 	}
1591*de1e4e89SAndroid Build Coastguard Worker 
1592*de1e4e89SAndroid Build Coastguard Worker 	if (!have_map_in_map && bpf_is_map_in_map_type(map)) {
1593*de1e4e89SAndroid Build Coastguard Worker 		map_inner_fd = bpf_find_map_id(ctx, map->inner_id);
1594*de1e4e89SAndroid Build Coastguard Worker 		if (map_inner_fd < 0) {
1595*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Map \'%s\' cannot be loaded. Inner map with ID %u not found!\n",
1596*de1e4e89SAndroid Build Coastguard Worker 				name, map->inner_id);
1597*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
1598*de1e4e89SAndroid Build Coastguard Worker 		}
1599*de1e4e89SAndroid Build Coastguard Worker 	}
1600*de1e4e89SAndroid Build Coastguard Worker 
1601*de1e4e89SAndroid Build Coastguard Worker 	errno = 0;
1602*de1e4e89SAndroid Build Coastguard Worker 	fd = bpf_map_create(map->type, map->size_key, map->size_value,
1603*de1e4e89SAndroid Build Coastguard Worker 			    map->max_elem, map->flags, map_inner_fd);
1604*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0 || ctx->verbose) {
1605*de1e4e89SAndroid Build Coastguard Worker 		bpf_map_report(fd, name, map, ctx, map_inner_fd);
1606*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0)
1607*de1e4e89SAndroid Build Coastguard Worker 			return fd;
1608*de1e4e89SAndroid Build Coastguard Worker 	}
1609*de1e4e89SAndroid Build Coastguard Worker 
1610*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_place_pinned(fd, name, ctx, map->pinning);
1611*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0 && errno != EEXIST) {
1612*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Could not pin %s map: %s\n", name,
1613*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
1614*de1e4e89SAndroid Build Coastguard Worker 		close(fd);
1615*de1e4e89SAndroid Build Coastguard Worker 		return ret;
1616*de1e4e89SAndroid Build Coastguard Worker 	}
1617*de1e4e89SAndroid Build Coastguard Worker 
1618*de1e4e89SAndroid Build Coastguard Worker 	return fd;
1619*de1e4e89SAndroid Build Coastguard Worker }
1620*de1e4e89SAndroid Build Coastguard Worker 
bpf_str_tab_name(const struct bpf_elf_ctx * ctx,const GElf_Sym * sym)1621*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx,
1622*de1e4e89SAndroid Build Coastguard Worker 				    const GElf_Sym *sym)
1623*de1e4e89SAndroid Build Coastguard Worker {
1624*de1e4e89SAndroid Build Coastguard Worker 	return ctx->str_tab->d_buf + sym->st_name;
1625*de1e4e89SAndroid Build Coastguard Worker }
1626*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_fetch_name(struct bpf_elf_ctx * ctx,int which)1627*de1e4e89SAndroid Build Coastguard Worker static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which)
1628*de1e4e89SAndroid Build Coastguard Worker {
1629*de1e4e89SAndroid Build Coastguard Worker 	GElf_Sym sym;
1630*de1e4e89SAndroid Build Coastguard Worker 	int i;
1631*de1e4e89SAndroid Build Coastguard Worker 
1632*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ctx->sym_num; i++) {
1633*de1e4e89SAndroid Build Coastguard Worker 		if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
1634*de1e4e89SAndroid Build Coastguard Worker 			continue;
1635*de1e4e89SAndroid Build Coastguard Worker 
1636*de1e4e89SAndroid Build Coastguard Worker 		if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
1637*de1e4e89SAndroid Build Coastguard Worker 		    GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
1638*de1e4e89SAndroid Build Coastguard Worker 		    sym.st_shndx != ctx->sec_maps ||
1639*de1e4e89SAndroid Build Coastguard Worker 		    sym.st_value / ctx->map_len != which)
1640*de1e4e89SAndroid Build Coastguard Worker 			continue;
1641*de1e4e89SAndroid Build Coastguard Worker 
1642*de1e4e89SAndroid Build Coastguard Worker 		return bpf_str_tab_name(ctx, &sym);
1643*de1e4e89SAndroid Build Coastguard Worker 	}
1644*de1e4e89SAndroid Build Coastguard Worker 
1645*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
1646*de1e4e89SAndroid Build Coastguard Worker }
1647*de1e4e89SAndroid Build Coastguard Worker 
bpf_maps_attach_all(struct bpf_elf_ctx * ctx)1648*de1e4e89SAndroid Build Coastguard Worker static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx)
1649*de1e4e89SAndroid Build Coastguard Worker {
1650*de1e4e89SAndroid Build Coastguard Worker 	int i, j, ret, fd, inner_fd, inner_idx, have_map_in_map = 0;
1651*de1e4e89SAndroid Build Coastguard Worker 	const char *map_name;
1652*de1e4e89SAndroid Build Coastguard Worker 
1653*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ctx->map_num; i++) {
1654*de1e4e89SAndroid Build Coastguard Worker 		map_name = bpf_map_fetch_name(ctx, i);
1655*de1e4e89SAndroid Build Coastguard Worker 		if (!map_name)
1656*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
1657*de1e4e89SAndroid Build Coastguard Worker 
1658*de1e4e89SAndroid Build Coastguard Worker 		fd = bpf_map_attach(map_name, ctx, &ctx->maps[i],
1659*de1e4e89SAndroid Build Coastguard Worker 				    &ctx->maps_ext[i], &have_map_in_map);
1660*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0)
1661*de1e4e89SAndroid Build Coastguard Worker 			return fd;
1662*de1e4e89SAndroid Build Coastguard Worker 
1663*de1e4e89SAndroid Build Coastguard Worker 		ctx->map_fds[i] = !fd ? -1 : fd;
1664*de1e4e89SAndroid Build Coastguard Worker 	}
1665*de1e4e89SAndroid Build Coastguard Worker 
1666*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; have_map_in_map && i < ctx->map_num; i++) {
1667*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->map_fds[i] >= 0)
1668*de1e4e89SAndroid Build Coastguard Worker 			continue;
1669*de1e4e89SAndroid Build Coastguard Worker 
1670*de1e4e89SAndroid Build Coastguard Worker 		map_name = bpf_map_fetch_name(ctx, i);
1671*de1e4e89SAndroid Build Coastguard Worker 		if (!map_name)
1672*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
1673*de1e4e89SAndroid Build Coastguard Worker 
1674*de1e4e89SAndroid Build Coastguard Worker 		fd = bpf_map_attach(map_name, ctx, &ctx->maps[i],
1675*de1e4e89SAndroid Build Coastguard Worker 				    &ctx->maps_ext[i], NULL);
1676*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0)
1677*de1e4e89SAndroid Build Coastguard Worker 			return fd;
1678*de1e4e89SAndroid Build Coastguard Worker 
1679*de1e4e89SAndroid Build Coastguard Worker 		ctx->map_fds[i] = fd;
1680*de1e4e89SAndroid Build Coastguard Worker 	}
1681*de1e4e89SAndroid Build Coastguard Worker 
1682*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; have_map_in_map && i < ctx->map_num; i++) {
1683*de1e4e89SAndroid Build Coastguard Worker 		if (!ctx->maps[i].id ||
1684*de1e4e89SAndroid Build Coastguard Worker 		    ctx->maps[i].inner_id ||
1685*de1e4e89SAndroid Build Coastguard Worker 		    ctx->maps[i].inner_idx == -1)
1686*de1e4e89SAndroid Build Coastguard Worker 			continue;
1687*de1e4e89SAndroid Build Coastguard Worker 
1688*de1e4e89SAndroid Build Coastguard Worker 		inner_fd  = ctx->map_fds[i];
1689*de1e4e89SAndroid Build Coastguard Worker 		inner_idx = ctx->maps[i].inner_idx;
1690*de1e4e89SAndroid Build Coastguard Worker 
1691*de1e4e89SAndroid Build Coastguard Worker 		for (j = 0; j < ctx->map_num; j++) {
1692*de1e4e89SAndroid Build Coastguard Worker 			if (!bpf_is_map_in_map_type(&ctx->maps[j]))
1693*de1e4e89SAndroid Build Coastguard Worker 				continue;
1694*de1e4e89SAndroid Build Coastguard Worker 			if (ctx->maps[j].inner_id != ctx->maps[i].id)
1695*de1e4e89SAndroid Build Coastguard Worker 				continue;
1696*de1e4e89SAndroid Build Coastguard Worker 
1697*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_map_update(ctx->map_fds[j], &inner_idx,
1698*de1e4e89SAndroid Build Coastguard Worker 					     &inner_fd, BPF_ANY);
1699*de1e4e89SAndroid Build Coastguard Worker 			if (ret < 0) {
1700*de1e4e89SAndroid Build Coastguard Worker 				bpf_report_map_in_map(ctx->map_fds[j],
1701*de1e4e89SAndroid Build Coastguard Worker 						      inner_idx);
1702*de1e4e89SAndroid Build Coastguard Worker 				return ret;
1703*de1e4e89SAndroid Build Coastguard Worker 			}
1704*de1e4e89SAndroid Build Coastguard Worker 		}
1705*de1e4e89SAndroid Build Coastguard Worker 	}
1706*de1e4e89SAndroid Build Coastguard Worker 
1707*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1708*de1e4e89SAndroid Build Coastguard Worker }
1709*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_num_sym(struct bpf_elf_ctx * ctx)1710*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_num_sym(struct bpf_elf_ctx *ctx)
1711*de1e4e89SAndroid Build Coastguard Worker {
1712*de1e4e89SAndroid Build Coastguard Worker 	int i, num = 0;
1713*de1e4e89SAndroid Build Coastguard Worker 	GElf_Sym sym;
1714*de1e4e89SAndroid Build Coastguard Worker 
1715*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ctx->sym_num; i++) {
1716*de1e4e89SAndroid Build Coastguard Worker 		if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
1717*de1e4e89SAndroid Build Coastguard Worker 			continue;
1718*de1e4e89SAndroid Build Coastguard Worker 
1719*de1e4e89SAndroid Build Coastguard Worker 		if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
1720*de1e4e89SAndroid Build Coastguard Worker 		    GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
1721*de1e4e89SAndroid Build Coastguard Worker 		    sym.st_shndx != ctx->sec_maps)
1722*de1e4e89SAndroid Build Coastguard Worker 			continue;
1723*de1e4e89SAndroid Build Coastguard Worker 		num++;
1724*de1e4e89SAndroid Build Coastguard Worker 	}
1725*de1e4e89SAndroid Build Coastguard Worker 
1726*de1e4e89SAndroid Build Coastguard Worker 	return num;
1727*de1e4e89SAndroid Build Coastguard Worker }
1728*de1e4e89SAndroid Build Coastguard Worker 
bpf_fill_section_data(struct bpf_elf_ctx * ctx,int section,struct bpf_elf_sec_data * data)1729*de1e4e89SAndroid Build Coastguard Worker static int bpf_fill_section_data(struct bpf_elf_ctx *ctx, int section,
1730*de1e4e89SAndroid Build Coastguard Worker 				 struct bpf_elf_sec_data *data)
1731*de1e4e89SAndroid Build Coastguard Worker {
1732*de1e4e89SAndroid Build Coastguard Worker 	Elf_Data *sec_edata;
1733*de1e4e89SAndroid Build Coastguard Worker 	GElf_Shdr sec_hdr;
1734*de1e4e89SAndroid Build Coastguard Worker 	Elf_Scn *sec_fd;
1735*de1e4e89SAndroid Build Coastguard Worker 	char *sec_name;
1736*de1e4e89SAndroid Build Coastguard Worker 
1737*de1e4e89SAndroid Build Coastguard Worker 	memset(data, 0, sizeof(*data));
1738*de1e4e89SAndroid Build Coastguard Worker 
1739*de1e4e89SAndroid Build Coastguard Worker 	sec_fd = elf_getscn(ctx->elf_fd, section);
1740*de1e4e89SAndroid Build Coastguard Worker 	if (!sec_fd)
1741*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1742*de1e4e89SAndroid Build Coastguard Worker 	if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr)
1743*de1e4e89SAndroid Build Coastguard Worker 		return -EIO;
1744*de1e4e89SAndroid Build Coastguard Worker 
1745*de1e4e89SAndroid Build Coastguard Worker 	sec_name = elf_strptr(ctx->elf_fd, ctx->elf_hdr.e_shstrndx,
1746*de1e4e89SAndroid Build Coastguard Worker 			      sec_hdr.sh_name);
1747*de1e4e89SAndroid Build Coastguard Worker 	if (!sec_name || !sec_hdr.sh_size)
1748*de1e4e89SAndroid Build Coastguard Worker 		return -ENOENT;
1749*de1e4e89SAndroid Build Coastguard Worker 
1750*de1e4e89SAndroid Build Coastguard Worker 	sec_edata = elf_getdata(sec_fd, NULL);
1751*de1e4e89SAndroid Build Coastguard Worker 	if (!sec_edata || elf_getdata(sec_fd, sec_edata))
1752*de1e4e89SAndroid Build Coastguard Worker 		return -EIO;
1753*de1e4e89SAndroid Build Coastguard Worker 
1754*de1e4e89SAndroid Build Coastguard Worker 	memcpy(&data->sec_hdr, &sec_hdr, sizeof(sec_hdr));
1755*de1e4e89SAndroid Build Coastguard Worker 
1756*de1e4e89SAndroid Build Coastguard Worker 	data->sec_name = sec_name;
1757*de1e4e89SAndroid Build Coastguard Worker 	data->sec_data = sec_edata;
1758*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1759*de1e4e89SAndroid Build Coastguard Worker }
1760*de1e4e89SAndroid Build Coastguard Worker 
1761*de1e4e89SAndroid Build Coastguard Worker struct bpf_elf_map_min {
1762*de1e4e89SAndroid Build Coastguard Worker 	__u32 type;
1763*de1e4e89SAndroid Build Coastguard Worker 	__u32 size_key;
1764*de1e4e89SAndroid Build Coastguard Worker 	__u32 size_value;
1765*de1e4e89SAndroid Build Coastguard Worker 	__u32 max_elem;
1766*de1e4e89SAndroid Build Coastguard Worker };
1767*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_maps_begin(struct bpf_elf_ctx * ctx,int section,struct bpf_elf_sec_data * data)1768*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_maps_begin(struct bpf_elf_ctx *ctx, int section,
1769*de1e4e89SAndroid Build Coastguard Worker 				struct bpf_elf_sec_data *data)
1770*de1e4e89SAndroid Build Coastguard Worker {
1771*de1e4e89SAndroid Build Coastguard Worker 	ctx->map_num = data->sec_data->d_size;
1772*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_maps = section;
1773*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_done[section] = true;
1774*de1e4e89SAndroid Build Coastguard Worker 
1775*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->map_num > sizeof(ctx->maps)) {
1776*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Too many BPF maps in ELF section!\n");
1777*de1e4e89SAndroid Build Coastguard Worker 		return -ENOMEM;
1778*de1e4e89SAndroid Build Coastguard Worker 	}
1779*de1e4e89SAndroid Build Coastguard Worker 
1780*de1e4e89SAndroid Build Coastguard Worker 	memcpy(ctx->maps, data->sec_data->d_buf, ctx->map_num);
1781*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1782*de1e4e89SAndroid Build Coastguard Worker }
1783*de1e4e89SAndroid Build Coastguard Worker 
bpf_map_verify_all_offs(struct bpf_elf_ctx * ctx,int end)1784*de1e4e89SAndroid Build Coastguard Worker static int bpf_map_verify_all_offs(struct bpf_elf_ctx *ctx, int end)
1785*de1e4e89SAndroid Build Coastguard Worker {
1786*de1e4e89SAndroid Build Coastguard Worker 	GElf_Sym sym;
1787*de1e4e89SAndroid Build Coastguard Worker 	int off, i;
1788*de1e4e89SAndroid Build Coastguard Worker 
1789*de1e4e89SAndroid Build Coastguard Worker 	for (off = 0; off < end; off += ctx->map_len) {
1790*de1e4e89SAndroid Build Coastguard Worker 		/* Order doesn't need to be linear here, hence we walk
1791*de1e4e89SAndroid Build Coastguard Worker 		 * the table again.
1792*de1e4e89SAndroid Build Coastguard Worker 		 */
1793*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < ctx->sym_num; i++) {
1794*de1e4e89SAndroid Build Coastguard Worker 			if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
1795*de1e4e89SAndroid Build Coastguard Worker 				continue;
1796*de1e4e89SAndroid Build Coastguard Worker 			if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
1797*de1e4e89SAndroid Build Coastguard Worker 			    GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
1798*de1e4e89SAndroid Build Coastguard Worker 			    sym.st_shndx != ctx->sec_maps)
1799*de1e4e89SAndroid Build Coastguard Worker 				continue;
1800*de1e4e89SAndroid Build Coastguard Worker 			if (sym.st_value == off)
1801*de1e4e89SAndroid Build Coastguard Worker 				break;
1802*de1e4e89SAndroid Build Coastguard Worker 			if (i == ctx->sym_num - 1)
1803*de1e4e89SAndroid Build Coastguard Worker 				return -1;
1804*de1e4e89SAndroid Build Coastguard Worker 		}
1805*de1e4e89SAndroid Build Coastguard Worker 	}
1806*de1e4e89SAndroid Build Coastguard Worker 
1807*de1e4e89SAndroid Build Coastguard Worker 	return off == end ? 0 : -1;
1808*de1e4e89SAndroid Build Coastguard Worker }
1809*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_maps_end(struct bpf_elf_ctx * ctx)1810*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_maps_end(struct bpf_elf_ctx *ctx)
1811*de1e4e89SAndroid Build Coastguard Worker {
1812*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map fixup[ARRAY_SIZE(ctx->maps)] = {};
1813*de1e4e89SAndroid Build Coastguard Worker 	int i, sym_num = bpf_map_num_sym(ctx);
1814*de1e4e89SAndroid Build Coastguard Worker 	__u8 *buff;
1815*de1e4e89SAndroid Build Coastguard Worker 
1816*de1e4e89SAndroid Build Coastguard Worker 	if (sym_num == 0 || sym_num > ARRAY_SIZE(ctx->maps)) {
1817*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "%u maps not supported in current map section!\n",
1818*de1e4e89SAndroid Build Coastguard Worker 			sym_num);
1819*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1820*de1e4e89SAndroid Build Coastguard Worker 	}
1821*de1e4e89SAndroid Build Coastguard Worker 
1822*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->map_num % sym_num != 0 ||
1823*de1e4e89SAndroid Build Coastguard Worker 	    ctx->map_num % sizeof(__u32) != 0) {
1824*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Number BPF map symbols are not multiple of struct bpf_elf_map!\n");
1825*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1826*de1e4e89SAndroid Build Coastguard Worker 	}
1827*de1e4e89SAndroid Build Coastguard Worker 
1828*de1e4e89SAndroid Build Coastguard Worker 	ctx->map_len = ctx->map_num / sym_num;
1829*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_map_verify_all_offs(ctx, ctx->map_num)) {
1830*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Different struct bpf_elf_map in use!\n");
1831*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1832*de1e4e89SAndroid Build Coastguard Worker 	}
1833*de1e4e89SAndroid Build Coastguard Worker 
1834*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->map_len == sizeof(struct bpf_elf_map)) {
1835*de1e4e89SAndroid Build Coastguard Worker 		ctx->map_num = sym_num;
1836*de1e4e89SAndroid Build Coastguard Worker 		return 0;
1837*de1e4e89SAndroid Build Coastguard Worker 	} else if (ctx->map_len > sizeof(struct bpf_elf_map)) {
1838*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "struct bpf_elf_map not supported, coming from future version?\n");
1839*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1840*de1e4e89SAndroid Build Coastguard Worker 	} else if (ctx->map_len < sizeof(struct bpf_elf_map_min)) {
1841*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "struct bpf_elf_map too small, not supported!\n");
1842*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
1843*de1e4e89SAndroid Build Coastguard Worker 	}
1844*de1e4e89SAndroid Build Coastguard Worker 
1845*de1e4e89SAndroid Build Coastguard Worker 	ctx->map_num = sym_num;
1846*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0, buff = (void *)ctx->maps; i < ctx->map_num;
1847*de1e4e89SAndroid Build Coastguard Worker 	     i++, buff += ctx->map_len) {
1848*de1e4e89SAndroid Build Coastguard Worker 		/* The fixup leaves the rest of the members as zero, which
1849*de1e4e89SAndroid Build Coastguard Worker 		 * is fine currently, but option exist to set some other
1850*de1e4e89SAndroid Build Coastguard Worker 		 * default value as well when needed in future.
1851*de1e4e89SAndroid Build Coastguard Worker 		 */
1852*de1e4e89SAndroid Build Coastguard Worker 		memcpy(&fixup[i], buff, ctx->map_len);
1853*de1e4e89SAndroid Build Coastguard Worker 	}
1854*de1e4e89SAndroid Build Coastguard Worker 
1855*de1e4e89SAndroid Build Coastguard Worker 	memcpy(ctx->maps, fixup, sizeof(fixup));
1856*de1e4e89SAndroid Build Coastguard Worker 
1857*de1e4e89SAndroid Build Coastguard Worker 	printf("Note: %zu bytes struct bpf_elf_map fixup performed due to size mismatch!\n",
1858*de1e4e89SAndroid Build Coastguard Worker 	       sizeof(struct bpf_elf_map) - ctx->map_len);
1859*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1860*de1e4e89SAndroid Build Coastguard Worker }
1861*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_license(struct bpf_elf_ctx * ctx,int section,struct bpf_elf_sec_data * data)1862*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_license(struct bpf_elf_ctx *ctx, int section,
1863*de1e4e89SAndroid Build Coastguard Worker 			     struct bpf_elf_sec_data *data)
1864*de1e4e89SAndroid Build Coastguard Worker {
1865*de1e4e89SAndroid Build Coastguard Worker 	if (data->sec_data->d_size > sizeof(ctx->license))
1866*de1e4e89SAndroid Build Coastguard Worker 		return -ENOMEM;
1867*de1e4e89SAndroid Build Coastguard Worker 
1868*de1e4e89SAndroid Build Coastguard Worker 	memcpy(ctx->license, data->sec_data->d_buf, data->sec_data->d_size);
1869*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_done[section] = true;
1870*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1871*de1e4e89SAndroid Build Coastguard Worker }
1872*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_symtab(struct bpf_elf_ctx * ctx,int section,struct bpf_elf_sec_data * data)1873*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_symtab(struct bpf_elf_ctx *ctx, int section,
1874*de1e4e89SAndroid Build Coastguard Worker 			    struct bpf_elf_sec_data *data)
1875*de1e4e89SAndroid Build Coastguard Worker {
1876*de1e4e89SAndroid Build Coastguard Worker 	ctx->sym_tab = data->sec_data;
1877*de1e4e89SAndroid Build Coastguard Worker 	ctx->sym_num = data->sec_hdr.sh_size / data->sec_hdr.sh_entsize;
1878*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_done[section] = true;
1879*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1880*de1e4e89SAndroid Build Coastguard Worker }
1881*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_strtab(struct bpf_elf_ctx * ctx,int section,struct bpf_elf_sec_data * data)1882*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section,
1883*de1e4e89SAndroid Build Coastguard Worker 			    struct bpf_elf_sec_data *data)
1884*de1e4e89SAndroid Build Coastguard Worker {
1885*de1e4e89SAndroid Build Coastguard Worker 	ctx->str_tab = data->sec_data;
1886*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_done[section] = true;
1887*de1e4e89SAndroid Build Coastguard Worker 	return 0;
1888*de1e4e89SAndroid Build Coastguard Worker }
1889*de1e4e89SAndroid Build Coastguard Worker 
bpf_has_map_data(const struct bpf_elf_ctx * ctx)1890*de1e4e89SAndroid Build Coastguard Worker static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx)
1891*de1e4e89SAndroid Build Coastguard Worker {
1892*de1e4e89SAndroid Build Coastguard Worker 	return ctx->sym_tab && ctx->str_tab && ctx->sec_maps;
1893*de1e4e89SAndroid Build Coastguard Worker }
1894*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_ancillary(struct bpf_elf_ctx * ctx)1895*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
1896*de1e4e89SAndroid Build Coastguard Worker {
1897*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_sec_data data;
1898*de1e4e89SAndroid Build Coastguard Worker 	int i, ret = -1;
1899*de1e4e89SAndroid Build Coastguard Worker 
1900*de1e4e89SAndroid Build Coastguard Worker 	for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1901*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fill_section_data(ctx, i, &data);
1902*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0)
1903*de1e4e89SAndroid Build Coastguard Worker 			continue;
1904*de1e4e89SAndroid Build Coastguard Worker 
1905*de1e4e89SAndroid Build Coastguard Worker 		if (data.sec_hdr.sh_type == SHT_PROGBITS &&
1906*de1e4e89SAndroid Build Coastguard Worker 		    !strcmp(data.sec_name, ELF_SECTION_MAPS))
1907*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_fetch_maps_begin(ctx, i, &data);
1908*de1e4e89SAndroid Build Coastguard Worker 		else if (data.sec_hdr.sh_type == SHT_PROGBITS &&
1909*de1e4e89SAndroid Build Coastguard Worker 			 !strcmp(data.sec_name, ELF_SECTION_LICENSE))
1910*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_fetch_license(ctx, i, &data);
1911*de1e4e89SAndroid Build Coastguard Worker 		else if (data.sec_hdr.sh_type == SHT_SYMTAB &&
1912*de1e4e89SAndroid Build Coastguard Worker 			 !strcmp(data.sec_name, ".symtab"))
1913*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_fetch_symtab(ctx, i, &data);
1914*de1e4e89SAndroid Build Coastguard Worker 		else if (data.sec_hdr.sh_type == SHT_STRTAB &&
1915*de1e4e89SAndroid Build Coastguard Worker 			 !strcmp(data.sec_name, ".strtab"))
1916*de1e4e89SAndroid Build Coastguard Worker 			ret = bpf_fetch_strtab(ctx, i, &data);
1917*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
1918*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Error parsing section %d! Perhaps check with readelf -a?\n",
1919*de1e4e89SAndroid Build Coastguard Worker 				i);
1920*de1e4e89SAndroid Build Coastguard Worker 			return ret;
1921*de1e4e89SAndroid Build Coastguard Worker 		}
1922*de1e4e89SAndroid Build Coastguard Worker 	}
1923*de1e4e89SAndroid Build Coastguard Worker 
1924*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_has_map_data(ctx)) {
1925*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fetch_maps_end(ctx);
1926*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
1927*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Error fixing up map structure, incompatible struct bpf_elf_map used?\n");
1928*de1e4e89SAndroid Build Coastguard Worker 			return ret;
1929*de1e4e89SAndroid Build Coastguard Worker 		}
1930*de1e4e89SAndroid Build Coastguard Worker 
1931*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_maps_attach_all(ctx);
1932*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
1933*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Error loading maps into kernel!\n");
1934*de1e4e89SAndroid Build Coastguard Worker 			return ret;
1935*de1e4e89SAndroid Build Coastguard Worker 		}
1936*de1e4e89SAndroid Build Coastguard Worker 	}
1937*de1e4e89SAndroid Build Coastguard Worker 
1938*de1e4e89SAndroid Build Coastguard Worker 	return ret;
1939*de1e4e89SAndroid Build Coastguard Worker }
1940*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_prog(struct bpf_elf_ctx * ctx,const char * section,bool * sseen)1941*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section,
1942*de1e4e89SAndroid Build Coastguard Worker 			  bool *sseen)
1943*de1e4e89SAndroid Build Coastguard Worker {
1944*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_sec_data data;
1945*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_prog prog;
1946*de1e4e89SAndroid Build Coastguard Worker 	int ret, i, fd = -1;
1947*de1e4e89SAndroid Build Coastguard Worker 
1948*de1e4e89SAndroid Build Coastguard Worker 	for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1949*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->sec_done[i])
1950*de1e4e89SAndroid Build Coastguard Worker 			continue;
1951*de1e4e89SAndroid Build Coastguard Worker 
1952*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fill_section_data(ctx, i, &data);
1953*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0 ||
1954*de1e4e89SAndroid Build Coastguard Worker 		    !(data.sec_hdr.sh_type == SHT_PROGBITS &&
1955*de1e4e89SAndroid Build Coastguard Worker 		      data.sec_hdr.sh_flags & SHF_EXECINSTR &&
1956*de1e4e89SAndroid Build Coastguard Worker 		      !strcmp(data.sec_name, section)))
1957*de1e4e89SAndroid Build Coastguard Worker 			continue;
1958*de1e4e89SAndroid Build Coastguard Worker 
1959*de1e4e89SAndroid Build Coastguard Worker 		*sseen = true;
1960*de1e4e89SAndroid Build Coastguard Worker 
1961*de1e4e89SAndroid Build Coastguard Worker 		memset(&prog, 0, sizeof(prog));
1962*de1e4e89SAndroid Build Coastguard Worker 		prog.type    = ctx->type;
1963*de1e4e89SAndroid Build Coastguard Worker 		prog.insns   = data.sec_data->d_buf;
1964*de1e4e89SAndroid Build Coastguard Worker 		prog.size    = data.sec_data->d_size;
1965*de1e4e89SAndroid Build Coastguard Worker 		prog.license = ctx->license;
1966*de1e4e89SAndroid Build Coastguard Worker 
1967*de1e4e89SAndroid Build Coastguard Worker 		fd = bpf_prog_attach(section, &prog, ctx);
1968*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0)
1969*de1e4e89SAndroid Build Coastguard Worker 			return fd;
1970*de1e4e89SAndroid Build Coastguard Worker 
1971*de1e4e89SAndroid Build Coastguard Worker 		ctx->sec_done[i] = true;
1972*de1e4e89SAndroid Build Coastguard Worker 		break;
1973*de1e4e89SAndroid Build Coastguard Worker 	}
1974*de1e4e89SAndroid Build Coastguard Worker 
1975*de1e4e89SAndroid Build Coastguard Worker 	return fd;
1976*de1e4e89SAndroid Build Coastguard Worker }
1977*de1e4e89SAndroid Build Coastguard Worker 
1978*de1e4e89SAndroid Build Coastguard Worker struct bpf_tail_call_props {
1979*de1e4e89SAndroid Build Coastguard Worker 	unsigned int total;
1980*de1e4e89SAndroid Build Coastguard Worker 	unsigned int jited;
1981*de1e4e89SAndroid Build Coastguard Worker };
1982*de1e4e89SAndroid Build Coastguard Worker 
bpf_apply_relo_data(struct bpf_elf_ctx * ctx,struct bpf_elf_sec_data * data_relo,struct bpf_elf_sec_data * data_insn,struct bpf_tail_call_props * props)1983*de1e4e89SAndroid Build Coastguard Worker static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
1984*de1e4e89SAndroid Build Coastguard Worker 			       struct bpf_elf_sec_data *data_relo,
1985*de1e4e89SAndroid Build Coastguard Worker 			       struct bpf_elf_sec_data *data_insn,
1986*de1e4e89SAndroid Build Coastguard Worker 			       struct bpf_tail_call_props *props)
1987*de1e4e89SAndroid Build Coastguard Worker {
1988*de1e4e89SAndroid Build Coastguard Worker 	Elf_Data *idata = data_insn->sec_data;
1989*de1e4e89SAndroid Build Coastguard Worker 	GElf_Shdr *rhdr = &data_relo->sec_hdr;
1990*de1e4e89SAndroid Build Coastguard Worker 	int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize;
1991*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_insn *insns = idata->d_buf;
1992*de1e4e89SAndroid Build Coastguard Worker 	unsigned int num_insns = idata->d_size / sizeof(*insns);
1993*de1e4e89SAndroid Build Coastguard Worker 
1994*de1e4e89SAndroid Build Coastguard Worker 	for (relo_ent = 0; relo_ent < relo_num; relo_ent++) {
1995*de1e4e89SAndroid Build Coastguard Worker 		unsigned int ioff, rmap;
1996*de1e4e89SAndroid Build Coastguard Worker 		GElf_Rel relo;
1997*de1e4e89SAndroid Build Coastguard Worker 		GElf_Sym sym;
1998*de1e4e89SAndroid Build Coastguard Worker 
1999*de1e4e89SAndroid Build Coastguard Worker 		if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo)
2000*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2001*de1e4e89SAndroid Build Coastguard Worker 
2002*de1e4e89SAndroid Build Coastguard Worker 		ioff = relo.r_offset / sizeof(struct bpf_insn);
2003*de1e4e89SAndroid Build Coastguard Worker 		if (ioff >= num_insns ||
2004*de1e4e89SAndroid Build Coastguard Worker 		    insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) {
2005*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n",
2006*de1e4e89SAndroid Build Coastguard Worker 				ioff);
2007*de1e4e89SAndroid Build Coastguard Worker 			if (ioff < num_insns &&
2008*de1e4e89SAndroid Build Coastguard Worker 			    insns[ioff].code == (BPF_JMP | BPF_CALL))
2009*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, " - Try to annotate functions with always_inline attribute!\n");
2010*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
2011*de1e4e89SAndroid Build Coastguard Worker 		}
2012*de1e4e89SAndroid Build Coastguard Worker 
2013*de1e4e89SAndroid Build Coastguard Worker 		if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym)
2014*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2015*de1e4e89SAndroid Build Coastguard Worker 		if (sym.st_shndx != ctx->sec_maps) {
2016*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "ELF contains non-map related relo data in entry %u pointing to section %u! Compiler bug?!\n",
2017*de1e4e89SAndroid Build Coastguard Worker 				relo_ent, sym.st_shndx);
2018*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2019*de1e4e89SAndroid Build Coastguard Worker 		}
2020*de1e4e89SAndroid Build Coastguard Worker 
2021*de1e4e89SAndroid Build Coastguard Worker 		rmap = sym.st_value / ctx->map_len;
2022*de1e4e89SAndroid Build Coastguard Worker 		if (rmap >= ARRAY_SIZE(ctx->map_fds))
2023*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
2024*de1e4e89SAndroid Build Coastguard Worker 		if (!ctx->map_fds[rmap])
2025*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
2026*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->maps[rmap].type == BPF_MAP_TYPE_PROG_ARRAY) {
2027*de1e4e89SAndroid Build Coastguard Worker 			props->total++;
2028*de1e4e89SAndroid Build Coastguard Worker 			if (ctx->maps_ext[rmap].owner.jited ||
2029*de1e4e89SAndroid Build Coastguard Worker 			    (ctx->maps_ext[rmap].owner.type == 0 &&
2030*de1e4e89SAndroid Build Coastguard Worker 			     ctx->cfg.jit_enabled))
2031*de1e4e89SAndroid Build Coastguard Worker 				props->jited++;
2032*de1e4e89SAndroid Build Coastguard Worker 		}
2033*de1e4e89SAndroid Build Coastguard Worker 
2034*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->verbose)
2035*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Map \'%s\' (%d) injected into prog section \'%s\' at offset %u!\n",
2036*de1e4e89SAndroid Build Coastguard Worker 				bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap],
2037*de1e4e89SAndroid Build Coastguard Worker 				data_insn->sec_name, ioff);
2038*de1e4e89SAndroid Build Coastguard Worker 
2039*de1e4e89SAndroid Build Coastguard Worker 		insns[ioff].src_reg = BPF_PSEUDO_MAP_FD;
2040*de1e4e89SAndroid Build Coastguard Worker 		insns[ioff].imm     = ctx->map_fds[rmap];
2041*de1e4e89SAndroid Build Coastguard Worker 	}
2042*de1e4e89SAndroid Build Coastguard Worker 
2043*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2044*de1e4e89SAndroid Build Coastguard Worker }
2045*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_prog_relo(struct bpf_elf_ctx * ctx,const char * section,bool * lderr,bool * sseen)2046*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
2047*de1e4e89SAndroid Build Coastguard Worker 			       bool *lderr, bool *sseen)
2048*de1e4e89SAndroid Build Coastguard Worker {
2049*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_sec_data data_relo, data_insn;
2050*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_prog prog;
2051*de1e4e89SAndroid Build Coastguard Worker 	int ret, idx, i, fd = -1;
2052*de1e4e89SAndroid Build Coastguard Worker 
2053*de1e4e89SAndroid Build Coastguard Worker 	for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
2054*de1e4e89SAndroid Build Coastguard Worker 		struct bpf_tail_call_props props = {};
2055*de1e4e89SAndroid Build Coastguard Worker 
2056*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fill_section_data(ctx, i, &data_relo);
2057*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL)
2058*de1e4e89SAndroid Build Coastguard Worker 			continue;
2059*de1e4e89SAndroid Build Coastguard Worker 
2060*de1e4e89SAndroid Build Coastguard Worker 		idx = data_relo.sec_hdr.sh_info;
2061*de1e4e89SAndroid Build Coastguard Worker 
2062*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fill_section_data(ctx, idx, &data_insn);
2063*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0 ||
2064*de1e4e89SAndroid Build Coastguard Worker 		    !(data_insn.sec_hdr.sh_type == SHT_PROGBITS &&
2065*de1e4e89SAndroid Build Coastguard Worker 		      data_insn.sec_hdr.sh_flags & SHF_EXECINSTR &&
2066*de1e4e89SAndroid Build Coastguard Worker 		      !strcmp(data_insn.sec_name, section)))
2067*de1e4e89SAndroid Build Coastguard Worker 			continue;
2068*de1e4e89SAndroid Build Coastguard Worker 
2069*de1e4e89SAndroid Build Coastguard Worker 		*sseen = true;
2070*de1e4e89SAndroid Build Coastguard Worker 
2071*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn, &props);
2072*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
2073*de1e4e89SAndroid Build Coastguard Worker 			*lderr = true;
2074*de1e4e89SAndroid Build Coastguard Worker 			return ret;
2075*de1e4e89SAndroid Build Coastguard Worker 		}
2076*de1e4e89SAndroid Build Coastguard Worker 
2077*de1e4e89SAndroid Build Coastguard Worker 		memset(&prog, 0, sizeof(prog));
2078*de1e4e89SAndroid Build Coastguard Worker 		prog.type    = ctx->type;
2079*de1e4e89SAndroid Build Coastguard Worker 		prog.insns   = data_insn.sec_data->d_buf;
2080*de1e4e89SAndroid Build Coastguard Worker 		prog.size    = data_insn.sec_data->d_size;
2081*de1e4e89SAndroid Build Coastguard Worker 		prog.license = ctx->license;
2082*de1e4e89SAndroid Build Coastguard Worker 
2083*de1e4e89SAndroid Build Coastguard Worker 		fd = bpf_prog_attach(section, &prog, ctx);
2084*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0) {
2085*de1e4e89SAndroid Build Coastguard Worker 			*lderr = true;
2086*de1e4e89SAndroid Build Coastguard Worker 			if (props.total) {
2087*de1e4e89SAndroid Build Coastguard Worker 				if (ctx->cfg.jit_enabled &&
2088*de1e4e89SAndroid Build Coastguard Worker 				    props.total != props.jited)
2089*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "JIT enabled, but only %u/%u tail call maps in the program have JITed owner!\n",
2090*de1e4e89SAndroid Build Coastguard Worker 						props.jited, props.total);
2091*de1e4e89SAndroid Build Coastguard Worker 				if (!ctx->cfg.jit_enabled &&
2092*de1e4e89SAndroid Build Coastguard Worker 				    props.jited)
2093*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "JIT disabled, but %u/%u tail call maps in the program have JITed owner!\n",
2094*de1e4e89SAndroid Build Coastguard Worker 						props.jited, props.total);
2095*de1e4e89SAndroid Build Coastguard Worker 			}
2096*de1e4e89SAndroid Build Coastguard Worker 			return fd;
2097*de1e4e89SAndroid Build Coastguard Worker 		}
2098*de1e4e89SAndroid Build Coastguard Worker 
2099*de1e4e89SAndroid Build Coastguard Worker 		ctx->sec_done[i]   = true;
2100*de1e4e89SAndroid Build Coastguard Worker 		ctx->sec_done[idx] = true;
2101*de1e4e89SAndroid Build Coastguard Worker 		break;
2102*de1e4e89SAndroid Build Coastguard Worker 	}
2103*de1e4e89SAndroid Build Coastguard Worker 
2104*de1e4e89SAndroid Build Coastguard Worker 	return fd;
2105*de1e4e89SAndroid Build Coastguard Worker }
2106*de1e4e89SAndroid Build Coastguard Worker 
bpf_fetch_prog_sec(struct bpf_elf_ctx * ctx,const char * section)2107*de1e4e89SAndroid Build Coastguard Worker static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section)
2108*de1e4e89SAndroid Build Coastguard Worker {
2109*de1e4e89SAndroid Build Coastguard Worker 	bool lderr = false, sseen = false;
2110*de1e4e89SAndroid Build Coastguard Worker 	int ret = -1;
2111*de1e4e89SAndroid Build Coastguard Worker 
2112*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_has_map_data(ctx))
2113*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen);
2114*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0 && !lderr)
2115*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fetch_prog(ctx, section, &sseen);
2116*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0 && !sseen)
2117*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Program section \'%s\' not found in ELF file!\n",
2118*de1e4e89SAndroid Build Coastguard Worker 			section);
2119*de1e4e89SAndroid Build Coastguard Worker 	return ret;
2120*de1e4e89SAndroid Build Coastguard Worker }
2121*de1e4e89SAndroid Build Coastguard Worker 
bpf_find_map_by_id(struct bpf_elf_ctx * ctx,uint32_t id)2122*de1e4e89SAndroid Build Coastguard Worker static int bpf_find_map_by_id(struct bpf_elf_ctx *ctx, uint32_t id)
2123*de1e4e89SAndroid Build Coastguard Worker {
2124*de1e4e89SAndroid Build Coastguard Worker 	int i;
2125*de1e4e89SAndroid Build Coastguard Worker 
2126*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++)
2127*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->map_fds[i] && ctx->maps[i].id == id &&
2128*de1e4e89SAndroid Build Coastguard Worker 		    ctx->maps[i].type == BPF_MAP_TYPE_PROG_ARRAY)
2129*de1e4e89SAndroid Build Coastguard Worker 			return i;
2130*de1e4e89SAndroid Build Coastguard Worker 	return -1;
2131*de1e4e89SAndroid Build Coastguard Worker }
2132*de1e4e89SAndroid Build Coastguard Worker 
2133*de1e4e89SAndroid Build Coastguard Worker struct bpf_jited_aux {
2134*de1e4e89SAndroid Build Coastguard Worker 	int prog_fd;
2135*de1e4e89SAndroid Build Coastguard Worker 	int map_fd;
2136*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_prog_data prog;
2137*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_ext map;
2138*de1e4e89SAndroid Build Coastguard Worker };
2139*de1e4e89SAndroid Build Coastguard Worker 
bpf_derive_prog_from_fdinfo(int fd,struct bpf_prog_data * prog)2140*de1e4e89SAndroid Build Coastguard Worker static int bpf_derive_prog_from_fdinfo(int fd, struct bpf_prog_data *prog)
2141*de1e4e89SAndroid Build Coastguard Worker {
2142*de1e4e89SAndroid Build Coastguard Worker 	char file[PATH_MAX], buff[4096];
2143*de1e4e89SAndroid Build Coastguard Worker 	unsigned int val;
2144*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp;
2145*de1e4e89SAndroid Build Coastguard Worker 
2146*de1e4e89SAndroid Build Coastguard Worker 	snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
2147*de1e4e89SAndroid Build Coastguard Worker 	memset(prog, 0, sizeof(*prog));
2148*de1e4e89SAndroid Build Coastguard Worker 
2149*de1e4e89SAndroid Build Coastguard Worker 	fp = fopen(file, "r");
2150*de1e4e89SAndroid Build Coastguard Worker 	if (!fp) {
2151*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "No procfs support?!\n");
2152*de1e4e89SAndroid Build Coastguard Worker 		return -EIO;
2153*de1e4e89SAndroid Build Coastguard Worker 	}
2154*de1e4e89SAndroid Build Coastguard Worker 
2155*de1e4e89SAndroid Build Coastguard Worker 	while (fgets(buff, sizeof(buff), fp)) {
2156*de1e4e89SAndroid Build Coastguard Worker 		if (sscanf(buff, "prog_type:\t%u", &val) == 1)
2157*de1e4e89SAndroid Build Coastguard Worker 			prog->type = val;
2158*de1e4e89SAndroid Build Coastguard Worker 		else if (sscanf(buff, "prog_jited:\t%u", &val) == 1)
2159*de1e4e89SAndroid Build Coastguard Worker 			prog->jited = val;
2160*de1e4e89SAndroid Build Coastguard Worker 	}
2161*de1e4e89SAndroid Build Coastguard Worker 
2162*de1e4e89SAndroid Build Coastguard Worker 	fclose(fp);
2163*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2164*de1e4e89SAndroid Build Coastguard Worker }
2165*de1e4e89SAndroid Build Coastguard Worker 
bpf_tail_call_get_aux(struct bpf_jited_aux * aux)2166*de1e4e89SAndroid Build Coastguard Worker static int bpf_tail_call_get_aux(struct bpf_jited_aux *aux)
2167*de1e4e89SAndroid Build Coastguard Worker {
2168*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_map tmp;
2169*de1e4e89SAndroid Build Coastguard Worker 	int ret;
2170*de1e4e89SAndroid Build Coastguard Worker 
2171*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_derive_elf_map_from_fdinfo(aux->map_fd, &tmp, &aux->map);
2172*de1e4e89SAndroid Build Coastguard Worker 	if (!ret)
2173*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_derive_prog_from_fdinfo(aux->prog_fd, &aux->prog);
2174*de1e4e89SAndroid Build Coastguard Worker 
2175*de1e4e89SAndroid Build Coastguard Worker 	return ret;
2176*de1e4e89SAndroid Build Coastguard Worker }
2177*de1e4e89SAndroid Build Coastguard Worker 
bpf_fill_prog_arrays(struct bpf_elf_ctx * ctx)2178*de1e4e89SAndroid Build Coastguard Worker static int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx)
2179*de1e4e89SAndroid Build Coastguard Worker {
2180*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_sec_data data;
2181*de1e4e89SAndroid Build Coastguard Worker 	uint32_t map_id, key_id;
2182*de1e4e89SAndroid Build Coastguard Worker 	int fd, i, ret, idx;
2183*de1e4e89SAndroid Build Coastguard Worker 
2184*de1e4e89SAndroid Build Coastguard Worker 	for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
2185*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->sec_done[i])
2186*de1e4e89SAndroid Build Coastguard Worker 			continue;
2187*de1e4e89SAndroid Build Coastguard Worker 
2188*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_fill_section_data(ctx, i, &data);
2189*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0)
2190*de1e4e89SAndroid Build Coastguard Worker 			continue;
2191*de1e4e89SAndroid Build Coastguard Worker 
2192*de1e4e89SAndroid Build Coastguard Worker 		ret = sscanf(data.sec_name, "%i/%i", &map_id, &key_id);
2193*de1e4e89SAndroid Build Coastguard Worker 		if (ret != 2)
2194*de1e4e89SAndroid Build Coastguard Worker 			continue;
2195*de1e4e89SAndroid Build Coastguard Worker 
2196*de1e4e89SAndroid Build Coastguard Worker 		idx = bpf_find_map_by_id(ctx, map_id);
2197*de1e4e89SAndroid Build Coastguard Worker 		if (idx < 0)
2198*de1e4e89SAndroid Build Coastguard Worker 			continue;
2199*de1e4e89SAndroid Build Coastguard Worker 
2200*de1e4e89SAndroid Build Coastguard Worker 		fd = bpf_fetch_prog_sec(ctx, data.sec_name);
2201*de1e4e89SAndroid Build Coastguard Worker 		if (fd < 0)
2202*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2203*de1e4e89SAndroid Build Coastguard Worker 
2204*de1e4e89SAndroid Build Coastguard Worker 		ret = bpf_map_update(ctx->map_fds[idx], &key_id,
2205*de1e4e89SAndroid Build Coastguard Worker 				     &fd, BPF_ANY);
2206*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0) {
2207*de1e4e89SAndroid Build Coastguard Worker 			struct bpf_jited_aux aux = {};
2208*de1e4e89SAndroid Build Coastguard Worker 
2209*de1e4e89SAndroid Build Coastguard Worker 			ret = -errno;
2210*de1e4e89SAndroid Build Coastguard Worker 			if (errno == E2BIG) {
2211*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Tail call key %u for map %u out of bounds?\n",
2212*de1e4e89SAndroid Build Coastguard Worker 					key_id, map_id);
2213*de1e4e89SAndroid Build Coastguard Worker 				return ret;
2214*de1e4e89SAndroid Build Coastguard Worker 			}
2215*de1e4e89SAndroid Build Coastguard Worker 
2216*de1e4e89SAndroid Build Coastguard Worker 			aux.map_fd  = ctx->map_fds[idx];
2217*de1e4e89SAndroid Build Coastguard Worker 			aux.prog_fd = fd;
2218*de1e4e89SAndroid Build Coastguard Worker 
2219*de1e4e89SAndroid Build Coastguard Worker 			if (bpf_tail_call_get_aux(&aux))
2220*de1e4e89SAndroid Build Coastguard Worker 				return ret;
2221*de1e4e89SAndroid Build Coastguard Worker 			if (!aux.map.owner.type)
2222*de1e4e89SAndroid Build Coastguard Worker 				return ret;
2223*de1e4e89SAndroid Build Coastguard Worker 
2224*de1e4e89SAndroid Build Coastguard Worker 			if (aux.prog.type != aux.map.owner.type)
2225*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Tail call map owned by prog type %u, but prog type is %u!\n",
2226*de1e4e89SAndroid Build Coastguard Worker 					aux.map.owner.type, aux.prog.type);
2227*de1e4e89SAndroid Build Coastguard Worker 			if (aux.prog.jited != aux.map.owner.jited)
2228*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Tail call map %s jited, but prog %s!\n",
2229*de1e4e89SAndroid Build Coastguard Worker 					aux.map.owner.jited ? "is" : "not",
2230*de1e4e89SAndroid Build Coastguard Worker 					aux.prog.jited ? "is" : "not");
2231*de1e4e89SAndroid Build Coastguard Worker 			return ret;
2232*de1e4e89SAndroid Build Coastguard Worker 		}
2233*de1e4e89SAndroid Build Coastguard Worker 
2234*de1e4e89SAndroid Build Coastguard Worker 		ctx->sec_done[i] = true;
2235*de1e4e89SAndroid Build Coastguard Worker 	}
2236*de1e4e89SAndroid Build Coastguard Worker 
2237*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2238*de1e4e89SAndroid Build Coastguard Worker }
2239*de1e4e89SAndroid Build Coastguard Worker 
bpf_save_finfo(struct bpf_elf_ctx * ctx)2240*de1e4e89SAndroid Build Coastguard Worker static void bpf_save_finfo(struct bpf_elf_ctx *ctx)
2241*de1e4e89SAndroid Build Coastguard Worker {
2242*de1e4e89SAndroid Build Coastguard Worker 	struct stat st;
2243*de1e4e89SAndroid Build Coastguard Worker 	int ret;
2244*de1e4e89SAndroid Build Coastguard Worker 
2245*de1e4e89SAndroid Build Coastguard Worker 	memset(&ctx->stat, 0, sizeof(ctx->stat));
2246*de1e4e89SAndroid Build Coastguard Worker 
2247*de1e4e89SAndroid Build Coastguard Worker 	ret = fstat(ctx->obj_fd, &st);
2248*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2249*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Stat of elf file failed: %s\n",
2250*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
2251*de1e4e89SAndroid Build Coastguard Worker 		return;
2252*de1e4e89SAndroid Build Coastguard Worker 	}
2253*de1e4e89SAndroid Build Coastguard Worker 
2254*de1e4e89SAndroid Build Coastguard Worker 	ctx->stat.st_dev = st.st_dev;
2255*de1e4e89SAndroid Build Coastguard Worker 	ctx->stat.st_ino = st.st_ino;
2256*de1e4e89SAndroid Build Coastguard Worker }
2257*de1e4e89SAndroid Build Coastguard Worker 
bpf_read_pin_mapping(FILE * fp,uint32_t * id,char * path)2258*de1e4e89SAndroid Build Coastguard Worker static int bpf_read_pin_mapping(FILE *fp, uint32_t *id, char *path)
2259*de1e4e89SAndroid Build Coastguard Worker {
2260*de1e4e89SAndroid Build Coastguard Worker 	char buff[PATH_MAX];
2261*de1e4e89SAndroid Build Coastguard Worker 
2262*de1e4e89SAndroid Build Coastguard Worker 	while (fgets(buff, sizeof(buff), fp)) {
2263*de1e4e89SAndroid Build Coastguard Worker 		char *ptr = buff;
2264*de1e4e89SAndroid Build Coastguard Worker 
2265*de1e4e89SAndroid Build Coastguard Worker 		while (*ptr == ' ' || *ptr == '\t')
2266*de1e4e89SAndroid Build Coastguard Worker 			ptr++;
2267*de1e4e89SAndroid Build Coastguard Worker 
2268*de1e4e89SAndroid Build Coastguard Worker 		if (*ptr == '#' || *ptr == '\n' || *ptr == 0)
2269*de1e4e89SAndroid Build Coastguard Worker 			continue;
2270*de1e4e89SAndroid Build Coastguard Worker 
2271*de1e4e89SAndroid Build Coastguard Worker 		if (sscanf(ptr, "%i %s\n", id, path) != 2 &&
2272*de1e4e89SAndroid Build Coastguard Worker 		    sscanf(ptr, "%i %s #", id, path) != 2) {
2273*de1e4e89SAndroid Build Coastguard Worker 			strcpy(path, ptr);
2274*de1e4e89SAndroid Build Coastguard Worker 			return -1;
2275*de1e4e89SAndroid Build Coastguard Worker 		}
2276*de1e4e89SAndroid Build Coastguard Worker 
2277*de1e4e89SAndroid Build Coastguard Worker 		return 1;
2278*de1e4e89SAndroid Build Coastguard Worker 	}
2279*de1e4e89SAndroid Build Coastguard Worker 
2280*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2281*de1e4e89SAndroid Build Coastguard Worker }
2282*de1e4e89SAndroid Build Coastguard Worker 
bpf_pinning_reserved(uint32_t pinning)2283*de1e4e89SAndroid Build Coastguard Worker static bool bpf_pinning_reserved(uint32_t pinning)
2284*de1e4e89SAndroid Build Coastguard Worker {
2285*de1e4e89SAndroid Build Coastguard Worker 	switch (pinning) {
2286*de1e4e89SAndroid Build Coastguard Worker 	case PIN_NONE:
2287*de1e4e89SAndroid Build Coastguard Worker 	case PIN_OBJECT_NS:
2288*de1e4e89SAndroid Build Coastguard Worker 	case PIN_GLOBAL_NS:
2289*de1e4e89SAndroid Build Coastguard Worker 		return true;
2290*de1e4e89SAndroid Build Coastguard Worker 	default:
2291*de1e4e89SAndroid Build Coastguard Worker 		return false;
2292*de1e4e89SAndroid Build Coastguard Worker 	}
2293*de1e4e89SAndroid Build Coastguard Worker }
2294*de1e4e89SAndroid Build Coastguard Worker 
bpf_hash_init(struct bpf_elf_ctx * ctx,const char * db_file)2295*de1e4e89SAndroid Build Coastguard Worker static void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
2296*de1e4e89SAndroid Build Coastguard Worker {
2297*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_hash_entry *entry;
2298*de1e4e89SAndroid Build Coastguard Worker 	char subpath[PATH_MAX] = {};
2299*de1e4e89SAndroid Build Coastguard Worker 	uint32_t pinning;
2300*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp;
2301*de1e4e89SAndroid Build Coastguard Worker 	int ret;
2302*de1e4e89SAndroid Build Coastguard Worker 
2303*de1e4e89SAndroid Build Coastguard Worker 	fp = fopen(db_file, "r");
2304*de1e4e89SAndroid Build Coastguard Worker 	if (!fp)
2305*de1e4e89SAndroid Build Coastguard Worker 		return;
2306*de1e4e89SAndroid Build Coastguard Worker 
2307*de1e4e89SAndroid Build Coastguard Worker 	while ((ret = bpf_read_pin_mapping(fp, &pinning, subpath))) {
2308*de1e4e89SAndroid Build Coastguard Worker 		if (ret == -1) {
2309*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Database %s is corrupted at: %s\n",
2310*de1e4e89SAndroid Build Coastguard Worker 				db_file, subpath);
2311*de1e4e89SAndroid Build Coastguard Worker 			fclose(fp);
2312*de1e4e89SAndroid Build Coastguard Worker 			return;
2313*de1e4e89SAndroid Build Coastguard Worker 		}
2314*de1e4e89SAndroid Build Coastguard Worker 
2315*de1e4e89SAndroid Build Coastguard Worker 		if (bpf_pinning_reserved(pinning)) {
2316*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Database %s, id %u is reserved - ignoring!\n",
2317*de1e4e89SAndroid Build Coastguard Worker 				db_file, pinning);
2318*de1e4e89SAndroid Build Coastguard Worker 			continue;
2319*de1e4e89SAndroid Build Coastguard Worker 		}
2320*de1e4e89SAndroid Build Coastguard Worker 
2321*de1e4e89SAndroid Build Coastguard Worker 		entry = malloc(sizeof(*entry));
2322*de1e4e89SAndroid Build Coastguard Worker 		if (!entry) {
2323*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "No memory left for db entry!\n");
2324*de1e4e89SAndroid Build Coastguard Worker 			continue;
2325*de1e4e89SAndroid Build Coastguard Worker 		}
2326*de1e4e89SAndroid Build Coastguard Worker 
2327*de1e4e89SAndroid Build Coastguard Worker 		entry->pinning = pinning;
2328*de1e4e89SAndroid Build Coastguard Worker 		entry->subpath = strdup(subpath);
2329*de1e4e89SAndroid Build Coastguard Worker 		if (!entry->subpath) {
2330*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "No memory left for db entry!\n");
2331*de1e4e89SAndroid Build Coastguard Worker 			free(entry);
2332*de1e4e89SAndroid Build Coastguard Worker 			continue;
2333*de1e4e89SAndroid Build Coastguard Worker 		}
2334*de1e4e89SAndroid Build Coastguard Worker 
2335*de1e4e89SAndroid Build Coastguard Worker 		entry->next = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)];
2336*de1e4e89SAndroid Build Coastguard Worker 		ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)] = entry;
2337*de1e4e89SAndroid Build Coastguard Worker 	}
2338*de1e4e89SAndroid Build Coastguard Worker 
2339*de1e4e89SAndroid Build Coastguard Worker 	fclose(fp);
2340*de1e4e89SAndroid Build Coastguard Worker }
2341*de1e4e89SAndroid Build Coastguard Worker 
bpf_hash_destroy(struct bpf_elf_ctx * ctx)2342*de1e4e89SAndroid Build Coastguard Worker static void bpf_hash_destroy(struct bpf_elf_ctx *ctx)
2343*de1e4e89SAndroid Build Coastguard Worker {
2344*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_hash_entry *entry;
2345*de1e4e89SAndroid Build Coastguard Worker 	int i;
2346*de1e4e89SAndroid Build Coastguard Worker 
2347*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(ctx->ht); i++) {
2348*de1e4e89SAndroid Build Coastguard Worker 		while ((entry = ctx->ht[i]) != NULL) {
2349*de1e4e89SAndroid Build Coastguard Worker 			ctx->ht[i] = entry->next;
2350*de1e4e89SAndroid Build Coastguard Worker 			free((char *)entry->subpath);
2351*de1e4e89SAndroid Build Coastguard Worker 			free(entry);
2352*de1e4e89SAndroid Build Coastguard Worker 		}
2353*de1e4e89SAndroid Build Coastguard Worker 	}
2354*de1e4e89SAndroid Build Coastguard Worker }
2355*de1e4e89SAndroid Build Coastguard Worker 
bpf_elf_check_ehdr(const struct bpf_elf_ctx * ctx)2356*de1e4e89SAndroid Build Coastguard Worker static int bpf_elf_check_ehdr(const struct bpf_elf_ctx *ctx)
2357*de1e4e89SAndroid Build Coastguard Worker {
2358*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->elf_hdr.e_type != ET_REL ||
2359*de1e4e89SAndroid Build Coastguard Worker 	    (ctx->elf_hdr.e_machine != EM_NONE &&
2360*de1e4e89SAndroid Build Coastguard Worker 	     ctx->elf_hdr.e_machine != EM_BPF) ||
2361*de1e4e89SAndroid Build Coastguard Worker 	    ctx->elf_hdr.e_version != EV_CURRENT) {
2362*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "ELF format error, ELF file not for eBPF?\n");
2363*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
2364*de1e4e89SAndroid Build Coastguard Worker 	}
2365*de1e4e89SAndroid Build Coastguard Worker 
2366*de1e4e89SAndroid Build Coastguard Worker 	switch (ctx->elf_hdr.e_ident[EI_DATA]) {
2367*de1e4e89SAndroid Build Coastguard Worker 	default:
2368*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "ELF format error, wrong endianness info?\n");
2369*de1e4e89SAndroid Build Coastguard Worker 		return -EINVAL;
2370*de1e4e89SAndroid Build Coastguard Worker 	case ELFDATA2LSB:
2371*de1e4e89SAndroid Build Coastguard Worker 		if (htons(1) == 1) {
2372*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr,
2373*de1e4e89SAndroid Build Coastguard Worker 				"We are big endian, eBPF object is little endian!\n");
2374*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2375*de1e4e89SAndroid Build Coastguard Worker 		}
2376*de1e4e89SAndroid Build Coastguard Worker 		break;
2377*de1e4e89SAndroid Build Coastguard Worker 	case ELFDATA2MSB:
2378*de1e4e89SAndroid Build Coastguard Worker 		if (htons(1) != 1) {
2379*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr,
2380*de1e4e89SAndroid Build Coastguard Worker 				"We are little endian, eBPF object is big endian!\n");
2381*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2382*de1e4e89SAndroid Build Coastguard Worker 		}
2383*de1e4e89SAndroid Build Coastguard Worker 		break;
2384*de1e4e89SAndroid Build Coastguard Worker 	}
2385*de1e4e89SAndroid Build Coastguard Worker 
2386*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2387*de1e4e89SAndroid Build Coastguard Worker }
2388*de1e4e89SAndroid Build Coastguard Worker 
bpf_get_cfg(struct bpf_elf_ctx * ctx)2389*de1e4e89SAndroid Build Coastguard Worker static void bpf_get_cfg(struct bpf_elf_ctx *ctx)
2390*de1e4e89SAndroid Build Coastguard Worker {
2391*de1e4e89SAndroid Build Coastguard Worker 	static const char *path_jit = "/proc/sys/net/core/bpf_jit_enable";
2392*de1e4e89SAndroid Build Coastguard Worker 	int fd;
2393*de1e4e89SAndroid Build Coastguard Worker 
2394*de1e4e89SAndroid Build Coastguard Worker 	fd = open(path_jit, O_RDONLY);
2395*de1e4e89SAndroid Build Coastguard Worker 	if (fd > 0) {
2396*de1e4e89SAndroid Build Coastguard Worker 		char tmp[16] = {};
2397*de1e4e89SAndroid Build Coastguard Worker 
2398*de1e4e89SAndroid Build Coastguard Worker 		if (read(fd, tmp, sizeof(tmp)) > 0)
2399*de1e4e89SAndroid Build Coastguard Worker 			ctx->cfg.jit_enabled = atoi(tmp);
2400*de1e4e89SAndroid Build Coastguard Worker 		close(fd);
2401*de1e4e89SAndroid Build Coastguard Worker 	}
2402*de1e4e89SAndroid Build Coastguard Worker }
2403*de1e4e89SAndroid Build Coastguard Worker 
bpf_elf_ctx_init(struct bpf_elf_ctx * ctx,const char * pathname,enum bpf_prog_type type,bool verbose)2404*de1e4e89SAndroid Build Coastguard Worker static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
2405*de1e4e89SAndroid Build Coastguard Worker 			    enum bpf_prog_type type, bool verbose)
2406*de1e4e89SAndroid Build Coastguard Worker {
2407*de1e4e89SAndroid Build Coastguard Worker 	int ret = -EINVAL;
2408*de1e4e89SAndroid Build Coastguard Worker 
2409*de1e4e89SAndroid Build Coastguard Worker 	if (elf_version(EV_CURRENT) == EV_NONE ||
2410*de1e4e89SAndroid Build Coastguard Worker 	    bpf_init_env(pathname))
2411*de1e4e89SAndroid Build Coastguard Worker 		return ret;
2412*de1e4e89SAndroid Build Coastguard Worker 
2413*de1e4e89SAndroid Build Coastguard Worker 	memset(ctx, 0, sizeof(*ctx));
2414*de1e4e89SAndroid Build Coastguard Worker 	bpf_get_cfg(ctx);
2415*de1e4e89SAndroid Build Coastguard Worker 	ctx->verbose = verbose;
2416*de1e4e89SAndroid Build Coastguard Worker 	ctx->type    = type;
2417*de1e4e89SAndroid Build Coastguard Worker 
2418*de1e4e89SAndroid Build Coastguard Worker 	ctx->obj_fd = open(pathname, O_RDONLY);
2419*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->obj_fd < 0)
2420*de1e4e89SAndroid Build Coastguard Worker 		return ctx->obj_fd;
2421*de1e4e89SAndroid Build Coastguard Worker 
2422*de1e4e89SAndroid Build Coastguard Worker 	ctx->elf_fd = elf_begin(ctx->obj_fd, ELF_C_READ, NULL);
2423*de1e4e89SAndroid Build Coastguard Worker 	if (!ctx->elf_fd) {
2424*de1e4e89SAndroid Build Coastguard Worker 		ret = -EINVAL;
2425*de1e4e89SAndroid Build Coastguard Worker 		goto out_fd;
2426*de1e4e89SAndroid Build Coastguard Worker 	}
2427*de1e4e89SAndroid Build Coastguard Worker 
2428*de1e4e89SAndroid Build Coastguard Worker 	if (elf_kind(ctx->elf_fd) != ELF_K_ELF) {
2429*de1e4e89SAndroid Build Coastguard Worker 		ret = -EINVAL;
2430*de1e4e89SAndroid Build Coastguard Worker 		goto out_fd;
2431*de1e4e89SAndroid Build Coastguard Worker 	}
2432*de1e4e89SAndroid Build Coastguard Worker 
2433*de1e4e89SAndroid Build Coastguard Worker 	if (gelf_getehdr(ctx->elf_fd, &ctx->elf_hdr) !=
2434*de1e4e89SAndroid Build Coastguard Worker 	    &ctx->elf_hdr) {
2435*de1e4e89SAndroid Build Coastguard Worker 		ret = -EIO;
2436*de1e4e89SAndroid Build Coastguard Worker 		goto out_elf;
2437*de1e4e89SAndroid Build Coastguard Worker 	}
2438*de1e4e89SAndroid Build Coastguard Worker 
2439*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_elf_check_ehdr(ctx);
2440*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
2441*de1e4e89SAndroid Build Coastguard Worker 		goto out_elf;
2442*de1e4e89SAndroid Build Coastguard Worker 
2443*de1e4e89SAndroid Build Coastguard Worker 	ctx->sec_done = calloc(ctx->elf_hdr.e_shnum,
2444*de1e4e89SAndroid Build Coastguard Worker 			       sizeof(*(ctx->sec_done)));
2445*de1e4e89SAndroid Build Coastguard Worker 	if (!ctx->sec_done) {
2446*de1e4e89SAndroid Build Coastguard Worker 		ret = -ENOMEM;
2447*de1e4e89SAndroid Build Coastguard Worker 		goto out_elf;
2448*de1e4e89SAndroid Build Coastguard Worker 	}
2449*de1e4e89SAndroid Build Coastguard Worker 
2450*de1e4e89SAndroid Build Coastguard Worker 	if (ctx->verbose && bpf_log_realloc(ctx)) {
2451*de1e4e89SAndroid Build Coastguard Worker 		ret = -ENOMEM;
2452*de1e4e89SAndroid Build Coastguard Worker 		goto out_free;
2453*de1e4e89SAndroid Build Coastguard Worker 	}
2454*de1e4e89SAndroid Build Coastguard Worker 
2455*de1e4e89SAndroid Build Coastguard Worker 	bpf_save_finfo(ctx);
2456*de1e4e89SAndroid Build Coastguard Worker 	bpf_hash_init(ctx, CONFDIR "/bpf_pinning");
2457*de1e4e89SAndroid Build Coastguard Worker 
2458*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2459*de1e4e89SAndroid Build Coastguard Worker out_free:
2460*de1e4e89SAndroid Build Coastguard Worker 	free(ctx->sec_done);
2461*de1e4e89SAndroid Build Coastguard Worker out_elf:
2462*de1e4e89SAndroid Build Coastguard Worker 	elf_end(ctx->elf_fd);
2463*de1e4e89SAndroid Build Coastguard Worker out_fd:
2464*de1e4e89SAndroid Build Coastguard Worker 	close(ctx->obj_fd);
2465*de1e4e89SAndroid Build Coastguard Worker 	return ret;
2466*de1e4e89SAndroid Build Coastguard Worker }
2467*de1e4e89SAndroid Build Coastguard Worker 
bpf_maps_count(struct bpf_elf_ctx * ctx)2468*de1e4e89SAndroid Build Coastguard Worker static int bpf_maps_count(struct bpf_elf_ctx *ctx)
2469*de1e4e89SAndroid Build Coastguard Worker {
2470*de1e4e89SAndroid Build Coastguard Worker 	int i, count = 0;
2471*de1e4e89SAndroid Build Coastguard Worker 
2472*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) {
2473*de1e4e89SAndroid Build Coastguard Worker 		if (!ctx->map_fds[i])
2474*de1e4e89SAndroid Build Coastguard Worker 			break;
2475*de1e4e89SAndroid Build Coastguard Worker 		count++;
2476*de1e4e89SAndroid Build Coastguard Worker 	}
2477*de1e4e89SAndroid Build Coastguard Worker 
2478*de1e4e89SAndroid Build Coastguard Worker 	return count;
2479*de1e4e89SAndroid Build Coastguard Worker }
2480*de1e4e89SAndroid Build Coastguard Worker 
bpf_maps_teardown(struct bpf_elf_ctx * ctx)2481*de1e4e89SAndroid Build Coastguard Worker static void bpf_maps_teardown(struct bpf_elf_ctx *ctx)
2482*de1e4e89SAndroid Build Coastguard Worker {
2483*de1e4e89SAndroid Build Coastguard Worker 	int i;
2484*de1e4e89SAndroid Build Coastguard Worker 
2485*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) {
2486*de1e4e89SAndroid Build Coastguard Worker 		if (ctx->map_fds[i])
2487*de1e4e89SAndroid Build Coastguard Worker 			close(ctx->map_fds[i]);
2488*de1e4e89SAndroid Build Coastguard Worker 	}
2489*de1e4e89SAndroid Build Coastguard Worker }
2490*de1e4e89SAndroid Build Coastguard Worker 
bpf_elf_ctx_destroy(struct bpf_elf_ctx * ctx,bool failure)2491*de1e4e89SAndroid Build Coastguard Worker static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
2492*de1e4e89SAndroid Build Coastguard Worker {
2493*de1e4e89SAndroid Build Coastguard Worker 	if (failure)
2494*de1e4e89SAndroid Build Coastguard Worker 		bpf_maps_teardown(ctx);
2495*de1e4e89SAndroid Build Coastguard Worker 
2496*de1e4e89SAndroid Build Coastguard Worker 	bpf_hash_destroy(ctx);
2497*de1e4e89SAndroid Build Coastguard Worker 
2498*de1e4e89SAndroid Build Coastguard Worker 	free(ctx->sec_done);
2499*de1e4e89SAndroid Build Coastguard Worker 	free(ctx->log);
2500*de1e4e89SAndroid Build Coastguard Worker 
2501*de1e4e89SAndroid Build Coastguard Worker 	elf_end(ctx->elf_fd);
2502*de1e4e89SAndroid Build Coastguard Worker 	close(ctx->obj_fd);
2503*de1e4e89SAndroid Build Coastguard Worker }
2504*de1e4e89SAndroid Build Coastguard Worker 
2505*de1e4e89SAndroid Build Coastguard Worker static struct bpf_elf_ctx __ctx;
2506*de1e4e89SAndroid Build Coastguard Worker 
bpf_obj_open(const char * pathname,enum bpf_prog_type type,const char * section,bool verbose)2507*de1e4e89SAndroid Build Coastguard Worker static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
2508*de1e4e89SAndroid Build Coastguard Worker 			const char *section, bool verbose)
2509*de1e4e89SAndroid Build Coastguard Worker {
2510*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_ctx *ctx = &__ctx;
2511*de1e4e89SAndroid Build Coastguard Worker 	int fd = 0, ret;
2512*de1e4e89SAndroid Build Coastguard Worker 
2513*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_elf_ctx_init(ctx, pathname, type, verbose);
2514*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2515*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot initialize ELF context!\n");
2516*de1e4e89SAndroid Build Coastguard Worker 		return ret;
2517*de1e4e89SAndroid Build Coastguard Worker 	}
2518*de1e4e89SAndroid Build Coastguard Worker 
2519*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_fetch_ancillary(ctx);
2520*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2521*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error fetching ELF ancillary data!\n");
2522*de1e4e89SAndroid Build Coastguard Worker 		goto out;
2523*de1e4e89SAndroid Build Coastguard Worker 	}
2524*de1e4e89SAndroid Build Coastguard Worker 
2525*de1e4e89SAndroid Build Coastguard Worker 	fd = bpf_fetch_prog_sec(ctx, section);
2526*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
2527*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error fetching program/map!\n");
2528*de1e4e89SAndroid Build Coastguard Worker 		ret = fd;
2529*de1e4e89SAndroid Build Coastguard Worker 		goto out;
2530*de1e4e89SAndroid Build Coastguard Worker 	}
2531*de1e4e89SAndroid Build Coastguard Worker 
2532*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_fill_prog_arrays(ctx);
2533*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
2534*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Error filling program arrays!\n");
2535*de1e4e89SAndroid Build Coastguard Worker out:
2536*de1e4e89SAndroid Build Coastguard Worker 	bpf_elf_ctx_destroy(ctx, ret < 0);
2537*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2538*de1e4e89SAndroid Build Coastguard Worker 		if (fd)
2539*de1e4e89SAndroid Build Coastguard Worker 			close(fd);
2540*de1e4e89SAndroid Build Coastguard Worker 		return ret;
2541*de1e4e89SAndroid Build Coastguard Worker 	}
2542*de1e4e89SAndroid Build Coastguard Worker 
2543*de1e4e89SAndroid Build Coastguard Worker 	return fd;
2544*de1e4e89SAndroid Build Coastguard Worker }
2545*de1e4e89SAndroid Build Coastguard Worker 
2546*de1e4e89SAndroid Build Coastguard Worker static int
bpf_map_set_send(int fd,struct sockaddr_un * addr,unsigned int addr_len,const struct bpf_map_data * aux,unsigned int entries)2547*de1e4e89SAndroid Build Coastguard Worker bpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len,
2548*de1e4e89SAndroid Build Coastguard Worker 		 const struct bpf_map_data *aux, unsigned int entries)
2549*de1e4e89SAndroid Build Coastguard Worker {
2550*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_set_msg msg = {
2551*de1e4e89SAndroid Build Coastguard Worker 		.aux.uds_ver = BPF_SCM_AUX_VER,
2552*de1e4e89SAndroid Build Coastguard Worker 		.aux.num_ent = entries,
2553*de1e4e89SAndroid Build Coastguard Worker 	};
2554*de1e4e89SAndroid Build Coastguard Worker 	int *cmsg_buf, min_fd;
2555*de1e4e89SAndroid Build Coastguard Worker 	char *amsg_buf;
2556*de1e4e89SAndroid Build Coastguard Worker 	int i;
2557*de1e4e89SAndroid Build Coastguard Worker 
2558*de1e4e89SAndroid Build Coastguard Worker 	strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name));
2559*de1e4e89SAndroid Build Coastguard Worker 	memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st));
2560*de1e4e89SAndroid Build Coastguard Worker 
2561*de1e4e89SAndroid Build Coastguard Worker 	cmsg_buf = bpf_map_set_init(&msg, addr, addr_len);
2562*de1e4e89SAndroid Build Coastguard Worker 	amsg_buf = (char *)msg.aux.ent;
2563*de1e4e89SAndroid Build Coastguard Worker 
2564*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < entries; i += min_fd) {
2565*de1e4e89SAndroid Build Coastguard Worker 		int ret;
2566*de1e4e89SAndroid Build Coastguard Worker 
2567*de1e4e89SAndroid Build Coastguard Worker 		min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i);
2568*de1e4e89SAndroid Build Coastguard Worker 		bpf_map_set_init_single(&msg, min_fd);
2569*de1e4e89SAndroid Build Coastguard Worker 
2570*de1e4e89SAndroid Build Coastguard Worker 		memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd);
2571*de1e4e89SAndroid Build Coastguard Worker 		memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd);
2572*de1e4e89SAndroid Build Coastguard Worker 
2573*de1e4e89SAndroid Build Coastguard Worker 		ret = sendmsg(fd, &msg.hdr, 0);
2574*de1e4e89SAndroid Build Coastguard Worker 		if (ret <= 0)
2575*de1e4e89SAndroid Build Coastguard Worker 			return ret ? : -1;
2576*de1e4e89SAndroid Build Coastguard Worker 	}
2577*de1e4e89SAndroid Build Coastguard Worker 
2578*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2579*de1e4e89SAndroid Build Coastguard Worker }
2580*de1e4e89SAndroid Build Coastguard Worker 
2581*de1e4e89SAndroid Build Coastguard Worker static int
bpf_map_set_recv(int fd,int * fds,struct bpf_map_aux * aux,unsigned int entries)2582*de1e4e89SAndroid Build Coastguard Worker bpf_map_set_recv(int fd, int *fds,  struct bpf_map_aux *aux,
2583*de1e4e89SAndroid Build Coastguard Worker 		 unsigned int entries)
2584*de1e4e89SAndroid Build Coastguard Worker {
2585*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_set_msg msg;
2586*de1e4e89SAndroid Build Coastguard Worker 	int *cmsg_buf, min_fd;
2587*de1e4e89SAndroid Build Coastguard Worker 	char *amsg_buf, *mmsg_buf;
2588*de1e4e89SAndroid Build Coastguard Worker 	unsigned int needed = 1;
2589*de1e4e89SAndroid Build Coastguard Worker 	int i;
2590*de1e4e89SAndroid Build Coastguard Worker 
2591*de1e4e89SAndroid Build Coastguard Worker 	cmsg_buf = bpf_map_set_init(&msg, NULL, 0);
2592*de1e4e89SAndroid Build Coastguard Worker 	amsg_buf = (char *)msg.aux.ent;
2593*de1e4e89SAndroid Build Coastguard Worker 	mmsg_buf = (char *)&msg.aux;
2594*de1e4e89SAndroid Build Coastguard Worker 
2595*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < min(entries, needed); i += min_fd) {
2596*de1e4e89SAndroid Build Coastguard Worker 		struct cmsghdr *cmsg;
2597*de1e4e89SAndroid Build Coastguard Worker 		int ret;
2598*de1e4e89SAndroid Build Coastguard Worker 
2599*de1e4e89SAndroid Build Coastguard Worker 		min_fd = min(entries, entries - i);
2600*de1e4e89SAndroid Build Coastguard Worker 		bpf_map_set_init_single(&msg, min_fd);
2601*de1e4e89SAndroid Build Coastguard Worker 
2602*de1e4e89SAndroid Build Coastguard Worker 		ret = recvmsg(fd, &msg.hdr, 0);
2603*de1e4e89SAndroid Build Coastguard Worker 		if (ret <= 0)
2604*de1e4e89SAndroid Build Coastguard Worker 			return ret ? : -1;
2605*de1e4e89SAndroid Build Coastguard Worker 
2606*de1e4e89SAndroid Build Coastguard Worker 		cmsg = CMSG_FIRSTHDR(&msg.hdr);
2607*de1e4e89SAndroid Build Coastguard Worker 		if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS)
2608*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
2609*de1e4e89SAndroid Build Coastguard Worker 		if (msg.hdr.msg_flags & MSG_CTRUNC)
2610*de1e4e89SAndroid Build Coastguard Worker 			return -EIO;
2611*de1e4e89SAndroid Build Coastguard Worker 		if (msg.aux.uds_ver != BPF_SCM_AUX_VER)
2612*de1e4e89SAndroid Build Coastguard Worker 			return -ENOSYS;
2613*de1e4e89SAndroid Build Coastguard Worker 
2614*de1e4e89SAndroid Build Coastguard Worker 		min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd);
2615*de1e4e89SAndroid Build Coastguard Worker 		if (min_fd > entries || min_fd <= 0)
2616*de1e4e89SAndroid Build Coastguard Worker 			return -EINVAL;
2617*de1e4e89SAndroid Build Coastguard Worker 
2618*de1e4e89SAndroid Build Coastguard Worker 		memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd);
2619*de1e4e89SAndroid Build Coastguard Worker 		memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd);
2620*de1e4e89SAndroid Build Coastguard Worker 		memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent));
2621*de1e4e89SAndroid Build Coastguard Worker 
2622*de1e4e89SAndroid Build Coastguard Worker 		needed = aux->num_ent;
2623*de1e4e89SAndroid Build Coastguard Worker 	}
2624*de1e4e89SAndroid Build Coastguard Worker 
2625*de1e4e89SAndroid Build Coastguard Worker 	return 0;
2626*de1e4e89SAndroid Build Coastguard Worker }
2627*de1e4e89SAndroid Build Coastguard Worker 
bpf_send_map_fds(const char * path,const char * obj)2628*de1e4e89SAndroid Build Coastguard Worker int bpf_send_map_fds(const char *path, const char *obj)
2629*de1e4e89SAndroid Build Coastguard Worker {
2630*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_elf_ctx *ctx = &__ctx;
2631*de1e4e89SAndroid Build Coastguard Worker 	struct sockaddr_un addr = { .sun_family = AF_UNIX };
2632*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_map_data bpf_aux = {
2633*de1e4e89SAndroid Build Coastguard Worker 		.fds = ctx->map_fds,
2634*de1e4e89SAndroid Build Coastguard Worker 		.ent = ctx->maps,
2635*de1e4e89SAndroid Build Coastguard Worker 		.st  = &ctx->stat,
2636*de1e4e89SAndroid Build Coastguard Worker 		.obj = obj,
2637*de1e4e89SAndroid Build Coastguard Worker 	};
2638*de1e4e89SAndroid Build Coastguard Worker 	int fd, ret;
2639*de1e4e89SAndroid Build Coastguard Worker 
2640*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
2641*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
2642*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot open socket: %s\n",
2643*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
2644*de1e4e89SAndroid Build Coastguard Worker 		return -1;
2645*de1e4e89SAndroid Build Coastguard Worker 	}
2646*de1e4e89SAndroid Build Coastguard Worker 
2647*de1e4e89SAndroid Build Coastguard Worker 	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
2648*de1e4e89SAndroid Build Coastguard Worker 
2649*de1e4e89SAndroid Build Coastguard Worker 	ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
2650*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2651*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot connect to %s: %s\n",
2652*de1e4e89SAndroid Build Coastguard Worker 			path, strerror(errno));
2653*de1e4e89SAndroid Build Coastguard Worker 		return -1;
2654*de1e4e89SAndroid Build Coastguard Worker 	}
2655*de1e4e89SAndroid Build Coastguard Worker 
2656*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux,
2657*de1e4e89SAndroid Build Coastguard Worker 			       bpf_maps_count(ctx));
2658*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
2659*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot send fds to %s: %s\n",
2660*de1e4e89SAndroid Build Coastguard Worker 			path, strerror(errno));
2661*de1e4e89SAndroid Build Coastguard Worker 
2662*de1e4e89SAndroid Build Coastguard Worker 	bpf_maps_teardown(ctx);
2663*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
2664*de1e4e89SAndroid Build Coastguard Worker 	return ret;
2665*de1e4e89SAndroid Build Coastguard Worker }
2666*de1e4e89SAndroid Build Coastguard Worker 
bpf_recv_map_fds(const char * path,int * fds,struct bpf_map_aux * aux,unsigned int entries)2667*de1e4e89SAndroid Build Coastguard Worker int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
2668*de1e4e89SAndroid Build Coastguard Worker 		     unsigned int entries)
2669*de1e4e89SAndroid Build Coastguard Worker {
2670*de1e4e89SAndroid Build Coastguard Worker 	struct sockaddr_un addr = { .sun_family = AF_UNIX };
2671*de1e4e89SAndroid Build Coastguard Worker 	int fd, ret;
2672*de1e4e89SAndroid Build Coastguard Worker 
2673*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
2674*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
2675*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot open socket: %s\n",
2676*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
2677*de1e4e89SAndroid Build Coastguard Worker 		return -1;
2678*de1e4e89SAndroid Build Coastguard Worker 	}
2679*de1e4e89SAndroid Build Coastguard Worker 
2680*de1e4e89SAndroid Build Coastguard Worker 	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
2681*de1e4e89SAndroid Build Coastguard Worker 
2682*de1e4e89SAndroid Build Coastguard Worker 	ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
2683*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0) {
2684*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot bind to socket: %s\n",
2685*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
2686*de1e4e89SAndroid Build Coastguard Worker 		return -1;
2687*de1e4e89SAndroid Build Coastguard Worker 	}
2688*de1e4e89SAndroid Build Coastguard Worker 
2689*de1e4e89SAndroid Build Coastguard Worker 	ret = bpf_map_set_recv(fd, fds, aux, entries);
2690*de1e4e89SAndroid Build Coastguard Worker 	if (ret < 0)
2691*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot recv fds from %s: %s\n",
2692*de1e4e89SAndroid Build Coastguard Worker 			path, strerror(errno));
2693*de1e4e89SAndroid Build Coastguard Worker 
2694*de1e4e89SAndroid Build Coastguard Worker 	unlink(addr.sun_path);
2695*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
2696*de1e4e89SAndroid Build Coastguard Worker 	return ret;
2697*de1e4e89SAndroid Build Coastguard Worker }
2698*de1e4e89SAndroid Build Coastguard Worker #endif /* HAVE_ELF */
2699