tc_bpf.c revision d937a74b6d7818d67b12f2439320bfddcdd35e58
11d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko/*
21d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko * tc_bpf.c	BPF common code
31d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *
41d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *		This program is free software; you can distribute it and/or
51d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *		modify it under the terms of the GNU General Public License
61d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *		as published by the Free Software Foundation; either version
71d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *		2 of the License, or (at your option) any later version.
81d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *
91d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko * Authors:	Daniel Borkmann <dborkman@redhat.com>
101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *		Jiri Pirko <jiri@resnulli.us>
1111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann *		Alexei Starovoitov <ast@plumgrid.com>
121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko */
131d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
141d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <stdio.h>
151d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <stdlib.h>
161d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <unistd.h>
171d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <string.h>
181d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <stdbool.h>
191d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <errno.h>
2011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <fcntl.h>
2111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <stdarg.h>
2211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <sys/types.h>
2311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <sys/stat.h>
246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <sys/un.h>
251d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <linux/filter.h>
261d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <linux/netlink.h>
271d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <linux/rtnetlink.h>
281d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
2911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#ifdef HAVE_ELF
3011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <libelf.h>
3111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <gelf.h>
3211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif
3311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
341d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "utils.h"
356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_elf.h"
376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_scm.h"
386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
391d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_util.h"
401d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_bpf.h"
411d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
421d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoint bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
431d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		     char **bpf_string, bool *need_release,
441d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		     const char separator)
451d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{
461d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	char sp;
471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (from_file) {
491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		char *tmp_string;
511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		FILE *fp;
521d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
531d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
541d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		tmp_string = malloc(tmp_len);
551d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (tmp_string == NULL)
561d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			return -ENOMEM;
571d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
581d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		memset(tmp_string, 0, tmp_len);
591d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
601d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		fp = fopen(arg, "r");
611d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (fp == NULL) {
621d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			perror("Cannot fopen");
631d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			free(tmp_string);
641d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			return -ENOENT;
651d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		}
661d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
671d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (!fgets(tmp_string, tmp_len, fp)) {
681d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			free(tmp_string);
691d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			fclose(fp);
701d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			return -EIO;
711d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		}
721d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
731d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		fclose(fp);
741d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
751d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		*need_release = true;
761d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		*bpf_string = tmp_string;
771d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	} else {
781d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		*need_release = false;
791d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		*bpf_string = arg;
801d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	}
811d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
821d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
831d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	    sp != separator) {
841d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (*need_release)
851d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			free(*bpf_string);
861d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		return -EINVAL;
871d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	}
881d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
891d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	return 0;
901d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko}
911d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
921d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoint bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops,
931d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		  bool from_file)
941d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{
951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	char *bpf_string, *token, separator = ',';
961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	int ret = 0, i = 0;
971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	bool need_release;
981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	__u16 bpf_len = 0;
991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (argc < 1)
1011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		return -EINVAL;
1021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
1031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			     &need_release, separator))
1041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		return -EINVAL;
1051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
1061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		ret = -EINVAL;
1071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		goto out;
1081d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	}
1091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	token = bpf_string;
1111d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	while ((token = strchr(token, separator)) && (++token)[0]) {
1121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (i >= bpf_len) {
1131d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			fprintf(stderr, "Real program length exceeds encoded "
1141d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko				"length parameter!\n");
1151d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			ret = -EINVAL;
1161d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			goto out;
1171d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		}
1181d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1191d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		if (sscanf(token, "%hu %hhu %hhu %u,",
1201d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			   &bpf_ops[i].code, &bpf_ops[i].jt,
1211d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			   &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
1221d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			fprintf(stderr, "Error at instruction %d!\n", i);
1231d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			ret = -EINVAL;
1241d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			goto out;
1251d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		}
1261d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1271d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		i++;
1281d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	}
1291d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1301d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (i != bpf_len) {
1311d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		fprintf(stderr, "Parsed program length is less than encoded"
1321d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			"length parameter!\n");
1331d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		ret = -EINVAL;
1341d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		goto out;
1351d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	}
1361d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	ret = bpf_len;
1371d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1381d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoout:
1391d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (need_release)
1401d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		free(bpf_string);
1411d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1421d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	return ret;
1431d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko}
1441d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1451d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkovoid bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
1461d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{
1471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
1481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	int i;
1491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	if (len == 0)
1511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		return;
1521d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1531d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	fprintf(f, "bytecode \'%u,", len);
1541d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1551d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko	for (i = 0; i < len - 1; i++)
1561d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
1571d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko			ops[i].jf, ops[i].k);
1581d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko
1596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt,
1601d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko		ops[i].jf, ops[i].k);
1611d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko}
16211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
1636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannconst char *bpf_default_section(const enum bpf_prog_type type)
16411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
16511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	switch (type) {
16611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	case BPF_PROG_TYPE_SCHED_CLS:
16711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return ELF_SECTION_CLASSIFIER;
1686256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	case BPF_PROG_TYPE_SCHED_ACT:
1696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		return ELF_SECTION_ACTION;
17011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	default:
17111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return NULL;
17211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
17311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
17411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
1756256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#ifdef HAVE_ELF
1766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_elf_sec_data {
1776256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	GElf_Shdr sec_hdr;
1786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	char *sec_name;
1796256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	Elf_Data *sec_data;
1806256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann};
1816256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1826256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_map_data {
1836256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int *fds;
1846256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	const char *obj;
1856256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_elf_st *st;
1866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_elf_map *ent;
1876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann};
1886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* If we provide a small buffer with log level enabled, the kernel
1906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * could fail program load as no buffer space is available for the
1916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * log and thus verifier fails. In case something doesn't pass the
1926256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * verifier we still want to hand something descriptive to the user.
1936256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann */
1946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic char bpf_log_buf[65536];
195d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmannstatic bool bpf_verbose;
1966256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1976256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic struct bpf_elf_st bpf_st;
1986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1996256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int map_fds[ELF_MAX_MAPS];
2006256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic struct bpf_elf_map map_ent[ELF_MAX_MAPS];
2016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
20211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic void bpf_dump_error(const char *format, ...)  __check_format_string(1, 2);
20311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic void bpf_dump_error(const char *format, ...)
20411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
20511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	va_list vl;
20611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
20711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	va_start(vl, format);
20811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	vfprintf(stderr, format, vl);
20911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	va_end(vl);
21011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
211d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann	if (bpf_log_buf[0]) {
212d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann		fprintf(stderr, "%s\n", bpf_log_buf);
213d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann		memset(bpf_log_buf, 0, sizeof(bpf_log_buf));
214d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann	}
21511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
21611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
2176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_save_finfo(int file_fd)
2186256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
2196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct stat st;
2206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int ret;
2216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&bpf_st, 0, sizeof(bpf_st));
2236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = fstat(file_fd, &st);
2256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret < 0) {
2266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Stat of elf file failed: %s\n",
2276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			strerror(errno));
2286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		return;
2296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_st.st_dev = st.st_dev;
2326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_st.st_ino = st.st_ino;
2336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
2346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_clear_finfo(void)
2366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
2376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&bpf_st, 0, sizeof(bpf_st));
2386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
2396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic bool bpf_may_skip_map_creation(int file_fd)
2416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
2426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct stat st;
2436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int ret;
2446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = fstat(file_fd, &st);
2466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret < 0) {
2476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Stat of elf file failed: %s\n",
2486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			strerror(errno));
2496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		return false;
2506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return (bpf_st.st_dev == st.st_dev) &&
2536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	       (bpf_st.st_ino == st.st_ino);
2546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
2556256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
25611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_create_map(enum bpf_map_type type, unsigned int size_key,
25711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			  unsigned int size_value, unsigned int max_elem)
25811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
25911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	union bpf_attr attr = {
26011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.map_type	= type,
26111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.key_size	= size_key,
26211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.value_size	= size_value,
26311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.max_entries	= max_elem,
26411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	};
26511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
26611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
26711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
26811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
26911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
27011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			 unsigned int len, const char *license)
27111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
27211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	union bpf_attr attr = {
27311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.prog_type	= type,
27411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.insns		= bpf_ptr_to_u64(insns),
27511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.insn_cnt	= len / sizeof(struct bpf_insn),
27611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.license	= bpf_ptr_to_u64(license),
27711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.log_buf	= bpf_ptr_to_u64(bpf_log_buf),
27811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.log_size	= sizeof(bpf_log_buf),
27911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		.log_level	= 1,
28011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	};
28111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
28211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
28311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
28411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
28511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_prog_attach(enum bpf_prog_type type, const struct bpf_insn *insns,
28611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			   unsigned int size, const char *license)
28711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
28811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int prog_fd = bpf_prog_load(type, insns, size, license);
28911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
290d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann	if (prog_fd < 0 || bpf_verbose) {
291d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann		bpf_dump_error("%s: %s\n", prog_fd < 0 ?
292d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann			       "BPF program rejected" :
293d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann			       "BPF program verification", strerror(errno));
294d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann	}
29511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
29611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return prog_fd;
29711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
29811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
29911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_map_attach(enum bpf_map_type type, unsigned int size_key,
30011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			  unsigned int size_value, unsigned int max_elem)
30111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
30211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int map_fd = bpf_create_map(type, size_key, size_value, max_elem);
30311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
30411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (map_fd < 0)
30511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		bpf_dump_error("BPF map rejected: %s\n", strerror(errno));
30611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
30711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return map_fd;
30811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
30911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_maps_init(void)
31111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
31211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int i;
31311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(map_ent, 0, sizeof(map_ent));
3156256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < ARRAY_SIZE(map_fds); i++)
31611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		map_fds[i] = -1;
31711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
31811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int bpf_maps_count(void)
3206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
3216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int i, count = 0;
3226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
3236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < ARRAY_SIZE(map_fds); i++) {
3246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (map_fds[i] < 0)
3256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			break;
3266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		count++;
3276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
3286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
3296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return count;
3306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
3316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
3326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_maps_destroy(void)
33311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
33411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int i;
33511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(map_ent, 0, sizeof(map_ent));
3376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < ARRAY_SIZE(map_fds); i++) {
33811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (map_fds[i] >= 0)
33911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			close(map_fds[i]);
34011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
34111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
34211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int bpf_maps_attach(struct bpf_elf_map *maps, unsigned int num_maps)
34411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
34511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int i, ret;
34611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
3476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; (i < num_maps) && (num_maps <= ARRAY_SIZE(map_fds)); i++) {
34811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		struct bpf_elf_map *map = &maps[i];
34911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
35011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = bpf_map_attach(map->type, map->size_key,
35111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann				     map->size_value, map->max_elem);
35211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0)
35311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			goto err_unwind;
35411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
35511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		map_fds[i] = ret;
35611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
35711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
35811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return 0;
35911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
36011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannerr_unwind:
3616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_maps_destroy();
36211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return ret;
36311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
36411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
36511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_fill_section_data(Elf *elf_fd, GElf_Ehdr *elf_hdr, int sec_index,
36611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann				 struct bpf_elf_sec_data *sec_data)
36711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
36811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	GElf_Shdr sec_hdr;
36911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	Elf_Scn *sec_fd;
37011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	Elf_Data *sec_edata;
37111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	char *sec_name;
37211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
37311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	memset(sec_data, 0, sizeof(*sec_data));
37411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
37511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_fd = elf_getscn(elf_fd, sec_index);
37611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (!sec_fd)
37711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -EINVAL;
37811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
37911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr)
38011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -EIO;
38111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
38211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_name = elf_strptr(elf_fd, elf_hdr->e_shstrndx,
38311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			      sec_hdr.sh_name);
38411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (!sec_name || !sec_hdr.sh_size)
38511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -ENOENT;
38611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
38711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_edata = elf_getdata(sec_fd, NULL);
38811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (!sec_edata || elf_getdata(sec_fd, sec_edata))
38911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -EIO;
39011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
39111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	memcpy(&sec_data->sec_hdr, &sec_hdr, sizeof(sec_hdr));
39211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_data->sec_name = sec_name;
39311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_data->sec_data = sec_edata;
39411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
39511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return 0;
39611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
39711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
39811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_apply_relo_data(struct bpf_elf_sec_data *data_relo,
39911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			       struct bpf_elf_sec_data *data_insn,
4006256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			       Elf_Data *sym_tab)
40111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
40211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	Elf_Data *idata = data_insn->sec_data;
40311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	GElf_Shdr *rhdr = &data_relo->sec_hdr;
40411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize;
40511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	struct bpf_insn *insns = idata->d_buf;
40611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	unsigned int num_insns = idata->d_size / sizeof(*insns);
40711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
40811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	for (relo_ent = 0; relo_ent < relo_num; relo_ent++) {
40911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		unsigned int ioff, fnum;
41011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		GElf_Rel relo;
41111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		GElf_Sym sym;
41211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
41311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo)
41411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			return -EIO;
41511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
41611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ioff = relo.r_offset / sizeof(struct bpf_insn);
41711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ioff >= num_insns)
41811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			return -EINVAL;
41911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW))
42011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			return -EINVAL;
42111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
42211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (gelf_getsym(sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym)
42311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			return -EIO;
42411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
42511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		fnum = sym.st_value / sizeof(struct bpf_elf_map);
4266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (fnum >= ARRAY_SIZE(map_fds))
4276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return -EINVAL;
4286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (map_fds[fnum] < 0)
42911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			return -EINVAL;
43011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
43111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		insns[ioff].src_reg = BPF_PSEUDO_MAP_FD;
43211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		insns[ioff].imm = map_fds[fnum];
43311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
43411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
43511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return 0;
43611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
43711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
4386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int bpf_fetch_ancillary(int file_fd, Elf *elf_fd, GElf_Ehdr *elf_hdr,
4396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			       bool *sec_seen, char *license, unsigned int lic_len,
44011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			       Elf_Data **sym_tab)
44111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
44211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int sec_index, ret = -1;
44311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
44411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	for (sec_index = 1; sec_index < elf_hdr->e_shnum; sec_index++) {
44511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		struct bpf_elf_sec_data data_anc;
44611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
44711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = bpf_fill_section_data(elf_fd, elf_hdr, sec_index,
44811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					    &data_anc);
44911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0)
45011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
45111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
45211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		/* Extract and load eBPF map fds. */
4536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (!strcmp(data_anc.sec_name, ELF_SECTION_MAPS) &&
4546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		    !bpf_may_skip_map_creation(file_fd)) {
4556256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			struct bpf_elf_map *maps;
4566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			unsigned int maps_num;
4576256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
4586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			if (data_anc.sec_data->d_size % sizeof(*maps) != 0)
4596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann				return -EINVAL;
4606256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
4616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			maps = data_anc.sec_data->d_buf;
4626256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			maps_num = data_anc.sec_data->d_size / sizeof(*maps);
4636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			memcpy(map_ent, maps, data_anc.sec_data->d_size);
46411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
46511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			sec_seen[sec_index] = true;
4666256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			ret = bpf_maps_attach(maps, maps_num);
46711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			if (ret < 0)
46811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann				return ret;
46911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		}
47011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		/* Extract eBPF license. */
47111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		else if (!strcmp(data_anc.sec_name, ELF_SECTION_LICENSE)) {
47211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			if (data_anc.sec_data->d_size > lic_len)
47311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann				return -ENOMEM;
47411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
47511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			sec_seen[sec_index] = true;
47611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			memcpy(license, data_anc.sec_data->d_buf,
47711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			       data_anc.sec_data->d_size);
47811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		}
47911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		/* Extract symbol table for relocations (map fd fixups). */
48011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		else if (data_anc.sec_hdr.sh_type == SHT_SYMTAB) {
48111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			sec_seen[sec_index] = true;
48211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			*sym_tab = data_anc.sec_data;
48311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		}
48411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
48511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
48611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return ret;
48711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
48811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
48911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_fetch_prog_relo(Elf *elf_fd, GElf_Ehdr *elf_hdr, bool *sec_seen,
4906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			       enum bpf_prog_type type, const char *sec,
4916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			       const char *license, Elf_Data *sym_tab)
49211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
49311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int sec_index, prog_fd = -1;
49411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
49511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	for (sec_index = 1; sec_index < elf_hdr->e_shnum; sec_index++) {
49611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		struct bpf_elf_sec_data data_relo, data_insn;
49711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		int ins_index, ret;
49811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
49911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		/* Attach eBPF programs with relocation data (maps). */
50011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = bpf_fill_section_data(elf_fd, elf_hdr, sec_index,
50111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					    &data_relo);
50211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL)
50311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
50411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
50511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ins_index = data_relo.sec_hdr.sh_info;
50611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
50711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = bpf_fill_section_data(elf_fd, elf_hdr, ins_index,
50811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					    &data_insn);
50911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0)
51011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
5116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (strcmp(data_insn.sec_name, sec))
51211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
51311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
51411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		sec_seen[sec_index] = true;
51511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		sec_seen[ins_index] = true;
51611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
5176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		ret = bpf_apply_relo_data(&data_relo, &data_insn, sym_tab);
51811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0)
51911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
52011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
52111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		prog_fd = bpf_prog_attach(type, data_insn.sec_data->d_buf,
52211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					  data_insn.sec_data->d_size, license);
52311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (prog_fd < 0)
52411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
52511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
52611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		break;
52711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
52811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
52911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return prog_fd;
53011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
53111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
53211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_fetch_prog(Elf *elf_fd, GElf_Ehdr *elf_hdr, bool *sec_seen,
5336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			  enum bpf_prog_type type, const char *sec,
5346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			  const char *license)
53511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
53611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int sec_index, prog_fd = -1;
53711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
53811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	for (sec_index = 1; sec_index < elf_hdr->e_shnum; sec_index++) {
53911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		struct bpf_elf_sec_data data_insn;
54011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		int ret;
54111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
54211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		/* Attach eBPF programs without relocation data. */
54311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (sec_seen[sec_index])
54411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
54511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
54611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = bpf_fill_section_data(elf_fd, elf_hdr, sec_index,
54711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					    &data_insn);
54811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (ret < 0)
54911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
5506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (strcmp(data_insn.sec_name, sec))
55111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
55211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
55311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		prog_fd = bpf_prog_attach(type, data_insn.sec_data->d_buf,
55411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					  data_insn.sec_data->d_size, license);
55511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		if (prog_fd < 0)
55611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann			continue;
55711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
55811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		break;
55911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
56011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
56111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return prog_fd;
56211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
56311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
564d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmannint bpf_open_object(const char *path, enum bpf_prog_type type,
565d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann		    const char *sec, bool verbose)
56611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{
56711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	char license[ELF_MAX_LICENSE_LEN];
56811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	int file_fd, prog_fd = -1, ret;
56911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	Elf_Data *sym_tab = NULL;
57011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	GElf_Ehdr elf_hdr;
57111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	bool *sec_seen;
57211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	Elf *elf_fd;
57311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
57411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (elf_version(EV_CURRENT) == EV_NONE)
57511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -EINVAL;
57611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
57711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	file_fd = open(path, O_RDONLY, 0);
57811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (file_fd < 0)
57911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		return -errno;
58011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
58111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	elf_fd = elf_begin(file_fd, ELF_C_READ, NULL);
58211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (!elf_fd) {
58311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = -EINVAL;
58411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		goto out;
58511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
58611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
58711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (gelf_getehdr(elf_fd, &elf_hdr) != &elf_hdr) {
58811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = -EIO;
58911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		goto out_elf;
59011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
59111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
59211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	sec_seen = calloc(elf_hdr.e_shnum, sizeof(*sec_seen));
59311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (!sec_seen) {
59411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		ret = -ENOMEM;
59511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		goto out_elf;
59611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	}
59711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
59811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	memset(license, 0, sizeof(license));
599d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann	bpf_verbose = verbose;
600d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann
6016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (!bpf_may_skip_map_creation(file_fd))
6026256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		bpf_maps_init();
60311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
6046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = bpf_fetch_ancillary(file_fd, elf_fd, &elf_hdr, sec_seen,
60511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann				  license, sizeof(license), &sym_tab);
60611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (ret < 0)
60711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		goto out_maps;
60811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (sym_tab)
60911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		prog_fd = bpf_fetch_prog_relo(elf_fd, &elf_hdr, sec_seen, type,
6106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann					      sec, license, sym_tab);
61111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (prog_fd < 0)
6126256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		prog_fd = bpf_fetch_prog(elf_fd, &elf_hdr, sec_seen, type, sec,
61311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann					 license);
61411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	if (prog_fd < 0)
61511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann		goto out_maps;
6166256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_save_finfo(file_fd);
6186256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	free(sec_seen);
6206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	elf_end(elf_fd);
6226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	close(file_fd);
6236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return prog_fd;
6256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannout_maps:
6276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_maps_destroy();
62811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	free(sec_seen);
62911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannout_elf:
63011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	elf_end(elf_fd);
63111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannout:
63211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	close(file_fd);
6336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_clear_finfo();
63411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann	return prog_fd;
6356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
63611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
6376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int
6384bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len,
6394bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		 const struct bpf_map_data *aux, unsigned int entries)
6406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
6416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_map_set_msg msg;
6426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int *cmsg_buf, min_fd;
6436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	char *amsg_buf;
6446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int i;
6456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&msg, 0, sizeof(msg));
6476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	msg.aux.uds_ver = BPF_SCM_AUX_VER;
6494bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	msg.aux.num_ent = entries;
6506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name));
6526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st));
6536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	cmsg_buf = bpf_map_set_init(&msg, addr, addr_len);
6556256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	amsg_buf = (char *)msg.aux.ent;
6566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	for (i = 0; i < entries; i += min_fd) {
6586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		int ret;
6596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i);
6616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		bpf_map_set_init_single(&msg, min_fd);
6626256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd);
6646256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd);
6656256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6666256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		ret = sendmsg(fd, &msg.hdr, 0);
6676256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (ret <= 0)
6686256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return ret ? : -1;
6696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
6706256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
6716256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return 0;
67211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann}
67311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann
6744bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic int
6754bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_recv(int fd, int *fds,  struct bpf_map_aux *aux,
6764bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		 unsigned int entries)
6774bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{
6784bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	struct bpf_map_set_msg msg;
6794bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	int *cmsg_buf, min_fd;
6804bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	char *amsg_buf, *mmsg_buf;
6814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	unsigned int needed = 1;
6824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	int i;
6834bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
6844bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	cmsg_buf = bpf_map_set_init(&msg, NULL, 0);
6854bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	amsg_buf = (char *)msg.aux.ent;
6864bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	mmsg_buf = (char *)&msg.aux;
6874bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
6884bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	for (i = 0; i < min(entries, needed); i += min_fd) {
6894bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		struct cmsghdr *cmsg;
6904bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		int ret;
6914bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
6924bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		min_fd = min(entries, entries - i);
6934bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_map_set_init_single(&msg, min_fd);
6944bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
6954bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		ret = recvmsg(fd, &msg.hdr, 0);
6964bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		if (ret <= 0)
6974bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			return ret ? : -1;
6984bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
6994bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		cmsg = CMSG_FIRSTHDR(&msg.hdr);
7004bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS)
7014bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			return -EINVAL;
7024bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		if (msg.hdr.msg_flags & MSG_CTRUNC)
7034bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			return -EIO;
7044bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		if (msg.aux.uds_ver != BPF_SCM_AUX_VER)
7054bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			return -ENOSYS;
7064bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7074bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd);
7084bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		if (min_fd > entries || min_fd <= 0)
7094bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			return -EINVAL;
7104bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7114bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd);
7124bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd);
7134bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent));
7144bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7154bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		needed = aux->num_ent;
7164bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	}
7174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	return 0;
7194bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann}
7204bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7214bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_send_map_fds(const char *path, const char *obj)
7226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
7236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct sockaddr_un addr;
7246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_map_data bpf_aux;
7256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int fd, ret;
7266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
7286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (fd < 0) {
7296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Cannot open socket: %s\n",
7306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			strerror(errno));
7316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		return -1;
7326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
7336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&addr, 0, sizeof(addr));
7356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	addr.sun_family = AF_UNIX;
7366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
7376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
7396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret < 0) {
7406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Cannot connect to %s: %s\n",
7416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			path, strerror(errno));
7426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		return -1;
7436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
7446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&bpf_aux, 0, sizeof(bpf_aux));
7466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_aux.fds = map_fds;
7486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_aux.ent = map_ent;
7496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_aux.obj = obj;
7516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	bpf_aux.st = &bpf_st;
7526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux,
7546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			       bpf_maps_count());
7556256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret < 0)
7564bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		fprintf(stderr, "Cannot send fds to %s: %s\n",
7574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			path, strerror(errno));
7584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	close(fd);
7604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	return ret;
7614bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann}
7624bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7634bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
7644bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		     unsigned int entries)
7654bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{
7664bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	struct sockaddr_un addr;
7674bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	int fd, ret;
7684bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7694bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
7704bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	if (fd < 0) {
7714bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		fprintf(stderr, "Cannot open socket: %s\n",
7724bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			strerror(errno));
7734bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		return -1;
7744bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	}
7754bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7764bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	memset(&addr, 0, sizeof(addr));
7774bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	addr.sun_family = AF_UNIX;
7784bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
7794bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7804bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
7814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	if (ret < 0) {
7824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		fprintf(stderr, "Cannot bind to socket: %s\n",
7834bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann			strerror(errno));
7844bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		return -1;
7854bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	}
7864bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
7874bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	ret = bpf_map_set_recv(fd, fds, aux, entries);
7884bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	if (ret < 0)
7894bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		fprintf(stderr, "Cannot recv fds from %s: %s\n",
7906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			path, strerror(errno));
7916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
7924bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	unlink(addr.sun_path);
7936256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	close(fd);
7946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return ret;
7956256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
79611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif /* HAVE_ELF */
797