tc_bpf.c revision fd7f9c7fd11fa926bda2edc8bc492e7515753a32
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 421d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "utils.h" 436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_elf.h" 456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_scm.h" 466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_util.h" 481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko#include "tc_bpf.h" 491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 5032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#ifdef HAVE_ELF 5132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *path, enum bpf_prog_type type, 5232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec, bool verbose); 5332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#else 5432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *path, enum bpf_prog_type type, 5532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec, bool verbose) 5632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 5732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "No ELF library support compiled in.\n"); 5832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = ENOSYS; 5932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 6032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 6132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#endif 6232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 6332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic inline __u64 bpf_ptr_to_u64(const void *ptr) 6432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 6532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return (__u64)(unsigned long)ptr; 6632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 6732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 6832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf(int cmd, union bpf_attr *attr, unsigned int size) 6932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 7032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#ifdef __NR_bpf 7132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return syscall(__NR_bpf, cmd, attr, size); 7232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#else 7332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "No bpf syscall, kernel headers too old?\n"); 7432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = ENOSYS; 7532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 7632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#endif 7732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 7832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 7991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_map_update(int fd, const void *key, const void *value, 8091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann uint64_t flags) 8132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 8232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 8391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .map_fd = fd, 8491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .key = bpf_ptr_to_u64(key), 8591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .value = bpf_ptr_to_u64(value), 8691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .flags = flags, 8732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 8832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 8991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 9032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 9132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 9232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, 9332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char **bpf_string, bool *need_release, 9432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char separator) 951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char sp; 971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (from_file) { 991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); 1001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *tmp_string; 1011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko FILE *fp; 1021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; 1041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_string = malloc(tmp_len); 1051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (tmp_string == NULL) 1061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOMEM; 1071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1081d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko memset(tmp_string, 0, tmp_len); 1091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fp = fopen(arg, "r"); 1111d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (fp == NULL) { 1121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko perror("Cannot fopen"); 1131d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1141d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOENT; 1151d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1161d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1171d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (!fgets(tmp_string, tmp_len, fp)) { 1181d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1191d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1201d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EIO; 1211d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1221d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1231d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1241d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1251d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = true; 1261d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = tmp_string; 1271d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } else { 1281d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = false; 1291d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = arg; 1301d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1311d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1321d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || 1331d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko sp != separator) { 1341d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (*need_release) 1351d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(*bpf_string); 1361d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1371d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1381d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1391d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return 0; 1401d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1411d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 14232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops, 14332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool from_file) 1441d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1451d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *bpf_string, *token, separator = ','; 1461d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int ret = 0, i = 0; 1471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko bool need_release; 1481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko __u16 bpf_len = 0; 1491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (argc < 1) 1511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1521d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, 1531d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &need_release, separator)) 1541d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1551d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { 1561d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1571d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1581d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1591d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1601d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko token = bpf_string; 1611d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko while ((token = strchr(token, separator)) && (++token)[0]) { 1621d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i >= bpf_len) { 1631d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Real program length exceeds encoded " 1641d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1651d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1661d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1671d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1681d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1691d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(token, "%hu %hhu %hhu %u,", 1701d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].code, &bpf_ops[i].jt, 1711d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { 1721d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Error at instruction %d!\n", i); 1731d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1741d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1751d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1761d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1771d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko i++; 1781d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1791d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1801d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i != bpf_len) { 1811d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Parsed program length is less than encoded" 1821d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1831d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1841d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1851d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1861d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = bpf_len; 1871d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoout: 1881d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (need_release) 1891d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(bpf_string); 1901d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1911d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return ret; 1921d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1931d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1941d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkovoid bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) 1951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); 1971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int i; 1981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (len == 0) 2001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return; 2011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "bytecode \'%u,", len); 2031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko for (i = 0; i < len - 1; i++) 2051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, 2061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2086256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt, 2091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 21111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 21291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map, 21391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int length) 2149e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann{ 2159e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann char file[PATH_MAX], buff[4096]; 2169e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann struct bpf_elf_map tmp, zero; 2179e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann unsigned int val; 2189e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann FILE *fp; 2199e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2209e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd); 2219e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2229e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fp = fopen(file, "r"); 2239e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (!fp) { 2249e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "No procfs support?!\n"); 2259e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return -EIO; 2269e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2279e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2289e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann memset(&tmp, 0, sizeof(tmp)); 2299e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann while (fgets(buff, sizeof(buff), fp)) { 2309e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (sscanf(buff, "map_type:\t%u", &val) == 1) 2319e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.type = val; 2329e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "key_size:\t%u", &val) == 1) 2339e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.size_key = val; 2349e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "value_size:\t%u", &val) == 1) 2359e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.size_value = val; 2369e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann else if (sscanf(buff, "max_entries:\t%u", &val) == 1) 2379e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann tmp.max_elem = val; 2389e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2399e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2409e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fclose(fp); 2419e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 24291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!memcmp(&tmp, map, length)) { 2439e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return 0; 2449e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } else { 2459e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann memset(&zero, 0, sizeof(zero)); 2469e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann /* If kernel doesn't have eBPF-related fdinfo, we cannot do much, 2479e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * so just accept it. We know we do have an eBPF fd and in this 2489e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * case, everything is 0. It is guaranteed that no such map exists 2499e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann * since map type of 0 is unloadable BPF_MAP_TYPE_UNSPEC. 2509e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann */ 25191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!memcmp(&tmp, &zero, length)) 2529e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return 0; 2539e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 2549e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "Map specs from pinned file differ!\n"); 2559e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return -EINVAL; 2569e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 2579e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann} 2589e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann 25991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_mnt_fs(const char *target) 26091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 26191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bool bind_done = false; 26291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 26391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) { 26491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (errno != EINVAL || bind_done) { 26591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount --make-private %s failed: %s\n", 26691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, strerror(errno)); 26791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 26891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 26991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 27091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mount(target, target, "none", MS_BIND, NULL)) { 27191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount --bind %s %s failed: %s\n", 27291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, target, strerror(errno)); 27391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 27491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 27591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 27691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bind_done = true; 27791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 27891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 27991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mount("bpf", target, "bpf", 0, NULL)) { 28091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mount -t bpf bpf %s failed: %s\n", 28191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann target, strerror(errno)); 28291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 28391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 28491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 28591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return 0; 28691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 28791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 28832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_valid_mntpt(const char *mnt, unsigned long magic) 28932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 29032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct statfs st_fs; 29132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 29232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (statfs(mnt, &st_fs) < 0) 29332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 29432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if ((unsigned long)st_fs.f_type != magic) 29532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 29632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 29732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 29832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 29932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 30032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_find_mntpt(const char *fstype, unsigned long magic, 30132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char *mnt, int len, 30232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *known_mnts) 30332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 30432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *ptr; 30532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char type[100]; 30632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann FILE *fp; 30732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 30832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (known_mnts) { 30932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr = known_mnts; 31032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (*ptr) { 31132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_valid_mntpt(*ptr, magic) == 0) { 31232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strncpy(mnt, *ptr, len - 1); 31332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt[len - 1] = 0; 31432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 31532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 31632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr++; 31732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 31832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 31932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 32032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fp = fopen("/proc/mounts", "r"); 32132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fp == NULL || len != PATH_MAX) 32232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 32332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 32432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (fscanf(fp, "%*s %" textify(PATH_MAX) "s %99s %*s %*d %*d\n", 32532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt, type) == 2) { 32632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) == 0) 32732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 32832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 32932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fclose(fp); 33132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) != 0) 33232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 33332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 33532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 33632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 33732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannint bpf_trace_pipe(void) 33832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 33932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tracefs_mnt[PATH_MAX] = TRACE_DIR_MNT; 34032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static const char * const tracefs_known_mnts[] = { 34132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann TRACE_DIR_MNT, 34232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/sys/kernel/debug/tracing", 34332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/tracing", 34432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/trace", 34532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 0, 34632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 34732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tpipe[PATH_MAX]; 34832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *mnt; 34932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 35032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 35132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt, 35232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(tracefs_mnt), tracefs_known_mnts); 35332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!mnt) { 35432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "tracefs not mounted?\n"); 35532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 35632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 35732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 35832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt); 35932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = open(tpipe, O_RDONLY); 36132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 36232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 36332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Running! Hang up with ^C!\n\n"); 36532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (1) { 36632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char buff[4096]; 36732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t ret; 36832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = read(fd, buff, sizeof(buff) - 1); 37032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret > 0) { 37132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann write(2, buff, ret); 37232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fflush(stderr); 37332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 37732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 37832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic const char *bpf_get_tc_dir(void) 38091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 38191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static bool bpf_mnt_cached = false; 38291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static char bpf_tc_dir[PATH_MAX]; 38391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static const char *mnt; 38491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann static const char * const bpf_known_mnts[] = { 38591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann BPF_DIR_MNT, 38691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 0, 38791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 38891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char bpf_mnt[PATH_MAX] = BPF_DIR_MNT; 38991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char bpf_glo_dir[PATH_MAX]; 39091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret; 39191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 39291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (bpf_mnt_cached) 39391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto done; 39491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 39591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_mnt, sizeof(bpf_mnt), 39691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_known_mnts); 39791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!mnt) { 39891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = getenv(BPF_ENV_MNT); 39991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (!mnt) 40091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = BPF_DIR_MNT; 40191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_mnt_fs(mnt); 40291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret) { 40391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 40491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 40591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 40691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 40791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 40891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(bpf_tc_dir, sizeof(bpf_tc_dir), "%s/%s", mnt, BPF_DIR_TC); 40991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = mkdir(bpf_tc_dir, S_IRWXU); 41091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret && errno != EEXIST) { 41191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_tc_dir, 41291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strerror(errno)); 41391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 41491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 41591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 41691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 41791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s", 41891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_tc_dir, BPF_DIR_GLOBALS); 41991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = mkdir(bpf_glo_dir, S_IRWXU); 42091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret && errno != EEXIST) { 42191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir, 42291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strerror(errno)); 42391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = NULL; 42491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out; 42591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 42691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 42791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann mnt = bpf_tc_dir; 42891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout: 42991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_mnt_cached = true; 43091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmanndone: 43191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return mnt; 43291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 43391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 43491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_obj_get(const char *pathname) 43591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 43691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann union bpf_attr attr; 43791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char tmp[PATH_MAX]; 43891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 43991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (strlen(pathname) > 2 && pathname[0] == 'm' && 44091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann pathname[1] == ':' && bpf_get_tc_dir()) { 44191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann snprintf(tmp, sizeof(tmp), "%s/%s", 44291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann bpf_get_tc_dir(), pathname + 2); 44391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann pathname = tmp; 44491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 44591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 44691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann memset(&attr, 0, sizeof(attr)); 44791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann attr.pathname = bpf_ptr_to_u64(pathname); 44891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 44991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 45091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 45191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 4526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannconst char *bpf_default_section(const enum bpf_prog_type type) 45311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 45411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann switch (type) { 45511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann case BPF_PROG_TYPE_SCHED_CLS: 45611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ELF_SECTION_CLASSIFIER; 4576256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann case BPF_PROG_TYPE_SCHED_ACT: 4586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ELF_SECTION_ACTION; 45911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann default: 46011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return NULL; 46111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 46211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 46311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 46491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannenum bpf_mode { 46591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann CBPF_BYTECODE = 0, 46691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann CBPF_FILE, 46791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann EBPF_OBJECT, 46891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann EBPF_PINNED, 46991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann __BPF_MODE_MAX, 47091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann#define BPF_MODE_MAX __BPF_MODE_MAX 47191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann}; 47291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 47391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannstatic int bpf_parse(int *ptr_argc, char ***ptr_argv, const bool *opt_tbl, 47491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type *type, enum bpf_mode *mode, 47591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_object, const char **ptr_section, 47691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_uds_name, struct sock_filter *opcodes) 47732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 47832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *file, *section, *uds_name; 47932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose = false; 48091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret, argc; 48191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char **argv; 48291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 48391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann argv = *ptr_argv; 48491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann argc = *ptr_argc; 48591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 48691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (opt_tbl[CBPF_BYTECODE] && 48791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "bytecode") == 0 || 48891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "bc") == 0)) { 48991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = CBPF_BYTECODE; 49091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[CBPF_FILE] && 49191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "bytecode-file") == 0 || 49291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "bcf") == 0)) { 49391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = CBPF_FILE; 49491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[EBPF_OBJECT] && 49591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "object-file") == 0 || 49691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann strcmp(*argv, "obj") == 0)) { 49791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = EBPF_OBJECT; 49891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (opt_tbl[EBPF_PINNED] && 49991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann (matches(*argv, "object-pinned") == 0 || 50091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann matches(*argv, "pinned") == 0 || 50191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann matches(*argv, "fd") == 0)) { 50291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *mode = EBPF_PINNED; 50332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 50432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "What mode is \"%s\"?\n", *argv); 50532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 50632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 50732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 50832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 50932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = section = uds_name = NULL; 51091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) { 51132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = *argv; 51232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 51332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 51491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*type == BPF_PROG_TYPE_UNSPEC) { 51591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (argc > 0 && matches(*argv, "type") == 0) { 51691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NEXT_ARG(); 51791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (matches(*argv, "cls") == 0) { 51891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_CLS; 51991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else if (matches(*argv, "act") == 0) { 52091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_ACT; 52191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 52291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "What type is \"%s\"?\n", 52391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *argv); 52491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return -1; 52591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 52691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NEXT_ARG_FWD(); 52791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 52891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *type = BPF_PROG_TYPE_SCHED_CLS; 52991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 53091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 53191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 53291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann section = bpf_default_section(*type); 53332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "section") == 0) { 53432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 53532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section = *argv; 53632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 53732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 53832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 53932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = getenv(BPF_ENV_UDS); 54032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && !uds_name && 54132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann matches(*argv, "export") == 0) { 54232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 54332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = *argv; 54432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 54532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 54632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 54732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "verbose") == 0) { 54832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann verbose = true; 54932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 55032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 55232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann PREV_ARG(); 55332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 55591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE) 55691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_ops_parse(argc, argv, opcodes, *mode == CBPF_FILE); 55791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else if (*mode == EBPF_OBJECT) 55891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_obj_open(file, *type, section, verbose); 55991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else if (*mode == EBPF_PINNED) 56032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_get(file); 56191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann else 56232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 56332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 56491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_object) 56591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_object = file; 56691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_section) 56791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_section = section; 56891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ptr_uds_name) 56991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_uds_name = uds_name; 57091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_argc = argc; 57291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann *ptr_argv = argv; 57391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 57591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 57691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 57791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannint bpf_parse_common(int *ptr_argc, char ***ptr_argv, const int *nla_tbl, 57891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type type, const char **ptr_object, 57991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char **ptr_uds_name, struct nlmsghdr *n) 58091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 58191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann struct sock_filter opcodes[BPF_MAXINSNS]; 58291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const bool opt_tbl[BPF_MODE_MAX] = { 58391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_BYTECODE] = true, 58491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_FILE] = true, 58591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_OBJECT] = true, 58691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_PINNED] = true, 58791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 58891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann char annotation[256]; 58991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char *section; 59091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_mode mode; 59191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret; 59291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 59391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_parse(ptr_argc, ptr_argv, opt_tbl, &type, &mode, 59491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ptr_object, §ion, ptr_uds_name, opcodes); 59591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) 59691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 59791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 59832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mode == CBPF_BYTECODE || mode == CBPF_FILE) { 59932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr16(n, MAX_MSG, nla_tbl[BPF_NLA_OPS_LEN], ret); 60032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr_l(n, MAX_MSG, nla_tbl[BPF_NLA_OPS], opcodes, 60132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret * sizeof(struct sock_filter)); 60291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 60391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 60491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (mode == EBPF_OBJECT || mode == EBPF_PINNED) { 60532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(annotation, sizeof(annotation), "%s:[%s]", 60691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann basename(*ptr_object), mode == EBPF_PINNED ? 60791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann "*fsobj" : section); 60832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 60932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr32(n, MAX_MSG, nla_tbl[BPF_NLA_FD], ret); 61032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattrstrz(n, MAX_MSG, nla_tbl[BPF_NLA_NAME], annotation); 61132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 61232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return 0; 61491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann} 61532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannint bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) 61791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann{ 61891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC; 61991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const bool opt_tbl[BPF_MODE_MAX] = { 62091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_BYTECODE] = false, 62191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [CBPF_FILE] = false, 62291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_OBJECT] = true, 62391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann [EBPF_PINNED] = true, 62491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 62591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const struct bpf_elf_map test = { 62691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .type = BPF_MAP_TYPE_PROG_ARRAY, 62791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .size_key = sizeof(int), 62891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann .size_value = sizeof(int), 62991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann }; 63091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann int ret, prog_fd, map_fd; 63191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann const char *section; 63291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann enum bpf_mode mode; 63391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann uint32_t map_key; 63491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 63591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann prog_fd = bpf_parse(&argc, &argv, opt_tbl, &type, &mode, 63691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann NULL, §ion, NULL, NULL); 63791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (prog_fd < 0) 63891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return prog_fd; 63991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (key) { 64091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_key = *key; 64191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } else { 64291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = sscanf(section, "%*i/%i", &map_key); 64391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret != 1) { 64491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Couldn\'t infer map key from section " 64591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann "name! Please provide \'key\' argument!\n"); 64691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = -EINVAL; 64791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_prog; 64891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 64991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 65032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 65191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_fd = bpf_obj_get(map_path); 65291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (map_fd < 0) { 65391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n", 65491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann map_path, strerror(errno)); 65591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = map_fd; 65691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_prog; 65791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 65891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 65991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_selfcheck_pinned(map_fd, &test, 66091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann offsetof(struct bpf_elf_map, max_elem)); 66191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) { 66291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path); 66391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann goto out_map; 66491d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann } 66591d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann 66691d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_update(map_fd, &map_key, &prog_fd, BPF_ANY); 66791d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann if (ret < 0) 66891d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann fprintf(stderr, "Map update failed: %s\n", strerror(errno)); 66991d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout_map: 67091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann close(map_fd); 67191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmannout_prog: 67291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann close(prog_fd); 67391d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann return ret; 67432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 67532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 6766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#ifdef HAVE_ELF 67732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_prog { 67832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 67932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_insn *insns; 68032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size; 68132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *license; 68232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 68332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 684f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstruct bpf_hash_entry { 685f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann unsigned int pinning; 686f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const char *subpath; 687f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *next; 688f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann}; 689f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 69032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_ctx { 69132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf *elf_fd; 69232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Ehdr elf_hdr; 69332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sym_tab; 69432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *str_tab; 69532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int obj_fd; 69632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_fds[ELF_MAX_MAPS]; 69732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map maps[ELF_MAX_MAPS]; 69832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sym_num; 69932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_num; 70032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool *sec_done; 70132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sec_maps; 70232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char license[ELF_MAX_LICENSE_LEN]; 70332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 70432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose; 70532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st stat; 706f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *ht[256]; 70732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 70832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 7096256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_elf_sec_data { 71032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr sec_hdr; 71132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_data; 71232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec_name; 7136256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 7146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 7156256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_map_data { 71632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int *fds; 71732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *obj; 71832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st *st; 71932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map *ent; 7206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 7216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 7226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* If we provide a small buffer with log level enabled, the kernel 7236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * could fail program load as no buffer space is available for the 7246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * log and thus verifier fails. In case something doesn't pass the 7256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * verifier we still want to hand something descriptive to the user. 7266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann */ 7276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic char bpf_log_buf[65536]; 7286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 72932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic __check_format_string(1, 2) void bpf_dump_error(const char *format, ...) 73011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 73111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_list vl; 73211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 73311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_start(vl, format); 73411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann vfprintf(stderr, format, vl); 73511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_end(vl); 73611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 737d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann if (bpf_log_buf[0]) { 738d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann fprintf(stderr, "%s\n", bpf_log_buf); 739d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann memset(bpf_log_buf, 0, sizeof(bpf_log_buf)); 740d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 74111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 74211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 74332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_create(enum bpf_map_type type, unsigned int size_key, 74411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann unsigned int size_value, unsigned int max_elem) 74511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 74611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 74711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .map_type = type, 74811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .key_size = size_key, 74911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .value_size = size_value, 75011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .max_entries = max_elem, 75111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 75211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 75311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 75411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 75511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 75611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, 75732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size, const char *license) 75811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 75911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 76011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .prog_type = type, 76111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .insns = bpf_ptr_to_u64(insns), 76232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .insn_cnt = size / sizeof(struct bpf_insn), 76311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .license = bpf_ptr_to_u64(license), 76411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_buf = bpf_ptr_to_u64(bpf_log_buf), 76511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_size = sizeof(bpf_log_buf), 76611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_level = 1, 76711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 76811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 76932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (getenv(BPF_ENV_NOLOG)) { 77032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_buf = 0; 77132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_size = 0; 77232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_level = 0; 77332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 77432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 77511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 77611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 77711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 77832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_pin(int fd, const char *pathname) 77911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 78032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 78132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .pathname = bpf_ptr_to_u64(pathname), 78232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .bpf_fd = fd, 78332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 78432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 78532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); 78632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 78711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 78832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_hash(const char *object, uint8_t *out, size_t len) 78932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 79032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct sockaddr_alg alg = { 79132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_family = AF_ALG, 79232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_type = "hash", 79332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_name = "sha1", 79432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 79532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, cfd, ofd, ffd; 79632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat stbuff; 79732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t size; 79832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 79932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!object || len != 20) 80032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 80132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 80232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann cfd = socket(AF_ALG, SOCK_SEQPACKET, 0); 80332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (cfd < 0) { 80432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot get AF_ALG socket: %s\n", 80532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 80632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return cfd; 80732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 80832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 80932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg)); 81032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 81132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error binding socket: %s\n", strerror(errno)); 81232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 81332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 81432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 81532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ofd = accept(cfd, NULL, 0); 81632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ofd < 0) { 81732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error accepting socket: %s\n", 81832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 81932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ofd; 82032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 82132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 82232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 82332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ffd = open(object, O_RDONLY); 82432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ffd < 0) { 82532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error opening object %s: %s\n", 82632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann object, strerror(errno)); 82732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ffd; 82832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ofd; 82932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 83032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 83132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ffd, &stbuff); 83232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 83332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error doing fstat: %s\n", 83432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 83532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 836d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 83711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 83832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = sendfile(ofd, ffd, NULL, stbuff.st_size); 83932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != stbuff.st_size) { 84032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n", 84132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, stbuff.st_size, strerror(errno)); 84232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 84332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 84432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 84532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 84632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = read(ofd, out, len); 84732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != len) { 84832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n", 84932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, len, strerror(errno)); 85032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 85132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 85232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = 0; 85332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 85432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ffd: 85532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ffd); 85632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ofd: 85732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ofd); 85832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_cfd: 85932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(cfd); 86032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 86111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 86211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 86332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_get_obj_uid(const char *pathname) 86411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 86532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static bool bpf_uid_cached = false; 86632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char bpf_uid[64]; 86732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint8_t tmp[20]; 86832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 86911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 87032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_uid_cached) 87132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto done; 87211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 87332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); 87432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret) { 87532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Object hashing failed!\n"); 87632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 87732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 87832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 87932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid)); 88032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_uid_cached = true; 88132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmanndone: 88232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_uid; 88311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 88411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 88532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_init_env(const char *pathname) 88632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 88732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct rlimit limit = { 88832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_cur = RLIM_INFINITY, 88932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_max = RLIM_INFINITY, 89032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 89132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 89232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* Don't bother in case we fail! */ 89332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann setrlimit(RLIMIT_MEMLOCK, &limit); 89432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 89532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_tc_dir()) { 89632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Continuing without mounted eBPF fs. " 89732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "Too old kernel?\n"); 89832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 89932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 90032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 90132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_obj_uid(pathname)) 90232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 90332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 90432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 9056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 9066256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 907f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic const char *bpf_custom_pinning(const struct bpf_elf_ctx *ctx, 908f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 909f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 910f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 911f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 912f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)]; 913f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (entry && entry->pinning != pinning) 914f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = entry->next; 915f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 916f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return entry ? entry->subpath : NULL; 917f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 918f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 919f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic bool bpf_no_pinning(const struct bpf_elf_ctx *ctx, 920f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 92111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 92232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 92332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 92432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 92532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return false; 92632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_NONE: 92732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return true; 928f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 929f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return !bpf_custom_pinning(ctx, pinning); 93032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 93132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 93232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 93332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_make_pathname(char *pathname, size_t len, const char *name, 934f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, uint32_t pinning) 93532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 93632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 93732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 93832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 93932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_get_obj_uid(NULL), name); 94032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 94132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 94232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 94332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann BPF_DIR_GLOBALS, name); 94432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 945f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 946f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(pathname, len, "%s/../%s/%s", bpf_get_tc_dir(), 947f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_custom_pinning(ctx, pinning), name); 948f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann break; 94932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 95032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 95132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 952f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_probe_pinned(const char *name, const struct bpf_elf_ctx *ctx, 953f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning) 95432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 95532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char pathname[PATH_MAX]; 95632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 957f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir()) 95832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 95932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 960f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning); 96132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_get(pathname); 96232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 96332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 964f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_make_obj_path(void) 96532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 966f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char tmp[PATH_MAX]; 96732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 96832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 969f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_tc_dir(), 970f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_get_obj_uid(NULL)); 971f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 972f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = mkdir(tmp, S_IRWXU); 973f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret && errno != EEXIST) { 974f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", tmp, strerror(errno)); 975f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return ret; 976f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 977f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 978f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 979f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 980f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 981f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_make_custom_path(const char *todo) 982f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 983f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char tmp[PATH_MAX], rem[PATH_MAX], *sub; 984f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret; 985f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 986f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(tmp, sizeof(tmp), "%s/../", bpf_get_tc_dir()); 987f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann snprintf(rem, sizeof(rem), "%s/", todo); 988f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sub = strtok(rem, "/"); 98932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 990f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (sub) { 991f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (strlen(tmp) + strlen(sub) + 2 > PATH_MAX) 992f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return -EINVAL; 993f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 994f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcat(tmp, sub); 995f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcat(tmp, "/"); 99632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 997f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = mkdir(tmp, S_IRWXU); 99832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret && errno != EEXIST) { 999f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", tmp, 100032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 100132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 100232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 1003f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1004f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sub = strtok(NULL, "/"); 100532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 100632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1007f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1008f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1009f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1010f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_place_pinned(int fd, const char *name, 1011f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, uint32_t pinning) 1012f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1013f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char pathname[PATH_MAX]; 1014f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const char *tmp; 1015f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret = 0; 1016f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1017f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_no_pinning(ctx, pinning) || !bpf_get_tc_dir()) 1018f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1019f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1020f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (pinning == PIN_OBJECT_NS) 1021f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_make_obj_path(); 1022f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann else if ((tmp = bpf_custom_pinning(ctx, pinning))) 1023f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_make_custom_path(tmp); 1024f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret < 0) 1025f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return ret; 1026f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1027f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, ctx, pinning); 102832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_pin(fd, pathname); 102932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 103032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 103132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_prog_attach(const char *section, 103232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_elf_prog *prog, bool verbose) 103332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 103432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 103532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 103632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* We can add pinning here later as well, same as bpf_map_attach(). */ 103732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 103832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_load(prog->type, prog->insns, prog->size, 103932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->license); 104032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 104132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Prog section \'%s\' (type:%u insns:%zu " 104232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "license:\'%s\') %s%s (%d)!\n\n", 104332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section, prog->type, 104432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->size / sizeof(struct bpf_insn), 1045fd7f9c7fd11fa926bda2edc8bc492e7515753a32Daniel Borkmann prog->license, fd < 0 ? "rejected: " : 104632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "loaded", fd < 0 ? strerror(errno) : "", 104732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? errno : fd); 104832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 104932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 105032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 105132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 105232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 105332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_attach(const char *name, const struct bpf_elf_map *map, 1054f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann const struct bpf_elf_ctx *ctx, bool verbose) 105532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 105632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd, ret; 105732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1058f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fd = bpf_probe_pinned(name, ctx, map->pinning); 105932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd > 0) { 106091d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann ret = bpf_map_selfcheck_pinned(fd, map, 106191d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann offsetof(struct bpf_elf_map, 106291d88eeb10cd4f51e3b5c675c7aee4ae1e41ff16Daniel Borkmann id)); 10639e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann if (ret < 0) { 10649e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann close(fd); 10659e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann fprintf(stderr, "Map \'%s\' self-check failed!\n", 10669e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann name); 10679e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann return ret; 10689e607f2e722604a57a2c1ec9a174fcc505d9c451Daniel Borkmann } 106932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (verbose) 107032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' loaded as pinned!\n", 107132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name); 107232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 107332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 107432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 107532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 107632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_map_create(map->type, map->size_key, map->size_value, 107732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->max_elem); 107832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 107932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Map \'%s\' (type:%u id:%u pinning:%u " 108032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "ksize:%u vsize:%u max-elems:%u) %s%s (%d)!\n", 108132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name, map->type, map->id, map->pinning, 108232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->size_key, map->size_value, map->max_elem, 108332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? "rejected: " : "loaded", fd < 0 ? 108432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno) : "", fd < 0 ? errno : fd); 108532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 108632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 108732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 108832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1089f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ret = bpf_place_pinned(fd, name, ctx, map->pinning); 109032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 && errno != EEXIST) { 109132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Could not pin %s map: %s\n", name, 109232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 109332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 109432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 109532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 109632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 109732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 109832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 109932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_BIND(x) ((x) >> 4) 110132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) 110232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx, 110432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const GElf_Sym *sym) 110532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 110632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->str_tab->d_buf + sym->st_name; 110732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 110832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) 111032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 111132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 111211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann int i; 111311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 111432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->sym_num; i++) { 111532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) 111632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 111732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 111832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (__ELF_ST_BIND(sym.st_info) != STB_GLOBAL || 111932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann __ELF_ST_TYPE(sym.st_info) != STT_NOTYPE || 112032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_shndx != ctx->sec_maps || 112132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_value / sizeof(struct bpf_elf_map) != which) 112232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 112332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 112432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_str_tab_name(ctx, &sym); 112511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 112632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 112732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 112811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 112911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 113032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_attach_all(struct bpf_elf_ctx *ctx) 113111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 113232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *map_name; 113332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, fd; 113411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 113532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->map_num; i++) { 113632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map_name = bpf_map_fetch_name(ctx, i); 113732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!map_name) 113832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 113911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 1140f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fd = bpf_map_attach(map_name, &ctx->maps[i], ctx, 1141f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->verbose); 114232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 114332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 114411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 114532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_fds[i] = fd; 114611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 114711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 114811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 114911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 115011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 115132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_section_data(struct bpf_elf_ctx *ctx, int section, 115232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 115311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 115432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_edata; 115511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann GElf_Shdr sec_hdr; 115611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann Elf_Scn *sec_fd; 115711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann char *sec_name; 115811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 115932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(data, 0, sizeof(*data)); 116011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 116132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_fd = elf_getscn(ctx->elf_fd, section); 116211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_fd) 116311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EINVAL; 116411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr) 116511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 116611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 116732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_name = elf_strptr(ctx->elf_fd, ctx->elf_hdr.e_shstrndx, 116811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_hdr.sh_name); 116911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_name || !sec_hdr.sh_size) 117011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -ENOENT; 117111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 117211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_edata = elf_getdata(sec_fd, NULL); 117311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_edata || elf_getdata(sec_fd, sec_edata)) 117411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 117511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 117632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(&data->sec_hdr, &sec_hdr, sizeof(sec_hdr)); 117711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 117832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_name = sec_name; 117932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_data = sec_edata; 118011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 118111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 118211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_maps(struct bpf_elf_ctx *ctx, int section, 118432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 118511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 118632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size % sizeof(struct bpf_elf_map) != 0) 118732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 118811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_num = data->sec_data->d_size / sizeof(struct bpf_elf_map); 119032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_maps = section; 119132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 119211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 119332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_num > ARRAY_SIZE(ctx->map_fds)) { 119432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Too many BPF maps in ELF section!\n"); 119532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 119632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 119711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 119832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->maps, data->sec_data->d_buf, data->sec_data->d_size); 119932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 120032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 120111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 120232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_license(struct bpf_elf_ctx *ctx, int section, 120332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 120432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 120532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size > sizeof(ctx->license)) 120632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 120711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 120832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->license, data->sec_data->d_buf, data->sec_data->d_size); 120932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 121032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 121132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 121211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 121332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_symtab(struct bpf_elf_ctx *ctx, int section, 121432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 121532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 121632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_tab = data->sec_data; 121732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_num = data->sec_hdr.sh_size / data->sec_hdr.sh_entsize; 121832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 121911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 122011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 122111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 122232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section, 122332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 122411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 122532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->str_tab = data->sec_data; 122632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 122732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 122832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 122911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 123032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx) 123132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 123232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 123332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, ret = -1; 123411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 123532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 123632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 123711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (ret < 0) 123811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 123911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 124032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!strcmp(data.sec_name, ELF_SECTION_MAPS)) 124132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_maps(ctx, i, &data); 124232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (!strcmp(data.sec_name, ELF_SECTION_LICENSE)) 124332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_license(ctx, i, &data); 124432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_SYMTAB) 124532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_symtab(ctx, i, &data); 124632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_STRTAB && 124732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann i != ctx->elf_hdr.e_shstrndx) 124832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_strtab(ctx, i, &data); 124932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 125032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error parsing section %d! Perhaps" 125132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "check with readelf -a?\n", i); 125232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 125311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 125432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 125532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 125632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) { 125732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_maps_attach_all(ctx); 125832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 125932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error loading maps into kernel!\n"); 126032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 126111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 126211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 126311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 126411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ret; 126511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 126611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 126732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section) 126811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 126932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 127032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 127132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, i, fd = -1; 127211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 127332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 127432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 127511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 127611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 127732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 127832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || strcmp(data.sec_name, section)) 127911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 128011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 128132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 128232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 128332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data.sec_data->d_buf; 128432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data.sec_data->d_size; 128532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 128611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 128732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 128832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 128911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 129011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 129132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 129211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 129311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 129411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 129532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 129611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 129711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 129832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_apply_relo_data(struct bpf_elf_ctx *ctx, 129932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_relo, 130032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_insn) 130111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 130232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *idata = data_insn->sec_data; 130332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr *rhdr = &data_relo->sec_hdr; 130432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize; 130532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_insn *insns = idata->d_buf; 130632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int num_insns = idata->d_size / sizeof(*insns); 130711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 130832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (relo_ent = 0; relo_ent < relo_num; relo_ent++) { 130932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int ioff, rmap; 131032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Rel relo; 131132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 131232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 131332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo) 131432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 131532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 131632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ioff = relo.r_offset / sizeof(struct bpf_insn); 131732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ioff >= num_insns || 131832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) 131932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 132032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 132132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym) 132232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 132332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 132432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann rmap = sym.st_value / sizeof(struct bpf_elf_map); 132532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (rmap >= ARRAY_SIZE(ctx->map_fds)) 132632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 132732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[rmap]) 132832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 132932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 133032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->verbose) 133132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' (%d) injected into prog " 133232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "section \'%s\' at offset %u!\n", 133332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap], 133432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data_insn->sec_name, ioff); 133511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 133632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].src_reg = BPF_PSEUDO_MAP_FD; 133732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].imm = ctx->map_fds[rmap]; 133832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 133932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 134032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 134132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 134232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 134332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section) 134432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 134532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data_relo, data_insn; 134632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 134732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, idx, i, fd = -1; 134832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 134932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 135032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data_relo); 135132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL) 135211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 135311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 135432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann idx = data_relo.sec_hdr.sh_info; 135532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, idx, &data_insn); 135632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || strcmp(data_insn.sec_name, section)) 135711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 135832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 135932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn); 136032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 136111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 136211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 136332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 136432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 136532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data_insn.sec_data->d_buf; 136632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data_insn.sec_data->d_size; 136732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 136832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 136932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 137032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 137111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 137211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 137332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 137432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[idx] = true; 137511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 137611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 137711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 137832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 137911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 138011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 138132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section) 1382473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 1383473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann int ret = -1; 1384473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 138532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab) 138632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog_relo(ctx, section); 1387473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 138832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog(ctx, section); 138932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1390473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return ret; 1391473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1392473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1393910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmannstatic int bpf_find_map_by_id(struct bpf_elf_ctx *ctx, uint32_t id) 1394910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann{ 1395910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann int i; 1396910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 1397910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) 1398910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (ctx->map_fds[i] && ctx->maps[i].id == id && 1399910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ctx->maps[i].type == BPF_MAP_TYPE_PROG_ARRAY) 1400910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann return i; 1401910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann return -1; 1402910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann} 1403910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 140432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx) 1405473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 140632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 140732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint32_t map_id, key_id; 1408910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann int fd, i, ret, idx; 1409473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 141032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 141132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 1412473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1413473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 141432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 1415473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1416473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1417473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1418910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ret = sscanf(data.sec_name, "%i/%i", &map_id, &key_id); 1419910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (ret != 2) 142032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 1421910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann 1422910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann idx = bpf_find_map_by_id(ctx, map_id); 1423910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann if (idx < 0) 1424473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1425473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 142632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, data.sec_name); 142732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 1428473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -EIO; 1429473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1430910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann ret = bpf_map_update(ctx->map_fds[idx], &key_id, 1431910b543dcce52290ce723758e1d9bb436188a26bDaniel Borkmann &fd, BPF_ANY); 1432473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1433473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -ENOENT; 1434473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 143532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 1436473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 1437473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1438473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return 0; 1439473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1440473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 144132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_save_finfo(struct bpf_elf_ctx *ctx) 144211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 144332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat st; 144432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 144511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 144632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&ctx->stat, 0, sizeof(ctx->stat)); 144711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 144832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ctx->obj_fd, &st); 144932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 145032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Stat of elf file failed: %s\n", 145132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 145232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return; 145332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 145411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 145532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_dev = st.st_dev; 145632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_ino = st.st_ino; 145732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 145832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1459f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic int bpf_read_pin_mapping(FILE *fp, uint32_t *id, char *path) 1460f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1461f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char buff[PATH_MAX]; 1462f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1463f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (fgets(buff, sizeof(buff), fp)) { 1464f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char *ptr = buff; 1465f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1466f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while (*ptr == ' ' || *ptr == '\t') 1467f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ptr++; 1468f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1469f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (*ptr == '#' || *ptr == '\n' || *ptr == 0) 1470f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1471f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1472f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (sscanf(ptr, "%i %s\n", id, path) != 2 && 1473f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann sscanf(ptr, "%i %s #", id, path) != 2) { 1474f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann strcpy(path, ptr); 1475f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return -1; 1476f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1477f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1478f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 1; 1479f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1480f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1481f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return 0; 1482f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1483f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1484f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic bool bpf_pinning_reserved(uint32_t pinning) 1485f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1486f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann switch (pinning) { 1487f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_NONE: 1488f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_OBJECT_NS: 1489f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann case PIN_GLOBAL_NS: 1490f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return true; 1491f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann default: 1492f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return false; 1493f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1494f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1495f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1496f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file) 1497f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1498f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 1499f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann char subpath[PATH_MAX]; 1500f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann uint32_t pinning; 1501f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann FILE *fp; 1502f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int ret; 1503f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1504f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fp = fopen(db_file, "r"); 1505f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!fp) 1506f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return; 1507f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1508f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann memset(subpath, 0, sizeof(subpath)); 1509f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while ((ret = bpf_read_pin_mapping(fp, &pinning, subpath))) { 1510f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (ret == -1) { 1511f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "Database %s is corrupted at: %s\n", 1512f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann db_file, subpath); 1513f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fclose(fp); 1514f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann return; 1515f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1516f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1517f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (bpf_pinning_reserved(pinning)) { 1518f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "Database %s, id %u is reserved - " 1519f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann "ignoring!\n", db_file, pinning); 1520f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1521f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1522f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1523f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry = malloc(sizeof(*entry)); 1524f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!entry) { 1525f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "No memory left for db entry!\n"); 1526f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1527f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1528f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1529f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->pinning = pinning; 1530f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->subpath = strdup(subpath); 1531f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann if (!entry->subpath) { 1532f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fprintf(stderr, "No memory left for db entry!\n"); 1533f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free(entry); 1534f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann continue; 1535f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1536f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1537f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann entry->next = ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)]; 1538f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->ht[pinning & (ARRAY_SIZE(ctx->ht) - 1)] = entry; 1539f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1540f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1541f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann fclose(fp); 1542f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1543f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1544f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmannstatic void bpf_hash_destroy(struct bpf_elf_ctx *ctx) 1545f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann{ 1546f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann struct bpf_hash_entry *entry; 1547f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann int i; 1548f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 1549f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->ht); i++) { 1550f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann while ((entry = ctx->ht[i]) != NULL) { 1551f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann ctx->ht[i] = entry->next; 1552f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free((char *)entry->subpath); 1553f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann free(entry); 1554f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1555f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann } 1556f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann} 1557f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 155832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, 155932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type, bool verbose) 156032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 156132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret = -EINVAL; 156232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 156332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (elf_version(EV_CURRENT) == EV_NONE || 156432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_init_env(pathname)) 156532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 156632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 156732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(ctx, 0, sizeof(*ctx)); 156832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->verbose = verbose; 156932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->type = type; 157032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 157132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->obj_fd = open(pathname, O_RDONLY); 157232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->obj_fd < 0) 157332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->obj_fd; 157432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 157532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->elf_fd = elf_begin(ctx->obj_fd, ELF_C_READ, NULL); 157632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->elf_fd) { 157711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EINVAL; 157832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_fd; 157911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 158011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 158132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getehdr(ctx->elf_fd, &ctx->elf_hdr) != 158232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann &ctx->elf_hdr) { 158311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EIO; 158411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 158511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 158611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 158732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done = calloc(ctx->elf_hdr.e_shnum, 158832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(*(ctx->sec_done))); 158932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->sec_done) { 159011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -ENOMEM; 159111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 159211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 159311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 159432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_save_finfo(ctx); 1595f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_hash_init(ctx, CONFDIR "/bpf_pinning"); 1596f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann 159732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 159832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_elf: 159932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 160032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_fd: 160132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 160232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 160332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 1604d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann 160532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_count(struct bpf_elf_ctx *ctx) 160632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 160732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, count = 0; 160811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 160932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 161032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[i]) 161132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 161232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann count++; 161332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 1614473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 161532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return count; 161632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 16176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 161832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_maps_teardown(struct bpf_elf_ctx *ctx) 161932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 162032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i; 162132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 162232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 162332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_fds[i]) 162432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->map_fds[i]); 1625473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 162632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 162732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 162832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) 162932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 163032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (failure) 163132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 1632473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1633f6793eec4600a9f9428026ed75c50a44eeb3c83fDaniel Borkmann bpf_hash_destroy(ctx); 163432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann free(ctx->sec_done); 163532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 163632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 163732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 16386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 163932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic struct bpf_elf_ctx __ctx; 16406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 164132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *pathname, enum bpf_prog_type type, 164232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *section, bool verbose) 164332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 164432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 164532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd = 0, ret; 16466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 164732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_elf_ctx_init(ctx, pathname, type, verbose); 164832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 164932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot initialize ELF context!\n"); 165032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 165132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 16526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 165332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_ancillary(ctx); 165432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 165532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching ELF ancillary data!\n"); 165632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 165732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 165832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 165932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, section); 166032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) { 166132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching program/map!\n"); 166232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fd; 166332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 166432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 166532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 166632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_prog_arrays(ctx); 166732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 166832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error filling program arrays!\n"); 166911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannout: 167032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_elf_ctx_destroy(ctx, ret < 0); 167132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 167232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd) 167332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 167432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 167532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 167632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 167732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 16786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 167911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 16806256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int 16814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len, 16824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann const struct bpf_map_data *aux, unsigned int entries) 16836256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 16846256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_set_msg msg; 16856256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int *cmsg_buf, min_fd; 16866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann char *amsg_buf; 16876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int i; 16886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 16896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&msg, 0, sizeof(msg)); 16906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 16916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann msg.aux.uds_ver = BPF_SCM_AUX_VER; 16924bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann msg.aux.num_ent = entries; 16936256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 16946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name)); 16956256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st)); 16966256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 16976256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, addr, addr_len); 16986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 16996256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17004bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < entries; i += min_fd) { 17016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int ret; 17026256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17034bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i); 17046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 17056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17066256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd); 17076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd); 17086256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17096256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = sendmsg(fd, &msg.hdr, 0); 17106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret <= 0) 17116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret ? : -1; 17126256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 17136256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return 0; 171511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 171611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 17174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic int 17184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_recv(int fd, int *fds, struct bpf_map_aux *aux, 17194bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 17204bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 17214bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct bpf_map_set_msg msg; 17224bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int *cmsg_buf, min_fd; 17234bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann char *amsg_buf, *mmsg_buf; 17244bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int needed = 1; 17254bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int i; 17264bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17274bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, NULL, 0); 17284bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 17294bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann mmsg_buf = (char *)&msg.aux; 17304bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17314bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < min(entries, needed); i += min_fd) { 17324bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct cmsghdr *cmsg; 17334bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int ret; 17344bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17354bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(entries, entries - i); 17364bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 17374bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17384bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = recvmsg(fd, &msg.hdr, 0); 17394bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret <= 0) 17404bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret ? : -1; 17414bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17424bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg = CMSG_FIRSTHDR(&msg.hdr); 17434bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) 17444bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 17454bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.hdr.msg_flags & MSG_CTRUNC) 17464bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EIO; 17474bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.aux.uds_ver != BPF_SCM_AUX_VER) 17484bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -ENOSYS; 17494bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17504bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd); 17514bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (min_fd > entries || min_fd <= 0) 17524bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 17534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17544bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd); 17554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd); 17564bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent)); 17574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann needed = aux->num_ent; 17594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 17604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17614bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return 0; 17624bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 17634bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 17644bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_send_map_fds(const char *path, const char *obj) 17656256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 176632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 17676256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct sockaddr_un addr; 17686256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_data bpf_aux; 17696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int fd, ret; 17706256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17716256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 17726256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (fd < 0) { 17736256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 17746256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strerror(errno)); 17756256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 17766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 17776256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&addr, 0, sizeof(addr)); 17796256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann addr.sun_family = AF_UNIX; 17806256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 17816256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17826256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); 17836256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) { 17846256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot connect to %s: %s\n", 17856256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 17866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 17876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 17886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&bpf_aux, 0, sizeof(bpf_aux)); 17906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 179132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.fds = ctx->map_fds; 179232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.ent = ctx->maps; 179332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.st = &ctx->stat; 17946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_aux.obj = obj; 17956256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 17964bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux, 179732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_count(ctx)); 17986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) 17994bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot send fds to %s: %s\n", 18004bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann path, strerror(errno)); 18014bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 180232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 18034bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann close(fd); 18044bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret; 18054bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 18064bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18074bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, 18084bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 18094bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 18104bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct sockaddr_un addr; 18114bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int fd, ret; 18124bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18134bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 18144bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (fd < 0) { 18154bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 18164bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 18174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 18184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 18194bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18204bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memset(&addr, 0, sizeof(addr)); 18214bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann addr.sun_family = AF_UNIX; 18224bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 18234bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18244bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 18254bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) { 18264bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot bind to socket: %s\n", 18274bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 18284bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 18294bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 18304bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 18314bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_recv(fd, fds, aux, entries); 18324bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) 18334bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot recv fds from %s: %s\n", 18346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 18356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 18364bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unlink(addr.sun_path); 18376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann close(fd); 18386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret; 18396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 184011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif /* HAVE_ELF */ 1841