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