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> 19473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann#include <stdint.h> 201d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include <errno.h> 2111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <fcntl.h> 2211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <stdarg.h> 231d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#ifdef HAVE_ELF 2511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <libelf.h> 2611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#include <gelf.h> 2711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif 2811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 2932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/types.h> 3032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/stat.h> 3132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/un.h> 3232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/vfs.h> 3332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/mount.h> 3432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/syscall.h> 3532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/sendfile.h> 3632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <sys/resource.h> 3732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 3832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <linux/bpf.h> 3932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <linux/filter.h> 4032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#include <linux/if_alg.h> 4132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 428187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann#include <arpa/inet.h> 438187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 441d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "utils.h" 456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_elf.h" 476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_scm.h" 486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_util.h" 501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_bpf.h" 511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 5232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#ifdef HAVE_ELF 5332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *path, enum bpf_prog_type type, 5432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec, bool verbose); 5532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#else 5632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *path, enum bpf_prog_type type, 5732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec, bool verbose) 5832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 5932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "No ELF library support compiled in.\n"); 6032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = ENOSYS; 6132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 6232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 6332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#endif 6432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 6532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic inline __u64 bpf_ptr_to_u64(const void *ptr) 6632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 6732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return (__u64)(unsigned long)ptr; 6832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 6932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 7032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf(int cmd, union bpf_attr *attr, unsigned int size) 7132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 7232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#ifdef __NR_bpf 7332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return syscall(__NR_bpf, cmd, attr, size); 7432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#else 7532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "No bpf syscall, kernel headers too old?\n"); 7632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = ENOSYS; 7732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 7832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#endif 7932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 8032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 8191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_map_update(int fd, const void *key, const void *value, 8291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann uint64_t flags) 8332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 8432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 8591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .map_fd = fd, 8691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .key = bpf_ptr_to_u64(key), 8791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .value = bpf_ptr_to_u64(value), 8891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .flags = flags, 8932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 9032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 9191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 9232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 9332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 9432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, 9532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char **bpf_string, bool *need_release, 9632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char separator) 971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char sp; 991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (from_file) { 1011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); 1021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *tmp_string; 1031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko FILE *fp; 1041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; 1061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_string = malloc(tmp_len); 1071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (tmp_string == NULL) 1081d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOMEM; 1091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko memset(tmp_string, 0, tmp_len); 1111d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fp = fopen(arg, "r"); 1131d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (fp == NULL) { 1141d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko perror("Cannot fopen"); 1151d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1161d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOENT; 1171d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1181d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1191d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (!fgets(tmp_string, tmp_len, fp)) { 1201d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1211d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1221d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EIO; 1231d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1241d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1251d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1261d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1271d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = true; 1281d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = tmp_string; 1291d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } else { 1301d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = false; 1311d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = arg; 1321d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1331d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1341d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || 1351d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko sp != separator) { 1361d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (*need_release) 1371d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(*bpf_string); 1381d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1391d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1401d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1411d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return 0; 1421d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1431d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 14432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops, 14532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool from_file) 1461d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *bpf_string, *token, separator = ','; 1481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int ret = 0, i = 0; 1491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko bool need_release; 1501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko __u16 bpf_len = 0; 1511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1521d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (argc < 1) 1531d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1541d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, 1551d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &need_release, separator)) 1561d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1571d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { 1581d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1591d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1601d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1611d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1621d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko token = bpf_string; 1631d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko while ((token = strchr(token, separator)) && (++token)[0]) { 1641d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i >= bpf_len) { 1651d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Real program length exceeds encoded " 1661d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1671d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1681d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1691d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1701d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1711d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(token, "%hu %hhu %hhu %u,", 1721d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].code, &bpf_ops[i].jt, 1731d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { 1741d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Error at instruction %d!\n", i); 1751d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1761d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1771d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1781d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1791d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko i++; 1801d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1811d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1821d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i != bpf_len) { 1831d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Parsed program length is less than encoded" 1841d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1851d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1861d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1871d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1881d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = bpf_len; 1891d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoout: 1901d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (need_release) 1911d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(bpf_string); 1921d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1931d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return ret; 1941d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkovoid bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) 1971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); 1991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int i; 2001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (len == 0) 2021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return; 2031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "bytecode \'%u,", len); 2051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko for (i = 0; i < len - 1; i++) 2071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, 2081d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt, 2111d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 21311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 21491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map, 21591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int length) 2169e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann{ 2179e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann char file[PATH_MAX], buff[4096]; 2189e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann struct bpf_elf_map tmp, zero; 2199e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann unsigned int val; 2209e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann FILE *fp; 2219e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2229e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd); 2239e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2249e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fp = fopen(file, "r"); 2259e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (!fp) { 2269e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "No procfs support?!\n"); 2279e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return -EIO; 2289e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2299e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2309e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann memset(&tmp, 0, sizeof(tmp)); 2319e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann while (fgets(buff, sizeof(buff), fp)) { 2329e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (sscanf(buff, "map_type:\t%u", &val) == 1) 2339e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.type = val; 2349e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "key_size:\t%u", &val) == 1) 2359e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.size_key = val; 2369e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "value_size:\t%u", &val) == 1) 2379e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.size_value = val; 2389e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "max_entries:\t%u", &val) == 1) 2399e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.max_elem = val; 2409e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2419e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2429e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fclose(fp); 2439e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 24491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!memcmp(&tmp, map, length)) { 2459e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return 0; 2469e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } else { 2479e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann memset(&zero, 0, sizeof(zero)); 2489e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann /* If kernel doesn't have eBPF-related fdinfo, we cannot do much, 2499e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * so just accept it. We know we do have an eBPF fd and in this 2509e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * case, everything is 0. It is guaranteed that no such map exists 2519e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * since map type of 0 is unloadable BPF_MAP_TYPE_UNSPEC. 2529e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann */ 25391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!memcmp(&tmp, &zero, length)) 2549e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return 0; 2559e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2569e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "Map specs from pinned file differ!\n"); 2579e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return -EINVAL; 2589e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2599e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann} 2609e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 26191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_mnt_fs(const char *target) 26291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 26391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bool bind_done = false; 26491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 26591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) { 26691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (errno != EINVAL || bind_done) { 26791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount --make-private %s failed: %s\n", 26891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, strerror(errno)); 26991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 27091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 27191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 27291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mount(target, target, "none", MS_BIND, NULL)) { 27391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount --bind %s %s failed: %s\n", 27491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, target, strerror(errno)); 27591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 27691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 27791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 27891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bind_done = true; 27991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 28091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 28191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mount("bpf", target, "bpf", 0, NULL)) { 28291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount -t bpf bpf %s failed: %s\n", 28391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, strerror(errno)); 28491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 28591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 28691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 28791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return 0; 28891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 28991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 29032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_valid_mntpt(const char *mnt, unsigned long magic) 29132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 29232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct statfs st_fs; 29332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 29432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (statfs(mnt, &st_fs) < 0) 29532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 29632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if ((unsigned long)st_fs.f_type != magic) 29732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 29832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 29932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 30032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 30132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 30232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_find_mntpt(const char *fstype, unsigned long magic, 30332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char *mnt, int len, 30432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *known_mnts) 30532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 30632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *ptr; 30732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char type[100]; 30832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann FILE *fp; 30932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 31032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (known_mnts) { 31132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr = known_mnts; 31232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (*ptr) { 31332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_valid_mntpt(*ptr, magic) == 0) { 31432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strncpy(mnt, *ptr, len - 1); 31532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt[len - 1] = 0; 31632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 31732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 31832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr++; 31932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 32032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 32132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 32232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fp = fopen("/proc/mounts", "r"); 32332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fp == NULL || len != PATH_MAX) 32432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 32532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 32632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (fscanf(fp, "%*s %" textify(PATH_MAX) "s %99s %*s %*d %*d\n", 32732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt, type) == 2) { 32832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) == 0) 32932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 33032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 33132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fclose(fp); 33332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) != 0) 33432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 33532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 33732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 33832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannint bpf_trace_pipe(void) 34032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 34132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tracefs_mnt[PATH_MAX] = TRACE_DIR_MNT; 34232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static const char * const tracefs_known_mnts[] = { 34332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann TRACE_DIR_MNT, 34432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/sys/kernel/debug/tracing", 34532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/tracing", 34632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/trace", 34732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 0, 34832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 34932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tpipe[PATH_MAX]; 35032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *mnt; 35132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 35232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 35332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt, 35432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(tracefs_mnt), tracefs_known_mnts); 35532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!mnt) { 35632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "tracefs not mounted?\n"); 35732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 35832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 35932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt); 36132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = open(tpipe, O_RDONLY); 36332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 36432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 36532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Running! Hang up with ^C!\n\n"); 36732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (1) { 36832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char buff[4096]; 36932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t ret; 37032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = read(fd, buff, sizeof(buff) - 1); 37232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret > 0) { 37332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann write(2, buff, ret); 37432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fflush(stderr); 37532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 37932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 38032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 38191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic const char *bpf_get_tc_dir(void) 38291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 38391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static bool bpf_mnt_cached = false; 38491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static char bpf_tc_dir[PATH_MAX]; 38591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static const char *mnt; 38691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static const char * const bpf_known_mnts[] = { 38791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann BPF_DIR_MNT, 38891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 0, 38991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 39091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char bpf_mnt[PATH_MAX] = BPF_DIR_MNT; 39191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char bpf_glo_dir[PATH_MAX]; 39291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret; 39391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 39491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (bpf_mnt_cached) 39591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto done; 39691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 39791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_mnt, sizeof(bpf_mnt), 39891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_known_mnts); 39991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!mnt) { 40091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = getenv(BPF_ENV_MNT); 40191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!mnt) 40291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = BPF_DIR_MNT; 40391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_mnt_fs(mnt); 40491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret) { 40591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 40691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 40791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 40891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 40991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 41091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(bpf_tc_dir, sizeof(bpf_tc_dir), "%s/%s", mnt, BPF_DIR_TC); 41191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = mkdir(bpf_tc_dir, S_IRWXU); 41291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret && errno != EEXIST) { 41391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_tc_dir, 41491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strerror(errno)); 41591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 41691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 41791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 41891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 41991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s", 42091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_tc_dir, BPF_DIR_GLOBALS); 42191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = mkdir(bpf_glo_dir, S_IRWXU); 42291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret && errno != EEXIST) { 42391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir, 42491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strerror(errno)); 42591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 42691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 42791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 42891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 42991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = bpf_tc_dir; 43091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout: 43191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_mnt_cached = true; 43291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmanndone: 43391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return mnt; 43491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 43591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 43691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_obj_get(const char *pathname) 43791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 43891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann union bpf_attr attr; 43991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char tmp[PATH_MAX]; 44091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 44191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (strlen(pathname) > 2 && pathname[0] == 'm' && 44291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann pathname[1] == ':' && bpf_get_tc_dir()) { 44391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(tmp, sizeof(tmp), "%s/%s", 44491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_get_tc_dir(), pathname + 2); 44591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann pathname = tmp; 44691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 44791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 44891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann memset(&attr, 0, sizeof(attr)); 44991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann attr.pathname = bpf_ptr_to_u64(pathname); 45091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 45191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 45291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 45391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 4546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannconst char *bpf_default_section(const enum bpf_prog_type type) 45511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 45611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann switch (type) { 45711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann case BPF_PROG_TYPE_SCHED_CLS: 45811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ELF_SECTION_CLASSIFIER; 4596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann case BPF_PROG_TYPE_SCHED_ACT: 4606256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ELF_SECTION_ACTION; 46111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann default: 46211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return NULL; 46311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 46411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 46511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 46691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannenum bpf_mode { 46791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann CBPF_BYTECODE = 0, 46891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann CBPF_FILE, 46991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann EBPF_OBJECT, 47091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann EBPF_PINNED, 47191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann __BPF_MODE_MAX, 47291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann#define BPF_MODE_MAX __BPF_MODE_MAX 47391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann}; 47491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 47591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_parse(int *ptr_argc, char ***ptr_argv, const bool *opt_tbl, 47691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type *type, enum bpf_mode *mode, 47791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_object, const char **ptr_section, 47891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_uds_name, struct sock_filter *opcodes) 47932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 48032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *file, *section, *uds_name; 48132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose = false; 48291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret, argc; 48391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char **argv; 48491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 48591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann argv = *ptr_argv; 48691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann argc = *ptr_argc; 48791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 48891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (opt_tbl[CBPF_BYTECODE] && 48991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "bytecode") == 0 || 49091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "bc") == 0)) { 49191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = CBPF_BYTECODE; 49291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[CBPF_FILE] && 49391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "bytecode-file") == 0 || 49491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "bcf") == 0)) { 49591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = CBPF_FILE; 49691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[EBPF_OBJECT] && 49791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "object-file") == 0 || 49891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "obj") == 0)) { 49991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = EBPF_OBJECT; 50091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[EBPF_PINNED] && 50191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "object-pinned") == 0 || 50291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann matches(*argv, "pinned") == 0 || 50391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann matches(*argv, "fd") == 0)) { 50491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = EBPF_PINNED; 50532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 50632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "What mode is \"%s\"?\n", *argv); 50732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 50832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 50932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 51032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 51132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = section = uds_name = NULL; 51291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) { 51332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = *argv; 51432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 51532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 51691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*type == BPF_PROG_TYPE_UNSPEC) { 51791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (argc > 0 && matches(*argv, "type") == 0) { 51891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NEXT_ARG(); 51991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (matches(*argv, "cls") == 0) { 52091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_CLS; 52191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (matches(*argv, "act") == 0) { 52291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_ACT; 52391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 52491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "What type is \"%s\"?\n", 52591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *argv); 52691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 52791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 52891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NEXT_ARG_FWD(); 52991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 53091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_CLS; 53191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 53291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 53391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 53491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann section = bpf_default_section(*type); 53532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "section") == 0) { 53632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 53732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section = *argv; 53832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 53932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 54032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 54132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = getenv(BPF_ENV_UDS); 54232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && !uds_name && 54332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann matches(*argv, "export") == 0) { 54432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 54532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = *argv; 54632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 54732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 54832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 54932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "verbose") == 0) { 55032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann verbose = true; 55132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 55232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 55432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann PREV_ARG(); 55532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 55791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE) 55891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_ops_parse(argc, argv, opcodes, *mode == CBPF_FILE); 55991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else if (*mode == EBPF_OBJECT) 56091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_obj_open(file, *type, section, verbose); 56191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else if (*mode == EBPF_PINNED) 56232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_get(file); 56391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else 56432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 56532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 56691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_object) 56791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_object = file; 56891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_section) 56991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_section = section; 57091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_uds_name) 57191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_uds_name = uds_name; 57291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_argc = argc; 57491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_argv = argv; 57591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 57791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 57891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannint bpf_parse_common(int *ptr_argc, char ***ptr_argv, const int *nla_tbl, 58091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type type, const char **ptr_object, 58191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_uds_name, struct nlmsghdr *n) 58291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 58391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann struct sock_filter opcodes[BPF_MAXINSNS]; 58491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const bool opt_tbl[BPF_MODE_MAX] = { 58591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_BYTECODE] = true, 58691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_FILE] = true, 58791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_OBJECT] = true, 58891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_PINNED] = true, 58991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 59091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char annotation[256]; 59191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char *section; 59291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_mode mode; 59391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret; 59491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 59591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_parse(ptr_argc, ptr_argv, opt_tbl, &type, &mode, 59691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ptr_object, §ion, ptr_uds_name, opcodes); 59791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) 59891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 59991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 60032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mode == CBPF_BYTECODE || mode == CBPF_FILE) { 60132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr16(n, MAX_MSG, nla_tbl[BPF_NLA_OPS_LEN], ret); 60232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr_l(n, MAX_MSG, nla_tbl[BPF_NLA_OPS], opcodes, 60332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret * sizeof(struct sock_filter)); 60491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 60591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 60691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mode == EBPF_OBJECT || mode == EBPF_PINNED) { 60732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(annotation, sizeof(annotation), "%s:[%s]", 60891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann basename(*ptr_object), mode == EBPF_PINNED ? 60991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann "*fsobj" : section); 61032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr32(n, MAX_MSG, nla_tbl[BPF_NLA_FD], ret); 61232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattrstrz(n, MAX_MSG, nla_tbl[BPF_NLA_NAME], annotation); 61332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 61432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return 0; 61691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 61732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannint bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) 61991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 62091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC; 62191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const bool opt_tbl[BPF_MODE_MAX] = { 62291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_BYTECODE] = false, 62391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_FILE] = false, 62491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_OBJECT] = true, 62591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_PINNED] = true, 62691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 62791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const struct bpf_elf_map test = { 62891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .type = BPF_MAP_TYPE_PROG_ARRAY, 62991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .size_key = sizeof(int), 63091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .size_value = sizeof(int), 63191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 63291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret, prog_fd, map_fd; 63391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char *section; 63491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_mode mode; 63591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann uint32_t map_key; 63691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 63791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann prog_fd = bpf_parse(&argc, &argv, opt_tbl, &type, &mode, 63891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NULL, §ion, NULL, NULL); 63991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (prog_fd < 0) 64091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return prog_fd; 64191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (key) { 64291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_key = *key; 64391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 64491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = sscanf(section, "%*i/%i", &map_key); 64591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret != 1) { 64691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Couldn\'t infer map key from section " 64791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann "name! Please provide \'key\' argument!\n"); 64891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = -EINVAL; 64991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_prog; 65091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 65191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 65232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 65391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_fd = bpf_obj_get(map_path); 65491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (map_fd < 0) { 65591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n", 65691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_path, strerror(errno)); 65791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = map_fd; 65891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_prog; 65991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 66091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 66191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_selfcheck_pinned(map_fd, &test, 66291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann offsetof(struct bpf_elf_map, max_elem)); 66391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) { 66491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path); 66591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_map; 66691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 66791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 66891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_update(map_fd, &map_key, &prog_fd, BPF_ANY); 66991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) 67091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Map update failed: %s\n", strerror(errno)); 67191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout_map: 67291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann close(map_fd); 67391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout_prog: 67491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann close(prog_fd); 67591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 67632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 67732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 6786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#ifdef HAVE_ELF 67932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_prog { 68032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 68132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_insn *insns; 68232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size; 68332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *license; 68432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 68532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 686f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstruct bpf_hash_entry { 687f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann unsigned int pinning; 688f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const char *subpath; 689f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *next; 690f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann}; 691f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 69232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_ctx { 69332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf *elf_fd; 69432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Ehdr elf_hdr; 69532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sym_tab; 69632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *str_tab; 69732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int obj_fd; 69832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_fds[ELF_MAX_MAPS]; 69932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map maps[ELF_MAX_MAPS]; 70032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sym_num; 70132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_num; 70232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool *sec_done; 70332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sec_maps; 70432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char license[ELF_MAX_LICENSE_LEN]; 70532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 70632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose; 70732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st stat; 708f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *ht[256]; 70932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 71032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 7116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_elf_sec_data { 71232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr sec_hdr; 71332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_data; 71432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec_name; 7156256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 7166256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 7176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_map_data { 71832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int *fds; 71932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *obj; 72032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st *st; 72132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map *ent; 7226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 7236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 7246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* If we provide a small buffer with log level enabled, the kernel 7256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * could fail program load as no buffer space is available for the 7266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * log and thus verifier fails. In case something doesn't pass the 7276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * verifier we still want to hand something descriptive to the user. 7286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann */ 7296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic char bpf_log_buf[65536]; 7306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 73132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic __check_format_string(1, 2) void bpf_dump_error(const char *format, ...) 73211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 73311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_list vl; 73411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 73511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_start(vl, format); 73611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann vfprintf(stderr, format, vl); 73711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_end(vl); 73811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 739d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann if (bpf_log_buf[0]) { 740d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann fprintf(stderr, "%s\n", bpf_log_buf); 741d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann memset(bpf_log_buf, 0, sizeof(bpf_log_buf)); 742d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 74311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 74411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 74532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_create(enum bpf_map_type type, unsigned int size_key, 74611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann unsigned int size_value, unsigned int max_elem) 74711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 74811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 74911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .map_type = type, 75011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .key_size = size_key, 75111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .value_size = size_value, 75211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .max_entries = max_elem, 75311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 75411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 75511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 75611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 75711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 75811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, 75932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size, const char *license) 76011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 76111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 76211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .prog_type = type, 76311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .insns = bpf_ptr_to_u64(insns), 76432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .insn_cnt = size / sizeof(struct bpf_insn), 76511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .license = bpf_ptr_to_u64(license), 76611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_buf = bpf_ptr_to_u64(bpf_log_buf), 76711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_size = sizeof(bpf_log_buf), 76811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_level = 1, 76911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 77011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 77132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (getenv(BPF_ENV_NOLOG)) { 77232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_buf = 0; 77332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_size = 0; 77432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_level = 0; 77532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 77632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 77711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 77811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 77911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 78032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_pin(int fd, const char *pathname) 78111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 78232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 78332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .pathname = bpf_ptr_to_u64(pathname), 78432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .bpf_fd = fd, 78532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 78632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 78732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); 78832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 78911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 79032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_hash(const char *object, uint8_t *out, size_t len) 79132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 79232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct sockaddr_alg alg = { 79332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_family = AF_ALG, 79432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_type = "hash", 79532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_name = "sha1", 79632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 79732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, cfd, ofd, ffd; 79832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat stbuff; 79932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t size; 80032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 80132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!object || len != 20) 80232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 80332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 80432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann cfd = socket(AF_ALG, SOCK_SEQPACKET, 0); 80532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (cfd < 0) { 80632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot get AF_ALG socket: %s\n", 80732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 80832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return cfd; 80932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 81032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 81132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg)); 81232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 81332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error binding socket: %s\n", strerror(errno)); 81432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 81532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 81632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 81732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ofd = accept(cfd, NULL, 0); 81832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ofd < 0) { 81932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error accepting socket: %s\n", 82032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 82132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ofd; 82232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 82332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 82432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 82532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ffd = open(object, O_RDONLY); 82632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ffd < 0) { 82732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error opening object %s: %s\n", 82832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann object, strerror(errno)); 82932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ffd; 83032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ofd; 83132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 83232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 83332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ffd, &stbuff); 83432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 83532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error doing fstat: %s\n", 83632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 83732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 838d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 83911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 84032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = sendfile(ofd, ffd, NULL, stbuff.st_size); 84132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != stbuff.st_size) { 84232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n", 84332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, stbuff.st_size, strerror(errno)); 84432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 84532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 84632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 84732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 84832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = read(ofd, out, len); 84932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != len) { 85032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n", 85132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, len, strerror(errno)); 85232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 85332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 85432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = 0; 85532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 85632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ffd: 85732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ffd); 85832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ofd: 85932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ofd); 86032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_cfd: 86132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(cfd); 86232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 86311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 86411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 86532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_get_obj_uid(const char *pathname) 86611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 86732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static bool bpf_uid_cached = false; 86832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char bpf_uid[64]; 86932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint8_t tmp[20]; 87032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 87111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 87232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_uid_cached) 87332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto done; 87411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 87532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); 87632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret) { 87732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Object hashing failed!\n"); 87832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 87932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 88032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 88132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid)); 88232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_uid_cached = true; 88332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmanndone: 88432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_uid; 88511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 88611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 88732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_init_env(const char *pathname) 88832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 88932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct rlimit limit = { 89032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_cur = RLIM_INFINITY, 89132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_max = RLIM_INFINITY, 89232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 89332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 89432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* Don't bother in case we fail! */ 89532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann setrlimit(RLIMIT_MEMLOCK, &limit); 89632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 89732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_tc_dir()) { 89832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Continuing without mounted eBPF fs. " 89932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "Too old kernel?\n"); 90032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 90132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 90232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 90332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_obj_uid(pathname)) 90432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 90532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 90632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 9076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 9086256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 909f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic const char *bpf_custom_pinning(const struct bpf_elf_ctx *ctx, 910f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 911f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 912f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 913f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 914f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)]; 915f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (entry && entry->pinning != pinning) 916f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = entry->next; 917f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 918f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return entry ? entry->subpath : NULL; 919f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 920f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 921f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic bool bpf_no_pinning(const struct bpf_elf_ctx *ctx, 922f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 92311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 92432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 92532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 92632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 92732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return false; 92832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_NONE: 92932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return true; 930f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 931f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return !bpf_custom_pinning(ctx, pinning); 93232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 93332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 93432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 93532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_make_pathname(char *pathname, size_t len, const char *name, 936f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, uint32_t pinning) 93732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 93832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 93932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 94032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 94132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_get_obj_uid(NULL), name); 94232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 94332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 94432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 94532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann BPF_DIR_GLOBALS, name); 94632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 947f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 948f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(pathname, len, "%s/../%s/%s", bpf_get_tc_dir(), 949f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_custom_pinning(ctx, pinning), name); 950f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann break; 95132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 95232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 95332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 954f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_probe_pinned(const char *name, const struct bpf_elf_ctx *ctx, 955f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 95632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 95732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char pathname[PATH_MAX]; 95832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 959f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir()) 96032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 96132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 962f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning); 96332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_get(pathname); 96432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 96532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 966f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_make_obj_path(void) 96732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 968f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char tmp[PATH_MAX]; 96932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 97032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 971f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_tc_dir(), 972f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_get_obj_uid(NULL)); 973f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 974f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = mkdir(tmp, S_IRWXU); 975f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret && errno != EEXIST) { 976f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", tmp, strerror(errno)); 977f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return ret; 978f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 979f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 980f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 981f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 982f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 983f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_make_custom_path(const char *todo) 984f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 985f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char tmp[PATH_MAX], rem[PATH_MAX], *sub; 986f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret; 987f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 988f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(tmp, sizeof(tmp), "%s/../", bpf_get_tc_dir()); 989f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(rem, sizeof(rem), "%s/", todo); 990f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sub = strtok(rem, "/"); 99132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 992f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (sub) { 993f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (strlen(tmp) + strlen(sub) + 2 > PATH_MAX) 994f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return -EINVAL; 995f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 996f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcat(tmp, sub); 997f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcat(tmp, "/"); 99832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 999f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = mkdir(tmp, S_IRWXU); 100032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret && errno != EEXIST) { 1001f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", tmp, 100232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 100332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 100432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 1005f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1006f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sub = strtok(NULL, "/"); 100732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 100832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1009f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1010f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1011f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1012f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_place_pinned(int fd, const char *name, 1013f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, uint32_t pinning) 1014f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1015f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char pathname[PATH_MAX]; 1016f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const char *tmp; 1017f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret = 0; 1018f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1019f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir()) 1020f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1021f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1022f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (pinning == PIN_OBJECT_NS) 1023f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_make_obj_path(); 1024f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann else if ((tmp = bpf_custom_pinning(ctx, pinning))) 1025f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_make_custom_path(tmp); 1026f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret < 0) 1027f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return ret; 1028f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1029f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning); 103032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_pin(fd, pathname); 103132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 103232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 103332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_prog_attach(const char *section, 103432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_elf_prog *prog, bool verbose) 103532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 103632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 103732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 103832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* We can add pinning here later as well, same as bpf_map_attach(). */ 103932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 104032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_load(prog->type, prog->insns, prog->size, 104132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->license); 104232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 104332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Prog section \'%s\' (type:%u insns:%zu " 104432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "license:\'%s\') %s%s (%d)!\n\n", 104532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section, prog->type, 104632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->size / sizeof(struct bpf_insn), 1047fd7f9c7fd11fa926bda2edc8bc492e7515753a32Daniel Borkmann prog->license, fd < 0 ? "rejected: " : 104832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "loaded", fd < 0 ? strerror(errno) : "", 104932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? errno : fd); 105032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 105132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 105232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 105332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 105432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 105532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_attach(const char *name, const struct bpf_elf_map *map, 1056f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, bool verbose) 105732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 105832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd, ret; 105932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1060f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fd = bpf_probe_pinned(name, ctx, map->pinning); 106132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd > 0) { 106291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_selfcheck_pinned(fd, map, 106391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann offsetof(struct bpf_elf_map, 106491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann id)); 10659e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (ret < 0) { 10669e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann close(fd); 10679e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "Map \'%s\' self-check failed!\n", 10689e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann name); 10699e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return ret; 10709e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 107132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (verbose) 107232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' loaded as pinned!\n", 107332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name); 107432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 107532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 107632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 107732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 107832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_map_create(map->type, map->size_key, map->size_value, 107932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->max_elem); 108032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 108132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Map \'%s\' (type:%u id:%u pinning:%u " 108232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "ksize:%u vsize:%u max-elems:%u) %s%s (%d)!\n", 108332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name, map->type, map->id, map->pinning, 108432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->size_key, map->size_value, map->max_elem, 108532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? "rejected: " : "loaded", fd < 0 ? 108632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno) : "", fd < 0 ? errno : fd); 108732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 108832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 108932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 109032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1091f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_place_pinned(fd, name, ctx, map->pinning); 109232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 && errno != EEXIST) { 109332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Could not pin %s map: %s\n", name, 109432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 109532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 109632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 109732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 109832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 109932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 110032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 110132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_BIND(x) ((x) >> 4) 110332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) 110432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx, 110632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const GElf_Sym *sym) 110732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 110832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->str_tab->d_buf + sym->st_name; 110932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 111032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 111132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) 111232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 111332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 111411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann int i; 111511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 111632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->sym_num; i++) { 111732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) 111832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 111932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 112032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (__ELF_ST_BIND(sym.st_info) != STB_GLOBAL || 112132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann __ELF_ST_TYPE(sym.st_info) != STT_NOTYPE || 112232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_shndx != ctx->sec_maps || 112332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_value / sizeof(struct bpf_elf_map) != which) 112432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 112532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 112632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_str_tab_name(ctx, &sym); 112711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 112832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 112932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 113011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 113111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 113232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_attach_all(struct bpf_elf_ctx *ctx) 113311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 113432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *map_name; 113532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, fd; 113611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 113732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->map_num; i++) { 113832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map_name = bpf_map_fetch_name(ctx, i); 113932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!map_name) 114032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 114111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 1142f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fd = bpf_map_attach(map_name, &ctx->maps[i], ctx, 1143f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->verbose); 114432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 114532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 114611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 114732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_fds[i] = fd; 114811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 114911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 115011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 115111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 115211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 115332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_section_data(struct bpf_elf_ctx *ctx, int section, 115432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 115511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 115632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_edata; 115711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann GElf_Shdr sec_hdr; 115811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann Elf_Scn *sec_fd; 115911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann char *sec_name; 116011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 116132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(data, 0, sizeof(*data)); 116211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 116332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_fd = elf_getscn(ctx->elf_fd, section); 116411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_fd) 116511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EINVAL; 116611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr) 116711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 116811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 116932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_name = elf_strptr(ctx->elf_fd, ctx->elf_hdr.e_shstrndx, 117011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_hdr.sh_name); 117111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_name || !sec_hdr.sh_size) 117211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -ENOENT; 117311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 117411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_edata = elf_getdata(sec_fd, NULL); 117511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_edata || elf_getdata(sec_fd, sec_edata)) 117611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 117711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 117832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(&data->sec_hdr, &sec_hdr, sizeof(sec_hdr)); 117911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_name = sec_name; 118132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_data = sec_edata; 118211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 118311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 118411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_maps(struct bpf_elf_ctx *ctx, int section, 118632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 118711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 118832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size % sizeof(struct bpf_elf_map) != 0) 118932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 119011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 119132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_num = data->sec_data->d_size / sizeof(struct bpf_elf_map); 119232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_maps = section; 119332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 119411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 119532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_num > ARRAY_SIZE(ctx->map_fds)) { 119632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Too many BPF maps in ELF section!\n"); 119732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 119832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 119911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 120032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->maps, data->sec_data->d_buf, data->sec_data->d_size); 120132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 120232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 120311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 120432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_license(struct bpf_elf_ctx *ctx, int section, 120532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 120632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 120732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size > sizeof(ctx->license)) 120832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 120911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 121032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->license, data->sec_data->d_buf, data->sec_data->d_size); 121132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 121232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 121332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 121411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 121532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_symtab(struct bpf_elf_ctx *ctx, int section, 121632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 121732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 121832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_tab = data->sec_data; 121932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_num = data->sec_hdr.sh_size / data->sec_hdr.sh_entsize; 122032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 122111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 122211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 122311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 122432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section, 122532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 122611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 122732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->str_tab = data->sec_data; 122832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 122932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 123032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 123111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 123232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx) 123332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 123432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 123532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, ret = -1; 123611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 123732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 123832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 123911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (ret < 0) 124011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 124111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 1242cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann if (data.sec_hdr.sh_type == SHT_PROGBITS && 1243cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data.sec_name, ELF_SECTION_MAPS)) 124432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_maps(ctx, i, &data); 1245cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_PROGBITS && 1246cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data.sec_name, ELF_SECTION_LICENSE)) 124732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_license(ctx, i, &data); 1248cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_SYMTAB && 1249cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data.sec_name, ".symtab")) 125032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_symtab(ctx, i, &data); 125132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_STRTAB && 1252cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data.sec_name, ".strtab")) 125332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_strtab(ctx, i, &data); 125432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 125532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error parsing section %d! Perhaps" 125632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "check with readelf -a?\n", i); 125732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 125811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 125932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 126032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 126132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) { 126232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_maps_attach_all(ctx); 126332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 126432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error loading maps into kernel!\n"); 126532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 126611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 126711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 126811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 126911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ret; 127011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 127111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 127232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section) 127311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 127432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 127532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 127632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, i, fd = -1; 127711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 127832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 127932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 128011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 128111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 128232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 1283cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann if (ret < 0 || 1284cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !(data.sec_hdr.sh_type == SHT_PROGBITS && 1285cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann data.sec_hdr.sh_flags & SHF_EXECINSTR && 1286cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data.sec_name, section))) 128711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 128811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 128932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 129032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 129132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data.sec_data->d_buf; 129232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data.sec_data->d_size; 129332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 129411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 129532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 129632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 129711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 129811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 129932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 130011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 130111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 130211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 130332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 130411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 130511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 130632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_apply_relo_data(struct bpf_elf_ctx *ctx, 130732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_relo, 130832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_insn) 130911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 131032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *idata = data_insn->sec_data; 131132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr *rhdr = &data_relo->sec_hdr; 131232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize; 131332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_insn *insns = idata->d_buf; 131432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int num_insns = idata->d_size / sizeof(*insns); 131511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 131632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (relo_ent = 0; relo_ent < relo_num; relo_ent++) { 131732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int ioff, rmap; 131832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Rel relo; 131932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 132032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 132132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo) 132232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 132332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 132432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ioff = relo.r_offset / sizeof(struct bpf_insn); 132532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ioff >= num_insns || 132632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) 132732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 132832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 132932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym) 133032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 133132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 133232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann rmap = sym.st_value / sizeof(struct bpf_elf_map); 133332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (rmap >= ARRAY_SIZE(ctx->map_fds)) 133432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 133532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[rmap]) 133632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 133732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 133832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->verbose) 133932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' (%d) injected into prog " 134032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "section \'%s\' at offset %u!\n", 134132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap], 134232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data_insn->sec_name, ioff); 134311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 134432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].src_reg = BPF_PSEUDO_MAP_FD; 134532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].imm = ctx->map_fds[rmap]; 134632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 134732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 134832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 134932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 135032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 135132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section) 135232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 135332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data_relo, data_insn; 135432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 135532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, idx, i, fd = -1; 135632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 135732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 135832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data_relo); 135932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL) 136011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 136111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 136232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann idx = data_relo.sec_hdr.sh_info; 136332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, idx, &data_insn); 1364cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann if (ret < 0 || 1365cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !(data_insn.sec_hdr.sh_type == SHT_PROGBITS && 1366cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann data_insn.sec_hdr.sh_flags & SHF_EXECINSTR && 1367cce3d4664c6bc839116e504183f9caebe6994120Daniel Borkmann !strcmp(data_insn.sec_name, section))) 136811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 136932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 137032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn); 137132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 137211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 137311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 137432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 137532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 137632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data_insn.sec_data->d_buf; 137732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data_insn.sec_data->d_size; 137832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 137932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 138032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 138132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 138211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 138311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 138432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 138532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[idx] = true; 138611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 138711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 138811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 138932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 139011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 139111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 139232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section) 1393473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 1394473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann int ret = -1; 1395473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 139632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab) 139732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog_relo(ctx, section); 1398473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 139932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog(ctx, section); 140032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1401473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return ret; 1402473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1403473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1404910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmannstatic int bpf_find_map_by_id(struct bpf_elf_ctx *ctx, uint32_t id) 1405910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann{ 1406910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann int i; 1407910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 1408910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) 1409910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (ctx->map_fds[i] && ctx->maps[i].id == id && 1410910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ctx->maps[i].type == BPF_MAP_TYPE_PROG_ARRAY) 1411910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann return i; 1412910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann return -1; 1413910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann} 1414910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 141532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx) 1416473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 141732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 141832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint32_t map_id, key_id; 1419910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann int fd, i, ret, idx; 1420473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 142132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 142232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 1423473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1424473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 142532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 1426473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1427473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1428473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1429910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ret = sscanf(data.sec_name, "%i/%i", &map_id, &key_id); 1430910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (ret != 2) 143132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 1432910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 1433910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann idx = bpf_find_map_by_id(ctx, map_id); 1434910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (idx < 0) 1435473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1436473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 143732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, data.sec_name); 143832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 1439473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -EIO; 1440473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1441910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ret = bpf_map_update(ctx->map_fds[idx], &key_id, 1442910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann &fd, BPF_ANY); 1443473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1444473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -ENOENT; 1445473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 144632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 1447473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 1448473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1449473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return 0; 1450473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1451473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 145232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_save_finfo(struct bpf_elf_ctx *ctx) 145311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 145432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat st; 145532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 145611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 145732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&ctx->stat, 0, sizeof(ctx->stat)); 145811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 145932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ctx->obj_fd, &st); 146032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 146132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Stat of elf file failed: %s\n", 146232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 146332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return; 146432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 146511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 146632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_dev = st.st_dev; 146732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_ino = st.st_ino; 146832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 146932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1470f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_read_pin_mapping(FILE *fp, uint32_t *id, char *path) 1471f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1472f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char buff[PATH_MAX]; 1473f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1474f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (fgets(buff, sizeof(buff), fp)) { 1475f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char *ptr = buff; 1476f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1477f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (*ptr == ' ' || *ptr == '\t') 1478f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ptr++; 1479f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1480f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (*ptr == '#' || *ptr == '\n' || *ptr == 0) 1481f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1482f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1483f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (sscanf(ptr, "%i %s\n", id, path) != 2 && 1484f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sscanf(ptr, "%i %s #", id, path) != 2) { 1485f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcpy(path, ptr); 1486f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return -1; 1487f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1488f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1489f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 1; 1490f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1491f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1492f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1493f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1494f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1495f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic bool bpf_pinning_reserved(uint32_t pinning) 1496f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1497f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann switch (pinning) { 1498f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_NONE: 1499f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_OBJECT_NS: 1500f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_GLOBAL_NS: 1501f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return true; 1502f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 1503f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return false; 1504f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1505f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1506f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1507f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file) 1508f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1509f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 1510f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char subpath[PATH_MAX]; 1511f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning; 1512f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann FILE *fp; 1513f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret; 1514f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1515f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fp = fopen(db_file, "r"); 1516f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!fp) 1517f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return; 1518f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1519f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann memset(subpath, 0, sizeof(subpath)); 1520f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while ((ret = bpf_read_pin_mapping(fp, &pinning, subpath))) { 1521f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret == -1) { 1522f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "Database %s is corrupted at: %s\n", 1523f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann db_file, subpath); 1524f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fclose(fp); 1525f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return; 1526f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1527f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1528f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_pinning_reserved(pinning)) { 1529f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "Database %s, id %u is reserved - " 1530f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann "ignoring!\n", db_file, pinning); 1531f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1532f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1533f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1534f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = malloc(sizeof(*entry)); 1535f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!entry) { 1536f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "No memory left for db entry!\n"); 1537f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1538f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1539f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1540f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->pinning = pinning; 1541f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->subpath = strdup(subpath); 1542f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!entry->subpath) { 1543f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "No memory left for db entry!\n"); 1544f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free(entry); 1545f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1546f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1547f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1548f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->next = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)]; 1549f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)] = entry; 1550f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1551f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1552f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fclose(fp); 1553f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1554f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1555f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic void bpf_hash_destroy(struct bpf_elf_ctx *ctx) 1556f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1557f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 1558f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int i; 1559f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1560f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->ht); i++) { 1561f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while ((entry = ctx->ht[i]) != NULL) { 1562f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->ht[i] = entry->next; 1563f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free((char *)entry->subpath); 1564f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free(entry); 1565f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1566f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1567f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1568f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 15698187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmannstatic int bpf_elf_check_ehdr(const struct bpf_elf_ctx *ctx) 15708187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann{ 15718187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann if (ctx->elf_hdr.e_type != ET_REL || 15728187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann ctx->elf_hdr.e_machine != 0 || 15738187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann ctx->elf_hdr.e_version != EV_CURRENT) { 15748187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann fprintf(stderr, "ELF format error, ELF file not for eBPF?\n"); 15758187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann return -EINVAL; 15768187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann } 15778187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 15788187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann switch (ctx->elf_hdr.e_ident[EI_DATA]) { 15798187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann default: 15808187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann fprintf(stderr, "ELF format error, wrong endianness info?\n"); 15818187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann return -EINVAL; 15828187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann case ELFDATA2LSB: 15838187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann if (htons(1) == 1) { 15848187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann fprintf(stderr, 15858187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann "We are big endian, eBPF object is little endian!\n"); 15868187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann return -EIO; 15878187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann } 15888187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann break; 15898187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann case ELFDATA2MSB: 15908187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann if (htons(1) != 1) { 15918187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann fprintf(stderr, 15928187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann "We are little endian, eBPF object is big endian!\n"); 15938187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann return -EIO; 15948187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann } 15958187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann break; 15968187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann } 15978187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 15988187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann return 0; 15998187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann} 16008187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 160132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, 160232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type, bool verbose) 160332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 160432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret = -EINVAL; 160532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 160632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (elf_version(EV_CURRENT) == EV_NONE || 160732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_init_env(pathname)) 160832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 160932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 161032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(ctx, 0, sizeof(*ctx)); 161132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->verbose = verbose; 161232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->type = type; 161332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 161432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->obj_fd = open(pathname, O_RDONLY); 161532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->obj_fd < 0) 161632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->obj_fd; 161732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 161832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->elf_fd = elf_begin(ctx->obj_fd, ELF_C_READ, NULL); 161932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->elf_fd) { 162011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EINVAL; 162132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_fd; 162211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 162311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 16248187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann if (elf_kind(ctx->elf_fd) != ELF_K_ELF) { 16258187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann ret = -EINVAL; 16268187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann goto out_fd; 16278187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann } 16288187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 162932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getehdr(ctx->elf_fd, &ctx->elf_hdr) != 163032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann &ctx->elf_hdr) { 163111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EIO; 163211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 163311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 163411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 16358187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann ret = bpf_elf_check_ehdr(ctx); 16368187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann if (ret < 0) 16378187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann goto out_elf; 16388187b012731cf2699c0abd5c88673bdaebca53b2Daniel Borkmann 163932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done = calloc(ctx->elf_hdr.e_shnum, 164032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(*(ctx->sec_done))); 164132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->sec_done) { 164211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -ENOMEM; 164311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 164411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 164511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 164632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_save_finfo(ctx); 1647f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_hash_init(ctx, CONFDIR "/bpf_pinning"); 1648f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 164932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 165032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_elf: 165132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 165232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_fd: 165332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 165432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 165532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 1656d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann 165732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_count(struct bpf_elf_ctx *ctx) 165832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 165932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, count = 0; 166011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 166132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 166232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[i]) 166332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 166432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann count++; 166532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 1666473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 166732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return count; 166832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 16696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 167032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_maps_teardown(struct bpf_elf_ctx *ctx) 167132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 167232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i; 167332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 167432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 167532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_fds[i]) 167632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->map_fds[i]); 1677473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 167832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 167932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 168032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) 168132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 168232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (failure) 168332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 1684473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1685f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_hash_destroy(ctx); 168632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann free(ctx->sec_done); 168732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 168832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 168932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 16906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 169132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic struct bpf_elf_ctx __ctx; 16926256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 169332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *pathname, enum bpf_prog_type type, 169432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *section, bool verbose) 169532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 169632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 169732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd = 0, ret; 16986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 169932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_elf_ctx_init(ctx, pathname, type, verbose); 170032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 170132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot initialize ELF context!\n"); 170232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 170332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 17046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 170532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_ancillary(ctx); 170632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 170732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching ELF ancillary data!\n"); 170832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 170932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 171032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 171132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, section); 171232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) { 171332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching program/map!\n"); 171432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fd; 171532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 171632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 171732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 171832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_prog_arrays(ctx); 171932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 172032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error filling program arrays!\n"); 172111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannout: 172232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_elf_ctx_destroy(ctx, ret < 0); 172332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 172432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd) 172532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 172632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 172732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 172832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 172932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 17306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 173111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 17326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int 17334bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len, 17344bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann const struct bpf_map_data *aux, unsigned int entries) 17356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 17366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_set_msg msg; 17376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int *cmsg_buf, min_fd; 17386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann char *amsg_buf; 17396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int i; 17406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&msg, 0, sizeof(msg)); 17426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann msg.aux.uds_ver = BPF_SCM_AUX_VER; 17444bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann msg.aux.num_ent = entries; 17456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name)); 17476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st)); 17486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, addr, addr_len); 17506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 17516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17524bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < entries; i += min_fd) { 17536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int ret; 17546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i); 17566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 17576256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd); 17596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd); 17606256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = sendmsg(fd, &msg.hdr, 0); 17626256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret <= 0) 17636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret ? : -1; 17646256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 17656256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17666256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return 0; 176711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 176811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 17694bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic int 17704bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_recv(int fd, int *fds, struct bpf_map_aux *aux, 17714bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 17724bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 17734bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct bpf_map_set_msg msg; 17744bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int *cmsg_buf, min_fd; 17754bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann char *amsg_buf, *mmsg_buf; 17764bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int needed = 1; 17774bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int i; 17784bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17794bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, NULL, 0); 17804bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 17814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann mmsg_buf = (char *)&msg.aux; 17824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17834bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < min(entries, needed); i += min_fd) { 17844bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct cmsghdr *cmsg; 17854bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int ret; 17864bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17874bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(entries, entries - i); 17884bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 17894bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17904bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = recvmsg(fd, &msg.hdr, 0); 17914bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret <= 0) 17924bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret ? : -1; 17934bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17944bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg = CMSG_FIRSTHDR(&msg.hdr); 17954bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) 17964bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 17974bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.hdr.msg_flags & MSG_CTRUNC) 17984bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EIO; 17994bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.aux.uds_ver != BPF_SCM_AUX_VER) 18004bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -ENOSYS; 18014bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18024bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd); 18034bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (min_fd > entries || min_fd <= 0) 18044bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 18054bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18064bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd); 18074bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd); 18084bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent)); 18094bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18104bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann needed = aux->num_ent; 18114bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 18124bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18134bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return 0; 18144bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 18154bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18164bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_send_map_fds(const char *path, const char *obj) 18176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 181832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 18196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct sockaddr_un addr; 18206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_data bpf_aux; 18216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int fd, ret; 18226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 18246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (fd < 0) { 18256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 18266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strerror(errno)); 18276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 18286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 18296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&addr, 0, sizeof(addr)); 18316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann addr.sun_family = AF_UNIX; 18326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 18336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); 18356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) { 18366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot connect to %s: %s\n", 18376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 18386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 18396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 18406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&bpf_aux, 0, sizeof(bpf_aux)); 18426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 184332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.fds = ctx->map_fds; 184432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.ent = ctx->maps; 184532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.st = &ctx->stat; 18466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_aux.obj = obj; 18476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18484bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux, 184932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_count(ctx)); 18506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) 18514bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot send fds to %s: %s\n", 18524bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann path, strerror(errno)); 18534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 185432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 18554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann close(fd); 18564bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret; 18574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 18584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, 18604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 18614bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 18624bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct sockaddr_un addr; 18634bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int fd, ret; 18644bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18654bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 18664bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (fd < 0) { 18674bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 18684bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 18694bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 18704bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 18714bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18724bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memset(&addr, 0, sizeof(addr)); 18734bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann addr.sun_family = AF_UNIX; 18744bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 18754bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18764bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 18774bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) { 18784bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot bind to socket: %s\n", 18794bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 18804bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 18814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 18824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18834bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_recv(fd, fds, aux, entries); 18844bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) 18854bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot recv fds from %s: %s\n", 18866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 18876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18884bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unlink(addr.sun_path); 18896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann close(fd); 18906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret; 18916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 189211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif /* HAVE_ELF */ 1893