]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/tc_bpf.c
tc: q_{codel,fq_codel}: add missing space in help text
[mirror_iproute2.git] / tc / tc_bpf.c
CommitLineData
1d129d19
JP
1/*
2 * tc_bpf.c BPF common code
3 *
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Daniel Borkmann <dborkman@redhat.com>
10 * Jiri Pirko <jiri@resnulli.us>
11c39b5e 11 * Alexei Starovoitov <ast@plumgrid.com>
1d129d19
JP
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <string.h>
18#include <stdbool.h>
473d7840 19#include <stdint.h>
1d129d19 20#include <errno.h>
11c39b5e
DB
21#include <fcntl.h>
22#include <stdarg.h>
1d129d19 23
11c39b5e
DB
24#ifdef HAVE_ELF
25#include <libelf.h>
26#include <gelf.h>
27#endif
28
32e93fb7
DB
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/un.h>
32#include <sys/vfs.h>
33#include <sys/mount.h>
34#include <sys/syscall.h>
35#include <sys/sendfile.h>
36#include <sys/resource.h>
37
38#include <linux/bpf.h>
39#include <linux/filter.h>
40#include <linux/if_alg.h>
41
8187b012
DB
42#include <arpa/inet.h>
43
1d129d19 44#include "utils.h"
6256f8c9
DB
45
46#include "bpf_elf.h"
47#include "bpf_scm.h"
48
1d129d19
JP
49#include "tc_util.h"
50#include "tc_bpf.h"
51
67584e3a
ND
52#ifndef AF_ALG
53#define AF_ALG 38
54#endif
55
32e93fb7
DB
56#ifdef HAVE_ELF
57static int bpf_obj_open(const char *path, enum bpf_prog_type type,
58 const char *sec, bool verbose);
59#else
60static int bpf_obj_open(const char *path, enum bpf_prog_type type,
61 const char *sec, bool verbose)
62{
63 fprintf(stderr, "No ELF library support compiled in.\n");
64 errno = ENOSYS;
65 return -1;
66}
67#endif
68
69static inline __u64 bpf_ptr_to_u64(const void *ptr)
70{
71 return (__u64)(unsigned long)ptr;
72}
73
74static int bpf(int cmd, union bpf_attr *attr, unsigned int size)
75{
76#ifdef __NR_bpf
77 return syscall(__NR_bpf, cmd, attr, size);
78#else
79 fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
80 errno = ENOSYS;
81 return -1;
82#endif
83}
84
91d88eeb
DB
85static int bpf_map_update(int fd, const void *key, const void *value,
86 uint64_t flags)
32e93fb7 87{
67584e3a
ND
88 union bpf_attr attr;
89
90 memset(&attr, 0, sizeof(attr));
91 attr.map_fd = fd;
92 attr.key = bpf_ptr_to_u64(key);
93 attr.value = bpf_ptr_to_u64(value);
94 attr.flags = flags;
32e93fb7 95
91d88eeb 96 return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
32e93fb7
DB
97}
98
99static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
100 char **bpf_string, bool *need_release,
101 const char separator)
1d129d19
JP
102{
103 char sp;
104
105 if (from_file) {
106 size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
107 char *tmp_string;
108 FILE *fp;
109
110 tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
111 tmp_string = malloc(tmp_len);
112 if (tmp_string == NULL)
113 return -ENOMEM;
114
115 memset(tmp_string, 0, tmp_len);
116
117 fp = fopen(arg, "r");
118 if (fp == NULL) {
119 perror("Cannot fopen");
120 free(tmp_string);
121 return -ENOENT;
122 }
123
124 if (!fgets(tmp_string, tmp_len, fp)) {
125 free(tmp_string);
126 fclose(fp);
127 return -EIO;
128 }
129
130 fclose(fp);
131
132 *need_release = true;
133 *bpf_string = tmp_string;
134 } else {
135 *need_release = false;
136 *bpf_string = arg;
137 }
138
139 if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
140 sp != separator) {
141 if (*need_release)
142 free(*bpf_string);
143 return -EINVAL;
144 }
145
146 return 0;
147}
148
32e93fb7
DB
149static int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops,
150 bool from_file)
1d129d19
JP
151{
152 char *bpf_string, *token, separator = ',';
153 int ret = 0, i = 0;
154 bool need_release;
155 __u16 bpf_len = 0;
156
157 if (argc < 1)
158 return -EINVAL;
159 if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
160 &need_release, separator))
161 return -EINVAL;
162 if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
163 ret = -EINVAL;
164 goto out;
165 }
166
167 token = bpf_string;
168 while ((token = strchr(token, separator)) && (++token)[0]) {
169 if (i >= bpf_len) {
170 fprintf(stderr, "Real program length exceeds encoded "
171 "length parameter!\n");
172 ret = -EINVAL;
173 goto out;
174 }
175
176 if (sscanf(token, "%hu %hhu %hhu %u,",
177 &bpf_ops[i].code, &bpf_ops[i].jt,
178 &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
179 fprintf(stderr, "Error at instruction %d!\n", i);
180 ret = -EINVAL;
181 goto out;
182 }
183
184 i++;
185 }
186
187 if (i != bpf_len) {
188 fprintf(stderr, "Parsed program length is less than encoded"
189 "length parameter!\n");
190 ret = -EINVAL;
191 goto out;
192 }
193 ret = bpf_len;
1d129d19
JP
194out:
195 if (need_release)
196 free(bpf_string);
197
198 return ret;
199}
200
201void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
202{
203 struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
204 int i;
205
206 if (len == 0)
207 return;
208
209 fprintf(f, "bytecode \'%u,", len);
210
211 for (i = 0; i < len - 1; i++)
212 fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
213 ops[i].jf, ops[i].k);
214
6256f8c9 215 fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt,
1d129d19
JP
216 ops[i].jf, ops[i].k);
217}
11c39b5e 218
91d88eeb
DB
219static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
220 int length)
9e607f2e
DB
221{
222 char file[PATH_MAX], buff[4096];
223 struct bpf_elf_map tmp, zero;
224 unsigned int val;
225 FILE *fp;
226
227 snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
228
229 fp = fopen(file, "r");
230 if (!fp) {
231 fprintf(stderr, "No procfs support?!\n");
232 return -EIO;
233 }
234
235 memset(&tmp, 0, sizeof(tmp));
236 while (fgets(buff, sizeof(buff), fp)) {
237 if (sscanf(buff, "map_type:\t%u", &val) == 1)
238 tmp.type = val;
239 else if (sscanf(buff, "key_size:\t%u", &val) == 1)
240 tmp.size_key = val;
241 else if (sscanf(buff, "value_size:\t%u", &val) == 1)
242 tmp.size_value = val;
243 else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
244 tmp.max_elem = val;
245 }
246
247 fclose(fp);
248
91d88eeb 249 if (!memcmp(&tmp, map, length)) {
9e607f2e
DB
250 return 0;
251 } else {
252 memset(&zero, 0, sizeof(zero));
253 /* If kernel doesn't have eBPF-related fdinfo, we cannot do much,
254 * so just accept it. We know we do have an eBPF fd and in this
255 * case, everything is 0. It is guaranteed that no such map exists
256 * since map type of 0 is unloadable BPF_MAP_TYPE_UNSPEC.
257 */
91d88eeb 258 if (!memcmp(&tmp, &zero, length))
9e607f2e
DB
259 return 0;
260
261 fprintf(stderr, "Map specs from pinned file differ!\n");
262 return -EINVAL;
263 }
264}
265
91d88eeb
DB
266static int bpf_mnt_fs(const char *target)
267{
268 bool bind_done = false;
269
270 while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
271 if (errno != EINVAL || bind_done) {
272 fprintf(stderr, "mount --make-private %s failed: %s\n",
273 target, strerror(errno));
274 return -1;
275 }
276
277 if (mount(target, target, "none", MS_BIND, NULL)) {
278 fprintf(stderr, "mount --bind %s %s failed: %s\n",
279 target, target, strerror(errno));
280 return -1;
281 }
282
283 bind_done = true;
284 }
285
286 if (mount("bpf", target, "bpf", 0, NULL)) {
287 fprintf(stderr, "mount -t bpf bpf %s failed: %s\n",
288 target, strerror(errno));
289 return -1;
290 }
291
292 return 0;
293}
294
32e93fb7
DB
295static int bpf_valid_mntpt(const char *mnt, unsigned long magic)
296{
297 struct statfs st_fs;
298
299 if (statfs(mnt, &st_fs) < 0)
300 return -ENOENT;
301 if ((unsigned long)st_fs.f_type != magic)
302 return -ENOENT;
303
304 return 0;
305}
306
307static const char *bpf_find_mntpt(const char *fstype, unsigned long magic,
308 char *mnt, int len,
309 const char * const *known_mnts)
310{
311 const char * const *ptr;
312 char type[100];
313 FILE *fp;
314
315 if (known_mnts) {
316 ptr = known_mnts;
317 while (*ptr) {
318 if (bpf_valid_mntpt(*ptr, magic) == 0) {
319 strncpy(mnt, *ptr, len - 1);
320 mnt[len - 1] = 0;
321 return mnt;
322 }
323 ptr++;
324 }
325 }
326
327 fp = fopen("/proc/mounts", "r");
328 if (fp == NULL || len != PATH_MAX)
329 return NULL;
330
331 while (fscanf(fp, "%*s %" textify(PATH_MAX) "s %99s %*s %*d %*d\n",
332 mnt, type) == 2) {
333 if (strcmp(type, fstype) == 0)
334 break;
335 }
336
337 fclose(fp);
338 if (strcmp(type, fstype) != 0)
339 return NULL;
340
341 return mnt;
342}
343
344int bpf_trace_pipe(void)
345{
346 char tracefs_mnt[PATH_MAX] = TRACE_DIR_MNT;
347 static const char * const tracefs_known_mnts[] = {
348 TRACE_DIR_MNT,
349 "/sys/kernel/debug/tracing",
350 "/tracing",
351 "/trace",
352 0,
353 };
354 char tpipe[PATH_MAX];
355 const char *mnt;
356 int fd;
357
358 mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt,
359 sizeof(tracefs_mnt), tracefs_known_mnts);
360 if (!mnt) {
361 fprintf(stderr, "tracefs not mounted?\n");
362 return -1;
363 }
364
365 snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt);
366
367 fd = open(tpipe, O_RDONLY);
368 if (fd < 0)
369 return -1;
370
371 fprintf(stderr, "Running! Hang up with ^C!\n\n");
372 while (1) {
373 static char buff[4096];
374 ssize_t ret;
375
376 ret = read(fd, buff, sizeof(buff) - 1);
377 if (ret > 0) {
378 write(2, buff, ret);
379 fflush(stderr);
380 }
381 }
382
383 return 0;
384}
385
91d88eeb
DB
386static const char *bpf_get_tc_dir(void)
387{
388 static bool bpf_mnt_cached = false;
389 static char bpf_tc_dir[PATH_MAX];
390 static const char *mnt;
391 static const char * const bpf_known_mnts[] = {
392 BPF_DIR_MNT,
393 0,
394 };
395 char bpf_mnt[PATH_MAX] = BPF_DIR_MNT;
396 char bpf_glo_dir[PATH_MAX];
397 int ret;
398
399 if (bpf_mnt_cached)
400 goto done;
401
402 mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_mnt, sizeof(bpf_mnt),
403 bpf_known_mnts);
404 if (!mnt) {
405 mnt = getenv(BPF_ENV_MNT);
406 if (!mnt)
407 mnt = BPF_DIR_MNT;
408 ret = bpf_mnt_fs(mnt);
409 if (ret) {
410 mnt = NULL;
411 goto out;
412 }
413 }
414
415 snprintf(bpf_tc_dir, sizeof(bpf_tc_dir), "%s/%s", mnt, BPF_DIR_TC);
416 ret = mkdir(bpf_tc_dir, S_IRWXU);
417 if (ret && errno != EEXIST) {
418 fprintf(stderr, "mkdir %s failed: %s\n", bpf_tc_dir,
419 strerror(errno));
420 mnt = NULL;
421 goto out;
422 }
423
424 snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s",
425 bpf_tc_dir, BPF_DIR_GLOBALS);
426 ret = mkdir(bpf_glo_dir, S_IRWXU);
427 if (ret && errno != EEXIST) {
428 fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir,
429 strerror(errno));
430 mnt = NULL;
431 goto out;
432 }
433
434 mnt = bpf_tc_dir;
435out:
436 bpf_mnt_cached = true;
437done:
438 return mnt;
439}
440
441static int bpf_obj_get(const char *pathname)
442{
443 union bpf_attr attr;
444 char tmp[PATH_MAX];
445
446 if (strlen(pathname) > 2 && pathname[0] == 'm' &&
447 pathname[1] == ':' && bpf_get_tc_dir()) {
448 snprintf(tmp, sizeof(tmp), "%s/%s",
449 bpf_get_tc_dir(), pathname + 2);
450 pathname = tmp;
451 }
452
453 memset(&attr, 0, sizeof(attr));
454 attr.pathname = bpf_ptr_to_u64(pathname);
455
456 return bpf(BPF_OBJ_GET, &attr, sizeof(attr));
457}
458
6256f8c9 459const char *bpf_default_section(const enum bpf_prog_type type)
11c39b5e
DB
460{
461 switch (type) {
462 case BPF_PROG_TYPE_SCHED_CLS:
463 return ELF_SECTION_CLASSIFIER;
6256f8c9
DB
464 case BPF_PROG_TYPE_SCHED_ACT:
465 return ELF_SECTION_ACTION;
11c39b5e
DB
466 default:
467 return NULL;
468 }
469}
470
91d88eeb
DB
471enum bpf_mode {
472 CBPF_BYTECODE = 0,
473 CBPF_FILE,
474 EBPF_OBJECT,
475 EBPF_PINNED,
476 __BPF_MODE_MAX,
477#define BPF_MODE_MAX __BPF_MODE_MAX
478};
479
480static int bpf_parse(int *ptr_argc, char ***ptr_argv, const bool *opt_tbl,
481 enum bpf_prog_type *type, enum bpf_mode *mode,
482 const char **ptr_object, const char **ptr_section,
483 const char **ptr_uds_name, struct sock_filter *opcodes)
32e93fb7 484{
32e93fb7 485 const char *file, *section, *uds_name;
32e93fb7 486 bool verbose = false;
91d88eeb
DB
487 int ret, argc;
488 char **argv;
489
490 argv = *ptr_argv;
491 argc = *ptr_argc;
492
493 if (opt_tbl[CBPF_BYTECODE] &&
494 (matches(*argv, "bytecode") == 0 ||
495 strcmp(*argv, "bc") == 0)) {
496 *mode = CBPF_BYTECODE;
497 } else if (opt_tbl[CBPF_FILE] &&
498 (matches(*argv, "bytecode-file") == 0 ||
499 strcmp(*argv, "bcf") == 0)) {
500 *mode = CBPF_FILE;
501 } else if (opt_tbl[EBPF_OBJECT] &&
502 (matches(*argv, "object-file") == 0 ||
503 strcmp(*argv, "obj") == 0)) {
504 *mode = EBPF_OBJECT;
505 } else if (opt_tbl[EBPF_PINNED] &&
506 (matches(*argv, "object-pinned") == 0 ||
507 matches(*argv, "pinned") == 0 ||
508 matches(*argv, "fd") == 0)) {
509 *mode = EBPF_PINNED;
32e93fb7
DB
510 } else {
511 fprintf(stderr, "What mode is \"%s\"?\n", *argv);
512 return -1;
513 }
514
515 NEXT_ARG();
516 file = section = uds_name = NULL;
91d88eeb 517 if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) {
32e93fb7
DB
518 file = *argv;
519 NEXT_ARG_FWD();
520
91d88eeb
DB
521 if (*type == BPF_PROG_TYPE_UNSPEC) {
522 if (argc > 0 && matches(*argv, "type") == 0) {
523 NEXT_ARG();
524 if (matches(*argv, "cls") == 0) {
525 *type = BPF_PROG_TYPE_SCHED_CLS;
526 } else if (matches(*argv, "act") == 0) {
527 *type = BPF_PROG_TYPE_SCHED_ACT;
528 } else {
529 fprintf(stderr, "What type is \"%s\"?\n",
530 *argv);
531 return -1;
532 }
533 NEXT_ARG_FWD();
534 } else {
535 *type = BPF_PROG_TYPE_SCHED_CLS;
536 }
537 }
538
539 section = bpf_default_section(*type);
32e93fb7
DB
540 if (argc > 0 && matches(*argv, "section") == 0) {
541 NEXT_ARG();
542 section = *argv;
543 NEXT_ARG_FWD();
544 }
545
546 uds_name = getenv(BPF_ENV_UDS);
547 if (argc > 0 && !uds_name &&
548 matches(*argv, "export") == 0) {
549 NEXT_ARG();
550 uds_name = *argv;
551 NEXT_ARG_FWD();
552 }
553
554 if (argc > 0 && matches(*argv, "verbose") == 0) {
555 verbose = true;
556 NEXT_ARG_FWD();
557 }
558
559 PREV_ARG();
560 }
561
91d88eeb
DB
562 if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE)
563 ret = bpf_ops_parse(argc, argv, opcodes, *mode == CBPF_FILE);
564 else if (*mode == EBPF_OBJECT)
565 ret = bpf_obj_open(file, *type, section, verbose);
566 else if (*mode == EBPF_PINNED)
32e93fb7 567 ret = bpf_obj_get(file);
91d88eeb 568 else
32e93fb7
DB
569 return -1;
570
91d88eeb
DB
571 if (ptr_object)
572 *ptr_object = file;
573 if (ptr_section)
574 *ptr_section = section;
575 if (ptr_uds_name)
576 *ptr_uds_name = uds_name;
577
578 *ptr_argc = argc;
579 *ptr_argv = argv;
580
581 return ret;
582}
583
584int bpf_parse_common(int *ptr_argc, char ***ptr_argv, const int *nla_tbl,
585 enum bpf_prog_type type, const char **ptr_object,
586 const char **ptr_uds_name, struct nlmsghdr *n)
587{
588 struct sock_filter opcodes[BPF_MAXINSNS];
589 const bool opt_tbl[BPF_MODE_MAX] = {
590 [CBPF_BYTECODE] = true,
591 [CBPF_FILE] = true,
592 [EBPF_OBJECT] = true,
593 [EBPF_PINNED] = true,
594 };
595 char annotation[256];
596 const char *section;
597 enum bpf_mode mode;
598 int ret;
599
600 ret = bpf_parse(ptr_argc, ptr_argv, opt_tbl, &type, &mode,
601 ptr_object, &section, ptr_uds_name, opcodes);
602 if (ret < 0)
603 return ret;
604
32e93fb7
DB
605 if (mode == CBPF_BYTECODE || mode == CBPF_FILE) {
606 addattr16(n, MAX_MSG, nla_tbl[BPF_NLA_OPS_LEN], ret);
607 addattr_l(n, MAX_MSG, nla_tbl[BPF_NLA_OPS], opcodes,
608 ret * sizeof(struct sock_filter));
91d88eeb
DB
609 }
610
611 if (mode == EBPF_OBJECT || mode == EBPF_PINNED) {
32e93fb7 612 snprintf(annotation, sizeof(annotation), "%s:[%s]",
91d88eeb
DB
613 basename(*ptr_object), mode == EBPF_PINNED ?
614 "*fsobj" : section);
32e93fb7
DB
615
616 addattr32(n, MAX_MSG, nla_tbl[BPF_NLA_FD], ret);
617 addattrstrz(n, MAX_MSG, nla_tbl[BPF_NLA_NAME], annotation);
618 }
619
91d88eeb
DB
620 return 0;
621}
32e93fb7 622
91d88eeb
DB
623int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
624{
625 enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC;
626 const bool opt_tbl[BPF_MODE_MAX] = {
627 [CBPF_BYTECODE] = false,
628 [CBPF_FILE] = false,
629 [EBPF_OBJECT] = true,
630 [EBPF_PINNED] = true,
631 };
632 const struct bpf_elf_map test = {
633 .type = BPF_MAP_TYPE_PROG_ARRAY,
634 .size_key = sizeof(int),
635 .size_value = sizeof(int),
636 };
637 int ret, prog_fd, map_fd;
638 const char *section;
639 enum bpf_mode mode;
640 uint32_t map_key;
641
642 prog_fd = bpf_parse(&argc, &argv, opt_tbl, &type, &mode,
643 NULL, &section, NULL, NULL);
644 if (prog_fd < 0)
645 return prog_fd;
646 if (key) {
647 map_key = *key;
648 } else {
649 ret = sscanf(section, "%*i/%i", &map_key);
650 if (ret != 1) {
651 fprintf(stderr, "Couldn\'t infer map key from section "
652 "name! Please provide \'key\' argument!\n");
653 ret = -EINVAL;
654 goto out_prog;
655 }
656 }
32e93fb7 657
91d88eeb
DB
658 map_fd = bpf_obj_get(map_path);
659 if (map_fd < 0) {
660 fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
661 map_path, strerror(errno));
662 ret = map_fd;
663 goto out_prog;
664 }
665
666 ret = bpf_map_selfcheck_pinned(map_fd, &test,
667 offsetof(struct bpf_elf_map, max_elem));
668 if (ret < 0) {
669 fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
670 goto out_map;
671 }
672
673 ret = bpf_map_update(map_fd, &map_key, &prog_fd, BPF_ANY);
674 if (ret < 0)
675 fprintf(stderr, "Map update failed: %s\n", strerror(errno));
676out_map:
677 close(map_fd);
678out_prog:
679 close(prog_fd);
680 return ret;
32e93fb7
DB
681}
682
6256f8c9 683#ifdef HAVE_ELF
32e93fb7
DB
684struct bpf_elf_prog {
685 enum bpf_prog_type type;
686 const struct bpf_insn *insns;
687 size_t size;
688 const char *license;
689};
690
f6793eec
DB
691struct bpf_hash_entry {
692 unsigned int pinning;
693 const char *subpath;
694 struct bpf_hash_entry *next;
695};
696
32e93fb7
DB
697struct bpf_elf_ctx {
698 Elf *elf_fd;
699 GElf_Ehdr elf_hdr;
700 Elf_Data *sym_tab;
701 Elf_Data *str_tab;
702 int obj_fd;
703 int map_fds[ELF_MAX_MAPS];
704 struct bpf_elf_map maps[ELF_MAX_MAPS];
705 int sym_num;
706 int map_num;
707 bool *sec_done;
708 int sec_maps;
709 char license[ELF_MAX_LICENSE_LEN];
710 enum bpf_prog_type type;
711 bool verbose;
712 struct bpf_elf_st stat;
f6793eec 713 struct bpf_hash_entry *ht[256];
f31645d1
DB
714 char *log;
715 size_t log_size;
32e93fb7
DB
716};
717
6256f8c9 718struct bpf_elf_sec_data {
32e93fb7
DB
719 GElf_Shdr sec_hdr;
720 Elf_Data *sec_data;
721 const char *sec_name;
6256f8c9
DB
722};
723
724struct bpf_map_data {
32e93fb7
DB
725 int *fds;
726 const char *obj;
727 struct bpf_elf_st *st;
728 struct bpf_elf_map *ent;
6256f8c9
DB
729};
730
f31645d1
DB
731static __check_format_string(2, 3) void
732bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...)
11c39b5e
DB
733{
734 va_list vl;
735
736 va_start(vl, format);
737 vfprintf(stderr, format, vl);
738 va_end(vl);
739
f31645d1
DB
740 if (ctx->log && ctx->log[0]) {
741 fprintf(stderr, "%s\n", ctx->log);
742 memset(ctx->log, 0, ctx->log_size);
743 }
744}
745
746static int bpf_log_realloc(struct bpf_elf_ctx *ctx)
747{
748 size_t log_size = ctx->log_size;
749 void *ptr;
750
751 if (!ctx->log) {
752 log_size = 65536;
753 } else {
754 log_size <<= 1;
755 if (log_size > (UINT_MAX >> 8))
756 return -EINVAL;
d937a74b 757 }
f31645d1
DB
758
759 ptr = realloc(ctx->log, log_size);
760 if (!ptr)
761 return -ENOMEM;
762
763 ctx->log = ptr;
764 ctx->log_size = log_size;
765
766 return 0;
11c39b5e
DB
767}
768
32e93fb7 769static int bpf_map_create(enum bpf_map_type type, unsigned int size_key,
11c39b5e
DB
770 unsigned int size_value, unsigned int max_elem)
771{
67584e3a
ND
772 union bpf_attr attr;
773
774 memset(&attr, 0, sizeof(attr));
775 attr.map_type = type;
776 attr.key_size = size_key;
777 attr.value_size = size_value;
778 attr.max_entries = max_elem;
11c39b5e
DB
779
780 return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
781}
782
783static int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
f31645d1
DB
784 size_t size_insns, const char *license, char *log,
785 size_t size_log)
11c39b5e 786{
67584e3a
ND
787 union bpf_attr attr;
788
789 memset(&attr, 0, sizeof(attr));
790 attr.prog_type = type;
791 attr.insns = bpf_ptr_to_u64(insns);
f31645d1 792 attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
67584e3a 793 attr.license = bpf_ptr_to_u64(license);
11c39b5e 794
f31645d1
DB
795 if (size_log > 0) {
796 attr.log_buf = bpf_ptr_to_u64(log);
797 attr.log_size = size_log;
798 attr.log_level = 1;
32e93fb7
DB
799 }
800
11c39b5e
DB
801 return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
802}
803
32e93fb7 804static int bpf_obj_pin(int fd, const char *pathname)
11c39b5e 805{
67584e3a
ND
806 union bpf_attr attr;
807
808 memset(&attr, 0, sizeof(attr));
809 attr.pathname = bpf_ptr_to_u64(pathname);
810 attr.bpf_fd = fd;
32e93fb7
DB
811
812 return bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
813}
11c39b5e 814
32e93fb7
DB
815static int bpf_obj_hash(const char *object, uint8_t *out, size_t len)
816{
817 struct sockaddr_alg alg = {
818 .salg_family = AF_ALG,
819 .salg_type = "hash",
820 .salg_name = "sha1",
821 };
822 int ret, cfd, ofd, ffd;
823 struct stat stbuff;
824 ssize_t size;
825
826 if (!object || len != 20)
827 return -EINVAL;
828
829 cfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
830 if (cfd < 0) {
831 fprintf(stderr, "Cannot get AF_ALG socket: %s\n",
832 strerror(errno));
833 return cfd;
834 }
835
836 ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg));
837 if (ret < 0) {
838 fprintf(stderr, "Error binding socket: %s\n", strerror(errno));
839 goto out_cfd;
840 }
841
842 ofd = accept(cfd, NULL, 0);
843 if (ofd < 0) {
844 fprintf(stderr, "Error accepting socket: %s\n",
845 strerror(errno));
846 ret = ofd;
847 goto out_cfd;
848 }
849
850 ffd = open(object, O_RDONLY);
851 if (ffd < 0) {
852 fprintf(stderr, "Error opening object %s: %s\n",
853 object, strerror(errno));
854 ret = ffd;
855 goto out_ofd;
856 }
857
858 ret = fstat(ffd, &stbuff);
859 if (ret < 0) {
860 fprintf(stderr, "Error doing fstat: %s\n",
861 strerror(errno));
862 goto out_ffd;
d937a74b 863 }
11c39b5e 864
32e93fb7
DB
865 size = sendfile(ofd, ffd, NULL, stbuff.st_size);
866 if (size != stbuff.st_size) {
867 fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n",
868 size, stbuff.st_size, strerror(errno));
869 ret = -1;
870 goto out_ffd;
871 }
872
873 size = read(ofd, out, len);
874 if (size != len) {
875 fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n",
876 size, len, strerror(errno));
877 ret = -1;
878 } else {
879 ret = 0;
880 }
881out_ffd:
882 close(ffd);
883out_ofd:
884 close(ofd);
885out_cfd:
886 close(cfd);
887 return ret;
11c39b5e
DB
888}
889
32e93fb7 890static const char *bpf_get_obj_uid(const char *pathname)
11c39b5e 891{
32e93fb7
DB
892 static bool bpf_uid_cached = false;
893 static char bpf_uid[64];
894 uint8_t tmp[20];
895 int ret;
11c39b5e 896
32e93fb7
DB
897 if (bpf_uid_cached)
898 goto done;
11c39b5e 899
32e93fb7
DB
900 ret = bpf_obj_hash(pathname, tmp, sizeof(tmp));
901 if (ret) {
902 fprintf(stderr, "Object hashing failed!\n");
903 return NULL;
904 }
905
906 hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid));
907 bpf_uid_cached = true;
908done:
909 return bpf_uid;
11c39b5e
DB
910}
911
32e93fb7
DB
912static int bpf_init_env(const char *pathname)
913{
914 struct rlimit limit = {
915 .rlim_cur = RLIM_INFINITY,
916 .rlim_max = RLIM_INFINITY,
917 };
918
919 /* Don't bother in case we fail! */
920 setrlimit(RLIMIT_MEMLOCK, &limit);
921
922 if (!bpf_get_tc_dir()) {
923 fprintf(stderr, "Continuing without mounted eBPF fs. "
924 "Too old kernel?\n");
925 return 0;
926 }
927
928 if (!bpf_get_obj_uid(pathname))
929 return -1;
930
931 return 0;
6256f8c9
DB
932}
933
f6793eec
DB
934static const char *bpf_custom_pinning(const struct bpf_elf_ctx *ctx,
935 uint32_t pinning)
936{
937 struct bpf_hash_entry *entry;
938
939 entry = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)];
940 while (entry && entry->pinning != pinning)
941 entry = entry->next;
942
943 return entry ? entry->subpath : NULL;
944}
945
946static bool bpf_no_pinning(const struct bpf_elf_ctx *ctx,
947 uint32_t pinning)
11c39b5e 948{
32e93fb7
DB
949 switch (pinning) {
950 case PIN_OBJECT_NS:
951 case PIN_GLOBAL_NS:
952 return false;
953 case PIN_NONE:
32e93fb7 954 return true;
f6793eec
DB
955 default:
956 return !bpf_custom_pinning(ctx, pinning);
32e93fb7
DB
957 }
958}
959
960static void bpf_make_pathname(char *pathname, size_t len, const char *name,
f6793eec 961 const struct bpf_elf_ctx *ctx, uint32_t pinning)
32e93fb7
DB
962{
963 switch (pinning) {
964 case PIN_OBJECT_NS:
965 snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(),
966 bpf_get_obj_uid(NULL), name);
967 break;
968 case PIN_GLOBAL_NS:
969 snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(),
970 BPF_DIR_GLOBALS, name);
971 break;
f6793eec
DB
972 default:
973 snprintf(pathname, len, "%s/../%s/%s", bpf_get_tc_dir(),
974 bpf_custom_pinning(ctx, pinning), name);
975 break;
32e93fb7
DB
976 }
977}
978
f6793eec
DB
979static int bpf_probe_pinned(const char *name, const struct bpf_elf_ctx *ctx,
980 uint32_t pinning)
32e93fb7
DB
981{
982 char pathname[PATH_MAX];
983
f6793eec 984 if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir())
32e93fb7
DB
985 return 0;
986
f6793eec 987 bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning);
32e93fb7
DB
988 return bpf_obj_get(pathname);
989}
990
f6793eec 991static int bpf_make_obj_path(void)
32e93fb7 992{
f6793eec 993 char tmp[PATH_MAX];
32e93fb7
DB
994 int ret;
995
f6793eec
DB
996 snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_tc_dir(),
997 bpf_get_obj_uid(NULL));
998
999 ret = mkdir(tmp, S_IRWXU);
1000 if (ret && errno != EEXIST) {
1001 fprintf(stderr, "mkdir %s failed: %s\n", tmp, strerror(errno));
1002 return ret;
1003 }
1004
1005 return 0;
1006}
1007
1008static int bpf_make_custom_path(const char *todo)
1009{
1010 char tmp[PATH_MAX], rem[PATH_MAX], *sub;
1011 int ret;
1012
1013 snprintf(tmp, sizeof(tmp), "%s/../", bpf_get_tc_dir());
1014 snprintf(rem, sizeof(rem), "%s/", todo);
1015 sub = strtok(rem, "/");
32e93fb7 1016
f6793eec
DB
1017 while (sub) {
1018 if (strlen(tmp) + strlen(sub) + 2 > PATH_MAX)
1019 return -EINVAL;
1020
1021 strcat(tmp, sub);
1022 strcat(tmp, "/");
32e93fb7 1023
f6793eec 1024 ret = mkdir(tmp, S_IRWXU);
32e93fb7 1025 if (ret && errno != EEXIST) {
f6793eec 1026 fprintf(stderr, "mkdir %s failed: %s\n", tmp,
32e93fb7
DB
1027 strerror(errno));
1028 return ret;
1029 }
f6793eec
DB
1030
1031 sub = strtok(NULL, "/");
32e93fb7
DB
1032 }
1033
f6793eec
DB
1034 return 0;
1035}
1036
1037static int bpf_place_pinned(int fd, const char *name,
1038 const struct bpf_elf_ctx *ctx, uint32_t pinning)
1039{
1040 char pathname[PATH_MAX];
1041 const char *tmp;
1042 int ret = 0;
1043
1044 if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir())
1045 return 0;
1046
1047 if (pinning == PIN_OBJECT_NS)
1048 ret = bpf_make_obj_path();
1049 else if ((tmp = bpf_custom_pinning(ctx, pinning)))
1050 ret = bpf_make_custom_path(tmp);
1051 if (ret < 0)
1052 return ret;
1053
1054 bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning);
32e93fb7
DB
1055 return bpf_obj_pin(fd, pathname);
1056}
1057
f31645d1
DB
1058static void bpf_prog_report(int fd, const char *section,
1059 const struct bpf_elf_prog *prog,
1060 struct bpf_elf_ctx *ctx)
32e93fb7 1061{
f31645d1
DB
1062 fprintf(stderr, "Prog section \'%s\' %s%s (%d)!\n", section,
1063 fd < 0 ? "rejected: " : "loaded",
1064 fd < 0 ? strerror(errno) : "",
1065 fd < 0 ? errno : fd);
1066
1067 fprintf(stderr, " - Type: %u\n", prog->type);
1068 fprintf(stderr, " - Instructions: %zu\n",
1069 prog->size / sizeof(struct bpf_insn));
1070 fprintf(stderr, " - License: %s\n\n", prog->license);
1071
1072 bpf_dump_error(ctx, "Verifier analysis:\n\n");
1073}
32e93fb7 1074
f31645d1
DB
1075static int bpf_prog_attach(const char *section,
1076 const struct bpf_elf_prog *prog,
1077 struct bpf_elf_ctx *ctx)
1078{
1079 int tries = 0, fd;
1080retry:
32e93fb7
DB
1081 errno = 0;
1082 fd = bpf_prog_load(prog->type, prog->insns, prog->size,
f31645d1
DB
1083 prog->license, ctx->log, ctx->log_size);
1084 if (fd < 0 || ctx->verbose) {
1085 /* The verifier log is pretty chatty, sometimes so chatty
1086 * on larger programs, that we could fail to dump everything
1087 * into our buffer. Still, try to give a debuggable error
1088 * log for the user, so enlarge it and re-fail.
1089 */
1090 if (fd < 0 && (errno == ENOSPC || !ctx->log_size)) {
1091 if (tries++ < 6 && !bpf_log_realloc(ctx))
1092 goto retry;
1093
1094 fprintf(stderr, "Log buffer too small to dump "
1095 "verifier log %zu bytes (%d tries)!\n",
1096 ctx->log_size, tries);
1097 return fd;
1098 }
1099
1100 bpf_prog_report(fd, section, prog, ctx);
32e93fb7
DB
1101 }
1102
1103 return fd;
1104}
1105
f31645d1
DB
1106static void bpf_map_report(int fd, const char *name,
1107 const struct bpf_elf_map *map,
1108 struct bpf_elf_ctx *ctx)
1109{
1110 fprintf(stderr, "Map object \'%s\' %s%s (%d)!\n", name,
1111 fd < 0 ? "rejected: " : "loaded",
1112 fd < 0 ? strerror(errno) : "",
1113 fd < 0 ? errno : fd);
1114
1115 fprintf(stderr, " - Type: %u\n", map->type);
1116 fprintf(stderr, " - Identifier: %u\n", map->id);
1117 fprintf(stderr, " - Pinning: %u\n", map->pinning);
1118 fprintf(stderr, " - Size key: %u\n", map->size_key);
1119 fprintf(stderr, " - Size value: %u\n", map->size_value);
1120 fprintf(stderr, " - Max elems: %u\n\n", map->max_elem);
1121}
1122
32e93fb7 1123static int bpf_map_attach(const char *name, const struct bpf_elf_map *map,
f31645d1 1124 struct bpf_elf_ctx *ctx)
32e93fb7
DB
1125{
1126 int fd, ret;
1127
f6793eec 1128 fd = bpf_probe_pinned(name, ctx, map->pinning);
32e93fb7 1129 if (fd > 0) {
91d88eeb
DB
1130 ret = bpf_map_selfcheck_pinned(fd, map,
1131 offsetof(struct bpf_elf_map,
1132 id));
9e607f2e
DB
1133 if (ret < 0) {
1134 close(fd);
1135 fprintf(stderr, "Map \'%s\' self-check failed!\n",
1136 name);
1137 return ret;
1138 }
f31645d1 1139 if (ctx->verbose)
32e93fb7
DB
1140 fprintf(stderr, "Map \'%s\' loaded as pinned!\n",
1141 name);
1142 return fd;
1143 }
1144
1145 errno = 0;
1146 fd = bpf_map_create(map->type, map->size_key, map->size_value,
1147 map->max_elem);
f31645d1
DB
1148 if (fd < 0 || ctx->verbose) {
1149 bpf_map_report(fd, name, map, ctx);
32e93fb7
DB
1150 if (fd < 0)
1151 return fd;
1152 }
1153
f6793eec 1154 ret = bpf_place_pinned(fd, name, ctx, map->pinning);
32e93fb7
DB
1155 if (ret < 0 && errno != EEXIST) {
1156 fprintf(stderr, "Could not pin %s map: %s\n", name,
1157 strerror(errno));
1158 close(fd);
1159 return ret;
1160 }
1161
1162 return fd;
1163}
1164
32e93fb7
DB
1165static const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx,
1166 const GElf_Sym *sym)
1167{
1168 return ctx->str_tab->d_buf + sym->st_name;
1169}
1170
1171static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which)
1172{
1173 GElf_Sym sym;
11c39b5e
DB
1174 int i;
1175
32e93fb7
DB
1176 for (i = 0; i < ctx->sym_num; i++) {
1177 if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
1178 continue;
1179
5230a2ed
DB
1180 if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
1181 GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
32e93fb7
DB
1182 sym.st_shndx != ctx->sec_maps ||
1183 sym.st_value / sizeof(struct bpf_elf_map) != which)
1184 continue;
1185
1186 return bpf_str_tab_name(ctx, &sym);
11c39b5e 1187 }
32e93fb7
DB
1188
1189 return NULL;
11c39b5e
DB
1190}
1191
32e93fb7 1192static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx)
11c39b5e 1193{
32e93fb7
DB
1194 const char *map_name;
1195 int i, fd;
11c39b5e 1196
32e93fb7
DB
1197 for (i = 0; i < ctx->map_num; i++) {
1198 map_name = bpf_map_fetch_name(ctx, i);
1199 if (!map_name)
1200 return -EIO;
11c39b5e 1201
f31645d1 1202 fd = bpf_map_attach(map_name, &ctx->maps[i], ctx);
32e93fb7
DB
1203 if (fd < 0)
1204 return fd;
11c39b5e 1205
32e93fb7 1206 ctx->map_fds[i] = fd;
11c39b5e
DB
1207 }
1208
1209 return 0;
11c39b5e
DB
1210}
1211
32e93fb7
DB
1212static int bpf_fill_section_data(struct bpf_elf_ctx *ctx, int section,
1213 struct bpf_elf_sec_data *data)
11c39b5e 1214{
32e93fb7 1215 Elf_Data *sec_edata;
11c39b5e
DB
1216 GElf_Shdr sec_hdr;
1217 Elf_Scn *sec_fd;
11c39b5e
DB
1218 char *sec_name;
1219
32e93fb7 1220 memset(data, 0, sizeof(*data));
11c39b5e 1221
32e93fb7 1222 sec_fd = elf_getscn(ctx->elf_fd, section);
11c39b5e
DB
1223 if (!sec_fd)
1224 return -EINVAL;
11c39b5e
DB
1225 if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr)
1226 return -EIO;
1227
32e93fb7 1228 sec_name = elf_strptr(ctx->elf_fd, ctx->elf_hdr.e_shstrndx,
11c39b5e
DB
1229 sec_hdr.sh_name);
1230 if (!sec_name || !sec_hdr.sh_size)
1231 return -ENOENT;
1232
1233 sec_edata = elf_getdata(sec_fd, NULL);
1234 if (!sec_edata || elf_getdata(sec_fd, sec_edata))
1235 return -EIO;
1236
32e93fb7 1237 memcpy(&data->sec_hdr, &sec_hdr, sizeof(sec_hdr));
11c39b5e 1238
32e93fb7
DB
1239 data->sec_name = sec_name;
1240 data->sec_data = sec_edata;
11c39b5e
DB
1241 return 0;
1242}
1243
32e93fb7
DB
1244static int bpf_fetch_maps(struct bpf_elf_ctx *ctx, int section,
1245 struct bpf_elf_sec_data *data)
11c39b5e 1246{
32e93fb7
DB
1247 if (data->sec_data->d_size % sizeof(struct bpf_elf_map) != 0)
1248 return -EINVAL;
11c39b5e 1249
32e93fb7
DB
1250 ctx->map_num = data->sec_data->d_size / sizeof(struct bpf_elf_map);
1251 ctx->sec_maps = section;
1252 ctx->sec_done[section] = true;
11c39b5e 1253
32e93fb7
DB
1254 if (ctx->map_num > ARRAY_SIZE(ctx->map_fds)) {
1255 fprintf(stderr, "Too many BPF maps in ELF section!\n");
1256 return -ENOMEM;
1257 }
11c39b5e 1258
32e93fb7
DB
1259 memcpy(ctx->maps, data->sec_data->d_buf, data->sec_data->d_size);
1260 return 0;
1261}
11c39b5e 1262
32e93fb7
DB
1263static int bpf_fetch_license(struct bpf_elf_ctx *ctx, int section,
1264 struct bpf_elf_sec_data *data)
1265{
1266 if (data->sec_data->d_size > sizeof(ctx->license))
1267 return -ENOMEM;
11c39b5e 1268
32e93fb7
DB
1269 memcpy(ctx->license, data->sec_data->d_buf, data->sec_data->d_size);
1270 ctx->sec_done[section] = true;
1271 return 0;
1272}
11c39b5e 1273
32e93fb7
DB
1274static int bpf_fetch_symtab(struct bpf_elf_ctx *ctx, int section,
1275 struct bpf_elf_sec_data *data)
1276{
1277 ctx->sym_tab = data->sec_data;
1278 ctx->sym_num = data->sec_hdr.sh_size / data->sec_hdr.sh_entsize;
1279 ctx->sec_done[section] = true;
11c39b5e
DB
1280 return 0;
1281}
1282
32e93fb7
DB
1283static int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section,
1284 struct bpf_elf_sec_data *data)
11c39b5e 1285{
32e93fb7
DB
1286 ctx->str_tab = data->sec_data;
1287 ctx->sec_done[section] = true;
1288 return 0;
1289}
11c39b5e 1290
32e93fb7
DB
1291static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
1292{
1293 struct bpf_elf_sec_data data;
1294 int i, ret = -1;
11c39b5e 1295
32e93fb7
DB
1296 for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1297 ret = bpf_fill_section_data(ctx, i, &data);
11c39b5e
DB
1298 if (ret < 0)
1299 continue;
1300
cce3d466
DB
1301 if (data.sec_hdr.sh_type == SHT_PROGBITS &&
1302 !strcmp(data.sec_name, ELF_SECTION_MAPS))
32e93fb7 1303 ret = bpf_fetch_maps(ctx, i, &data);
cce3d466
DB
1304 else if (data.sec_hdr.sh_type == SHT_PROGBITS &&
1305 !strcmp(data.sec_name, ELF_SECTION_LICENSE))
32e93fb7 1306 ret = bpf_fetch_license(ctx, i, &data);
cce3d466
DB
1307 else if (data.sec_hdr.sh_type == SHT_SYMTAB &&
1308 !strcmp(data.sec_name, ".symtab"))
32e93fb7
DB
1309 ret = bpf_fetch_symtab(ctx, i, &data);
1310 else if (data.sec_hdr.sh_type == SHT_STRTAB &&
cce3d466 1311 !strcmp(data.sec_name, ".strtab"))
32e93fb7
DB
1312 ret = bpf_fetch_strtab(ctx, i, &data);
1313 if (ret < 0) {
1314 fprintf(stderr, "Error parsing section %d! Perhaps"
1315 "check with readelf -a?\n", i);
1316 break;
11c39b5e 1317 }
32e93fb7
DB
1318 }
1319
1320 if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) {
1321 ret = bpf_maps_attach_all(ctx);
1322 if (ret < 0) {
1323 fprintf(stderr, "Error loading maps into kernel!\n");
1324 return ret;
11c39b5e
DB
1325 }
1326 }
1327
1328 return ret;
1329}
1330
32e93fb7 1331static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section)
11c39b5e 1332{
32e93fb7
DB
1333 struct bpf_elf_sec_data data;
1334 struct bpf_elf_prog prog;
1335 int ret, i, fd = -1;
11c39b5e 1336
32e93fb7
DB
1337 for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1338 if (ctx->sec_done[i])
11c39b5e
DB
1339 continue;
1340
32e93fb7 1341 ret = bpf_fill_section_data(ctx, i, &data);
cce3d466
DB
1342 if (ret < 0 ||
1343 !(data.sec_hdr.sh_type == SHT_PROGBITS &&
1344 data.sec_hdr.sh_flags & SHF_EXECINSTR &&
1345 !strcmp(data.sec_name, section)))
11c39b5e
DB
1346 continue;
1347
32e93fb7
DB
1348 memset(&prog, 0, sizeof(prog));
1349 prog.type = ctx->type;
1350 prog.insns = data.sec_data->d_buf;
1351 prog.size = data.sec_data->d_size;
1352 prog.license = ctx->license;
11c39b5e 1353
f31645d1 1354 fd = bpf_prog_attach(section, &prog, ctx);
32e93fb7 1355 if (fd < 0)
11c39b5e
DB
1356 continue;
1357
32e93fb7 1358 ctx->sec_done[i] = true;
11c39b5e
DB
1359 break;
1360 }
1361
32e93fb7 1362 return fd;
11c39b5e
DB
1363}
1364
32e93fb7
DB
1365static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
1366 struct bpf_elf_sec_data *data_relo,
1367 struct bpf_elf_sec_data *data_insn)
11c39b5e 1368{
32e93fb7
DB
1369 Elf_Data *idata = data_insn->sec_data;
1370 GElf_Shdr *rhdr = &data_relo->sec_hdr;
1371 int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize;
1372 struct bpf_insn *insns = idata->d_buf;
1373 unsigned int num_insns = idata->d_size / sizeof(*insns);
11c39b5e 1374
32e93fb7
DB
1375 for (relo_ent = 0; relo_ent < relo_num; relo_ent++) {
1376 unsigned int ioff, rmap;
1377 GElf_Rel relo;
1378 GElf_Sym sym;
1379
1380 if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo)
1381 return -EIO;
1382
1383 ioff = relo.r_offset / sizeof(struct bpf_insn);
1384 if (ioff >= num_insns ||
a576c6b9
DB
1385 insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) {
1386 fprintf(stderr, "ELF contains relo data for non ld64 "
1387 "instruction at offset %u! Compiler bug?!\n",
1388 ioff);
1389 if (ioff < num_insns &&
1390 insns[ioff].code == (BPF_JMP | BPF_CALL))
1391 fprintf(stderr, " - Try to annotate functions "
1392 "with always_inline attribute!\n");
32e93fb7 1393 return -EINVAL;
a576c6b9 1394 }
32e93fb7
DB
1395
1396 if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym)
1397 return -EIO;
2486337a
DB
1398 if (sym.st_shndx != ctx->sec_maps) {
1399 fprintf(stderr, "ELF contains non-map related relo data in "
1400 "entry %u pointing to section %u! Compiler bug?!\n",
1401 relo_ent, sym.st_shndx);
1402 return -EIO;
1403 }
32e93fb7
DB
1404
1405 rmap = sym.st_value / sizeof(struct bpf_elf_map);
1406 if (rmap >= ARRAY_SIZE(ctx->map_fds))
1407 return -EINVAL;
1408 if (!ctx->map_fds[rmap])
1409 return -EINVAL;
1410
1411 if (ctx->verbose)
1412 fprintf(stderr, "Map \'%s\' (%d) injected into prog "
1413 "section \'%s\' at offset %u!\n",
1414 bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap],
1415 data_insn->sec_name, ioff);
11c39b5e 1416
32e93fb7
DB
1417 insns[ioff].src_reg = BPF_PSEUDO_MAP_FD;
1418 insns[ioff].imm = ctx->map_fds[rmap];
1419 }
1420
1421 return 0;
1422}
1423
1424static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section)
1425{
1426 struct bpf_elf_sec_data data_relo, data_insn;
1427 struct bpf_elf_prog prog;
1428 int ret, idx, i, fd = -1;
1429
1430 for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1431 ret = bpf_fill_section_data(ctx, i, &data_relo);
1432 if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL)
11c39b5e
DB
1433 continue;
1434
32e93fb7
DB
1435 idx = data_relo.sec_hdr.sh_info;
1436 ret = bpf_fill_section_data(ctx, idx, &data_insn);
cce3d466
DB
1437 if (ret < 0 ||
1438 !(data_insn.sec_hdr.sh_type == SHT_PROGBITS &&
1439 data_insn.sec_hdr.sh_flags & SHF_EXECINSTR &&
1440 !strcmp(data_insn.sec_name, section)))
11c39b5e 1441 continue;
32e93fb7
DB
1442
1443 ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn);
1444 if (ret < 0)
11c39b5e
DB
1445 continue;
1446
32e93fb7
DB
1447 memset(&prog, 0, sizeof(prog));
1448 prog.type = ctx->type;
1449 prog.insns = data_insn.sec_data->d_buf;
1450 prog.size = data_insn.sec_data->d_size;
1451 prog.license = ctx->license;
1452
f31645d1 1453 fd = bpf_prog_attach(section, &prog, ctx);
32e93fb7 1454 if (fd < 0)
11c39b5e
DB
1455 continue;
1456
32e93fb7
DB
1457 ctx->sec_done[i] = true;
1458 ctx->sec_done[idx] = true;
11c39b5e
DB
1459 break;
1460 }
1461
32e93fb7 1462 return fd;
11c39b5e
DB
1463}
1464
32e93fb7 1465static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section)
473d7840
DB
1466{
1467 int ret = -1;
1468
32e93fb7
DB
1469 if (ctx->sym_tab)
1470 ret = bpf_fetch_prog_relo(ctx, section);
473d7840 1471 if (ret < 0)
32e93fb7
DB
1472 ret = bpf_fetch_prog(ctx, section);
1473
473d7840
DB
1474 return ret;
1475}
1476
910b543d
DB
1477static int bpf_find_map_by_id(struct bpf_elf_ctx *ctx, uint32_t id)
1478{
1479 int i;
1480
1481 for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++)
1482 if (ctx->map_fds[i] && ctx->maps[i].id == id &&
1483 ctx->maps[i].type == BPF_MAP_TYPE_PROG_ARRAY)
1484 return i;
1485 return -1;
1486}
1487
32e93fb7 1488static int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx)
473d7840 1489{
32e93fb7
DB
1490 struct bpf_elf_sec_data data;
1491 uint32_t map_id, key_id;
910b543d 1492 int fd, i, ret, idx;
473d7840 1493
32e93fb7
DB
1494 for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
1495 if (ctx->sec_done[i])
473d7840
DB
1496 continue;
1497
32e93fb7 1498 ret = bpf_fill_section_data(ctx, i, &data);
473d7840
DB
1499 if (ret < 0)
1500 continue;
1501
910b543d
DB
1502 ret = sscanf(data.sec_name, "%i/%i", &map_id, &key_id);
1503 if (ret != 2)
32e93fb7 1504 continue;
910b543d
DB
1505
1506 idx = bpf_find_map_by_id(ctx, map_id);
1507 if (idx < 0)
473d7840
DB
1508 continue;
1509
32e93fb7
DB
1510 fd = bpf_fetch_prog_sec(ctx, data.sec_name);
1511 if (fd < 0)
473d7840
DB
1512 return -EIO;
1513
910b543d
DB
1514 ret = bpf_map_update(ctx->map_fds[idx], &key_id,
1515 &fd, BPF_ANY);
473d7840
DB
1516 if (ret < 0)
1517 return -ENOENT;
1518
32e93fb7 1519 ctx->sec_done[i] = true;
473d7840
DB
1520 }
1521
1522 return 0;
1523}
1524
32e93fb7 1525static void bpf_save_finfo(struct bpf_elf_ctx *ctx)
11c39b5e 1526{
32e93fb7
DB
1527 struct stat st;
1528 int ret;
11c39b5e 1529
32e93fb7 1530 memset(&ctx->stat, 0, sizeof(ctx->stat));
11c39b5e 1531
32e93fb7
DB
1532 ret = fstat(ctx->obj_fd, &st);
1533 if (ret < 0) {
1534 fprintf(stderr, "Stat of elf file failed: %s\n",
1535 strerror(errno));
1536 return;
1537 }
11c39b5e 1538
32e93fb7
DB
1539 ctx->stat.st_dev = st.st_dev;
1540 ctx->stat.st_ino = st.st_ino;
1541}
1542
f6793eec
DB
1543static int bpf_read_pin_mapping(FILE *fp, uint32_t *id, char *path)
1544{
1545 char buff[PATH_MAX];
1546
1547 while (fgets(buff, sizeof(buff), fp)) {
1548 char *ptr = buff;
1549
1550 while (*ptr == ' ' || *ptr == '\t')
1551 ptr++;
1552
1553 if (*ptr == '#' || *ptr == '\n' || *ptr == 0)
1554 continue;
1555
1556 if (sscanf(ptr, "%i %s\n", id, path) != 2 &&
1557 sscanf(ptr, "%i %s #", id, path) != 2) {
1558 strcpy(path, ptr);
1559 return -1;
1560 }
1561
1562 return 1;
1563 }
1564
1565 return 0;
1566}
1567
1568static bool bpf_pinning_reserved(uint32_t pinning)
1569{
1570 switch (pinning) {
1571 case PIN_NONE:
1572 case PIN_OBJECT_NS:
1573 case PIN_GLOBAL_NS:
1574 return true;
1575 default:
1576 return false;
1577 }
1578}
1579
1580static void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
1581{
1582 struct bpf_hash_entry *entry;
1583 char subpath[PATH_MAX];
1584 uint32_t pinning;
1585 FILE *fp;
1586 int ret;
1587
1588 fp = fopen(db_file, "r");
1589 if (!fp)
1590 return;
1591
1592 memset(subpath, 0, sizeof(subpath));
1593 while ((ret = bpf_read_pin_mapping(fp, &pinning, subpath))) {
1594 if (ret == -1) {
1595 fprintf(stderr, "Database %s is corrupted at: %s\n",
1596 db_file, subpath);
1597 fclose(fp);
1598 return;
1599 }
1600
1601 if (bpf_pinning_reserved(pinning)) {
1602 fprintf(stderr, "Database %s, id %u is reserved - "
1603 "ignoring!\n", db_file, pinning);
1604 continue;
1605 }
1606
1607 entry = malloc(sizeof(*entry));
1608 if (!entry) {
1609 fprintf(stderr, "No memory left for db entry!\n");
1610 continue;
1611 }
1612
1613 entry->pinning = pinning;
1614 entry->subpath = strdup(subpath);
1615 if (!entry->subpath) {
1616 fprintf(stderr, "No memory left for db entry!\n");
1617 free(entry);
1618 continue;
1619 }
1620
1621 entry->next = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)];
1622 ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)] = entry;
1623 }
1624
1625 fclose(fp);
1626}
1627
1628static void bpf_hash_destroy(struct bpf_elf_ctx *ctx)
1629{
1630 struct bpf_hash_entry *entry;
1631 int i;
1632
1633 for (i = 0; i < ARRAY_SIZE(ctx->ht); i++) {
1634 while ((entry = ctx->ht[i]) != NULL) {
1635 ctx->ht[i] = entry->next;
1636 free((char *)entry->subpath);
1637 free(entry);
1638 }
1639 }
1640}
1641
8187b012
DB
1642static int bpf_elf_check_ehdr(const struct bpf_elf_ctx *ctx)
1643{
1644 if (ctx->elf_hdr.e_type != ET_REL ||
1645 ctx->elf_hdr.e_machine != 0 ||
1646 ctx->elf_hdr.e_version != EV_CURRENT) {
1647 fprintf(stderr, "ELF format error, ELF file not for eBPF?\n");
1648 return -EINVAL;
1649 }
1650
1651 switch (ctx->elf_hdr.e_ident[EI_DATA]) {
1652 default:
1653 fprintf(stderr, "ELF format error, wrong endianness info?\n");
1654 return -EINVAL;
1655 case ELFDATA2LSB:
1656 if (htons(1) == 1) {
1657 fprintf(stderr,
1658 "We are big endian, eBPF object is little endian!\n");
1659 return -EIO;
1660 }
1661 break;
1662 case ELFDATA2MSB:
1663 if (htons(1) != 1) {
1664 fprintf(stderr,
1665 "We are little endian, eBPF object is big endian!\n");
1666 return -EIO;
1667 }
1668 break;
1669 }
1670
1671 return 0;
1672}
1673
32e93fb7
DB
1674static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
1675 enum bpf_prog_type type, bool verbose)
1676{
1677 int ret = -EINVAL;
1678
1679 if (elf_version(EV_CURRENT) == EV_NONE ||
1680 bpf_init_env(pathname))
1681 return ret;
1682
1683 memset(ctx, 0, sizeof(*ctx));
1684 ctx->verbose = verbose;
1685 ctx->type = type;
1686
1687 ctx->obj_fd = open(pathname, O_RDONLY);
1688 if (ctx->obj_fd < 0)
1689 return ctx->obj_fd;
1690
1691 ctx->elf_fd = elf_begin(ctx->obj_fd, ELF_C_READ, NULL);
1692 if (!ctx->elf_fd) {
11c39b5e 1693 ret = -EINVAL;
32e93fb7 1694 goto out_fd;
11c39b5e
DB
1695 }
1696
8187b012
DB
1697 if (elf_kind(ctx->elf_fd) != ELF_K_ELF) {
1698 ret = -EINVAL;
1699 goto out_fd;
1700 }
1701
32e93fb7
DB
1702 if (gelf_getehdr(ctx->elf_fd, &ctx->elf_hdr) !=
1703 &ctx->elf_hdr) {
11c39b5e
DB
1704 ret = -EIO;
1705 goto out_elf;
1706 }
1707
8187b012
DB
1708 ret = bpf_elf_check_ehdr(ctx);
1709 if (ret < 0)
1710 goto out_elf;
1711
32e93fb7
DB
1712 ctx->sec_done = calloc(ctx->elf_hdr.e_shnum,
1713 sizeof(*(ctx->sec_done)));
1714 if (!ctx->sec_done) {
11c39b5e
DB
1715 ret = -ENOMEM;
1716 goto out_elf;
1717 }
1718
f31645d1
DB
1719 if (ctx->verbose && bpf_log_realloc(ctx)) {
1720 ret = -ENOMEM;
1721 goto out_free;
1722 }
1723
32e93fb7 1724 bpf_save_finfo(ctx);
f6793eec
DB
1725 bpf_hash_init(ctx, CONFDIR "/bpf_pinning");
1726
32e93fb7 1727 return 0;
f31645d1
DB
1728out_free:
1729 free(ctx->sec_done);
32e93fb7
DB
1730out_elf:
1731 elf_end(ctx->elf_fd);
1732out_fd:
1733 close(ctx->obj_fd);
1734 return ret;
1735}
d937a74b 1736
32e93fb7
DB
1737static int bpf_maps_count(struct bpf_elf_ctx *ctx)
1738{
1739 int i, count = 0;
11c39b5e 1740
32e93fb7
DB
1741 for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) {
1742 if (!ctx->map_fds[i])
1743 break;
1744 count++;
1745 }
473d7840 1746
32e93fb7
DB
1747 return count;
1748}
6256f8c9 1749
32e93fb7
DB
1750static void bpf_maps_teardown(struct bpf_elf_ctx *ctx)
1751{
1752 int i;
1753
1754 for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) {
1755 if (ctx->map_fds[i])
1756 close(ctx->map_fds[i]);
473d7840 1757 }
32e93fb7
DB
1758}
1759
1760static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
1761{
1762 if (failure)
1763 bpf_maps_teardown(ctx);
473d7840 1764
f6793eec 1765 bpf_hash_destroy(ctx);
f31645d1 1766
32e93fb7 1767 free(ctx->sec_done);
f31645d1
DB
1768 free(ctx->log);
1769
32e93fb7
DB
1770 elf_end(ctx->elf_fd);
1771 close(ctx->obj_fd);
1772}
6256f8c9 1773
32e93fb7 1774static struct bpf_elf_ctx __ctx;
6256f8c9 1775
32e93fb7
DB
1776static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
1777 const char *section, bool verbose)
1778{
1779 struct bpf_elf_ctx *ctx = &__ctx;
1780 int fd = 0, ret;
6256f8c9 1781
32e93fb7
DB
1782 ret = bpf_elf_ctx_init(ctx, pathname, type, verbose);
1783 if (ret < 0) {
1784 fprintf(stderr, "Cannot initialize ELF context!\n");
1785 return ret;
1786 }
6256f8c9 1787
32e93fb7
DB
1788 ret = bpf_fetch_ancillary(ctx);
1789 if (ret < 0) {
1790 fprintf(stderr, "Error fetching ELF ancillary data!\n");
1791 goto out;
1792 }
1793
1794 fd = bpf_fetch_prog_sec(ctx, section);
1795 if (fd < 0) {
1796 fprintf(stderr, "Error fetching program/map!\n");
1797 ret = fd;
1798 goto out;
1799 }
1800
1801 ret = bpf_fill_prog_arrays(ctx);
1802 if (ret < 0)
1803 fprintf(stderr, "Error filling program arrays!\n");
11c39b5e 1804out:
32e93fb7
DB
1805 bpf_elf_ctx_destroy(ctx, ret < 0);
1806 if (ret < 0) {
1807 if (fd)
1808 close(fd);
1809 return ret;
1810 }
1811
1812 return fd;
6256f8c9 1813}
11c39b5e 1814
6256f8c9 1815static int
4bd62446
DB
1816bpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len,
1817 const struct bpf_map_data *aux, unsigned int entries)
6256f8c9
DB
1818{
1819 struct bpf_map_set_msg msg;
1820 int *cmsg_buf, min_fd;
1821 char *amsg_buf;
1822 int i;
1823
1824 memset(&msg, 0, sizeof(msg));
1825
1826 msg.aux.uds_ver = BPF_SCM_AUX_VER;
4bd62446 1827 msg.aux.num_ent = entries;
6256f8c9
DB
1828
1829 strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name));
1830 memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st));
1831
1832 cmsg_buf = bpf_map_set_init(&msg, addr, addr_len);
1833 amsg_buf = (char *)msg.aux.ent;
1834
4bd62446 1835 for (i = 0; i < entries; i += min_fd) {
6256f8c9
DB
1836 int ret;
1837
4bd62446 1838 min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i);
6256f8c9
DB
1839 bpf_map_set_init_single(&msg, min_fd);
1840
1841 memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd);
1842 memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd);
1843
1844 ret = sendmsg(fd, &msg.hdr, 0);
1845 if (ret <= 0)
1846 return ret ? : -1;
1847 }
1848
1849 return 0;
11c39b5e
DB
1850}
1851
4bd62446
DB
1852static int
1853bpf_map_set_recv(int fd, int *fds, struct bpf_map_aux *aux,
1854 unsigned int entries)
1855{
1856 struct bpf_map_set_msg msg;
1857 int *cmsg_buf, min_fd;
1858 char *amsg_buf, *mmsg_buf;
1859 unsigned int needed = 1;
1860 int i;
1861
1862 cmsg_buf = bpf_map_set_init(&msg, NULL, 0);
1863 amsg_buf = (char *)msg.aux.ent;
1864 mmsg_buf = (char *)&msg.aux;
1865
1866 for (i = 0; i < min(entries, needed); i += min_fd) {
1867 struct cmsghdr *cmsg;
1868 int ret;
1869
1870 min_fd = min(entries, entries - i);
1871 bpf_map_set_init_single(&msg, min_fd);
1872
1873 ret = recvmsg(fd, &msg.hdr, 0);
1874 if (ret <= 0)
1875 return ret ? : -1;
1876
1877 cmsg = CMSG_FIRSTHDR(&msg.hdr);
1878 if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS)
1879 return -EINVAL;
1880 if (msg.hdr.msg_flags & MSG_CTRUNC)
1881 return -EIO;
1882 if (msg.aux.uds_ver != BPF_SCM_AUX_VER)
1883 return -ENOSYS;
1884
1885 min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd);
1886 if (min_fd > entries || min_fd <= 0)
1887 return -EINVAL;
1888
1889 memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd);
1890 memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd);
1891 memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent));
1892
1893 needed = aux->num_ent;
1894 }
1895
1896 return 0;
1897}
1898
1899int bpf_send_map_fds(const char *path, const char *obj)
6256f8c9 1900{
32e93fb7 1901 struct bpf_elf_ctx *ctx = &__ctx;
6256f8c9
DB
1902 struct sockaddr_un addr;
1903 struct bpf_map_data bpf_aux;
1904 int fd, ret;
1905
1906 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
1907 if (fd < 0) {
1908 fprintf(stderr, "Cannot open socket: %s\n",
1909 strerror(errno));
1910 return -1;
1911 }
1912
1913 memset(&addr, 0, sizeof(addr));
1914 addr.sun_family = AF_UNIX;
1915 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
1916
1917 ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
1918 if (ret < 0) {
1919 fprintf(stderr, "Cannot connect to %s: %s\n",
1920 path, strerror(errno));
1921 return -1;
1922 }
1923
1924 memset(&bpf_aux, 0, sizeof(bpf_aux));
1925
32e93fb7
DB
1926 bpf_aux.fds = ctx->map_fds;
1927 bpf_aux.ent = ctx->maps;
1928 bpf_aux.st = &ctx->stat;
6256f8c9 1929 bpf_aux.obj = obj;
6256f8c9 1930
4bd62446 1931 ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux,
32e93fb7 1932 bpf_maps_count(ctx));
6256f8c9 1933 if (ret < 0)
4bd62446
DB
1934 fprintf(stderr, "Cannot send fds to %s: %s\n",
1935 path, strerror(errno));
1936
32e93fb7 1937 bpf_maps_teardown(ctx);
4bd62446
DB
1938 close(fd);
1939 return ret;
1940}
1941
1942int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
1943 unsigned int entries)
1944{
1945 struct sockaddr_un addr;
1946 int fd, ret;
1947
1948 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
1949 if (fd < 0) {
1950 fprintf(stderr, "Cannot open socket: %s\n",
1951 strerror(errno));
1952 return -1;
1953 }
1954
1955 memset(&addr, 0, sizeof(addr));
1956 addr.sun_family = AF_UNIX;
1957 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
1958
1959 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
1960 if (ret < 0) {
1961 fprintf(stderr, "Cannot bind to socket: %s\n",
1962 strerror(errno));
1963 return -1;
1964 }
1965
1966 ret = bpf_map_set_recv(fd, fds, aux, entries);
1967 if (ret < 0)
1968 fprintf(stderr, "Cannot recv fds from %s: %s\n",
6256f8c9
DB
1969 path, strerror(errno));
1970
4bd62446 1971 unlink(addr.sun_path);
6256f8c9
DB
1972 close(fd);
1973 return ret;
1974}
11c39b5e 1975#endif /* HAVE_ELF */