tc_bpf.c revision 32e93fb7f66d55d597b52ec3b10fd44a47784114
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 7932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_get(const char *pathname) 8032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 8132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 8232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .pathname = bpf_ptr_to_u64(pathname), 8332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 8432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 8532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 8632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 8732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 8832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, 8932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char **bpf_string, bool *need_release, 9032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char separator) 911d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 921d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char sp; 931d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 941d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (from_file) { 951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); 961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *tmp_string; 971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko FILE *fp; 981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; 1001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko tmp_string = malloc(tmp_len); 1011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (tmp_string == NULL) 1021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOMEM; 1031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1041d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko memset(tmp_string, 0, tmp_len); 1051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fp = fopen(arg, "r"); 1071d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (fp == NULL) { 1081d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko perror("Cannot fopen"); 1091d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1101d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -ENOENT; 1111d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1121d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1131d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (!fgets(tmp_string, tmp_len, fp)) { 1141d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(tmp_string); 1151d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1161d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EIO; 1171d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1181d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1191d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fclose(fp); 1201d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1211d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = true; 1221d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = tmp_string; 1231d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } else { 1241d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *need_release = false; 1251d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko *bpf_string = arg; 1261d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1271d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1281d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || 1291d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko sp != separator) { 1301d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (*need_release) 1311d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(*bpf_string); 1321d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1331d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1341d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1351d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return 0; 1361d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1371d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 13832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops, 13932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool from_file) 1401d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1411d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko char *bpf_string, *token, separator = ','; 1421d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int ret = 0, i = 0; 1431d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko bool need_release; 1441d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko __u16 bpf_len = 0; 1451d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1461d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (argc < 1) 1471d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1481d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, 1491d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &need_release, separator)) 1501d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return -EINVAL; 1511d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { 1521d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1531d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1541d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1551d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1561d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko token = bpf_string; 1571d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko while ((token = strchr(token, separator)) && (++token)[0]) { 1581d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i >= bpf_len) { 1591d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Real program length exceeds encoded " 1601d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1611d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1621d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1631d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1641d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1651d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (sscanf(token, "%hu %hhu %hhu %u,", 1661d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].code, &bpf_ops[i].jt, 1671d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { 1681d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Error at instruction %d!\n", i); 1691d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1701d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1711d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1721d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1731d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko i++; 1741d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1751d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1761d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (i != bpf_len) { 1771d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(stderr, "Parsed program length is less than encoded" 1781d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko "length parameter!\n"); 1791d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = -EINVAL; 1801d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko goto out; 1811d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko } 1821d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ret = bpf_len; 1831d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkoout: 1841d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (need_release) 1851d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko free(bpf_string); 1861d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1871d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return ret; 1881d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 1891d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1901d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirkovoid bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) 1911d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko{ 1921d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); 1931d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko int i; 1941d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1951d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko if (len == 0) 1961d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko return; 1971d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 1981d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "bytecode \'%u,", len); 1991d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2001d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko for (i = 0; i < len - 1; i++) 2011d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, 2021d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2031d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko 2046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt, 2051d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko ops[i].jf, ops[i].k); 2061d129d191a3a632e05cf440c15aaffe23e0fa798Jiri Pirko} 20711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 20832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_valid_mntpt(const char *mnt, unsigned long magic) 20932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 21032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct statfs st_fs; 21132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 21232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (statfs(mnt, &st_fs) < 0) 21332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 21432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if ((unsigned long)st_fs.f_type != magic) 21532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOENT; 21632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 21732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 21832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 21932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 22032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_find_mntpt(const char *fstype, unsigned long magic, 22132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char *mnt, int len, 22232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *known_mnts) 22332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 22432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char * const *ptr; 22532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char type[100]; 22632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann FILE *fp; 22732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 22832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (known_mnts) { 22932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr = known_mnts; 23032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (*ptr) { 23132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_valid_mntpt(*ptr, magic) == 0) { 23232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strncpy(mnt, *ptr, len - 1); 23332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt[len - 1] = 0; 23432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 23532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 23632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ptr++; 23732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 23832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 23932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 24032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fp = fopen("/proc/mounts", "r"); 24132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fp == NULL || len != PATH_MAX) 24232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 24332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 24432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (fscanf(fp, "%*s %" textify(PATH_MAX) "s %99s %*s %*d %*d\n", 24532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt, type) == 2) { 24632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) == 0) 24732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 24832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 24932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 25032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fclose(fp); 25132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (strcmp(type, fstype) != 0) 25232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 25332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 25432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 25532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 25632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 25732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannint bpf_trace_pipe(void) 25832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 25932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tracefs_mnt[PATH_MAX] = TRACE_DIR_MNT; 26032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static const char * const tracefs_known_mnts[] = { 26132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann TRACE_DIR_MNT, 26232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/sys/kernel/debug/tracing", 26332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/tracing", 26432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "/trace", 26532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 0, 26632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 26732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char tpipe[PATH_MAX]; 26832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *mnt; 26932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 27032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 27132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt, 27232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(tracefs_mnt), tracefs_known_mnts); 27332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!mnt) { 27432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "tracefs not mounted?\n"); 27532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 27632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 27732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 27832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt); 27932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 28032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = open(tpipe, O_RDONLY); 28132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 28232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 28332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 28432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Running! Hang up with ^C!\n\n"); 28532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (1) { 28632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char buff[4096]; 28732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t ret; 28832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 28932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = read(fd, buff, sizeof(buff) - 1); 29032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret > 0) { 29132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann write(2, buff, ret); 29232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fflush(stderr); 29332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 29432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 29532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 29632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 29732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 29832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 2996256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannconst char *bpf_default_section(const enum bpf_prog_type type) 30011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 30111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann switch (type) { 30211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann case BPF_PROG_TYPE_SCHED_CLS: 30311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ELF_SECTION_CLASSIFIER; 3046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann case BPF_PROG_TYPE_SCHED_ACT: 3056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ELF_SECTION_ACTION; 30611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann default: 30711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return NULL; 30811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 30911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 31011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 31132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannint bpf_parse_common(int *ptr_argc, char ***ptr_argv, const int *nla_tbl, 31232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type, const char **ptr_object, 31332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char **ptr_uds_name, struct nlmsghdr *n) 31432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 31532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct sock_filter opcodes[BPF_MAXINSNS]; 31632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *file, *section, *uds_name; 31732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char **argv = *ptr_argv; 31832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int argc = *ptr_argc; 31932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char annotation[256]; 32032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose = false; 32132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 32232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_mode { 32332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann CBPF_BYTECODE, 32432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann CBPF_FILE, 32532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann EBPF_OBJECT, 32632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann EBPF_PINNED, 32732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } mode; 32832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 32932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (matches(*argv, "bytecode") == 0 || 33032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strcmp(*argv, "bc") == 0) { 33132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mode = CBPF_BYTECODE; 33232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else if (matches(*argv, "bytecode-file") == 0 || 33332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strcmp(*argv, "bcf") == 0) { 33432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mode = CBPF_FILE; 33532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else if (matches(*argv, "object-file") == 0 || 33632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strcmp(*argv, "obj") == 0) { 33732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mode = EBPF_OBJECT; 33832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else if (matches(*argv, "object-pinned") == 0 || 33932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann matches(*argv, "pinned") == 0 || 34032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann matches(*argv, "fd") == 0) { 34132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mode = EBPF_PINNED; 34232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 34332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "What mode is \"%s\"?\n", *argv); 34432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 34532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 34632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 34732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 34832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = section = uds_name = NULL; 34932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mode == EBPF_OBJECT || mode == EBPF_PINNED) { 35032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann file = *argv; 35132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 35232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 35332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section = bpf_default_section(type); 35432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "section") == 0) { 35532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 35632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section = *argv; 35732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 35832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 35932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = getenv(BPF_ENV_UDS); 36132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && !uds_name && 36232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann matches(*argv, "export") == 0) { 36332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG(); 36432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uds_name = *argv; 36532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 36632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 36732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 36832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (argc > 0 && matches(*argv, "verbose") == 0) { 36932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann verbose = true; 37032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann NEXT_ARG_FWD(); 37132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann PREV_ARG(); 37432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 37532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 37632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mode == CBPF_BYTECODE || mode == CBPF_FILE) 37732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_ops_parse(argc, argv, opcodes, mode == CBPF_FILE); 37832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (mode == EBPF_OBJECT) 37932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_open(file, type, section, verbose); 38032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (mode == EBPF_PINNED) 38132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_get(file); 38232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 38332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 38432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 38532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mode == CBPF_BYTECODE || mode == CBPF_FILE) { 38632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr16(n, MAX_MSG, nla_tbl[BPF_NLA_OPS_LEN], ret); 38732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr_l(n, MAX_MSG, nla_tbl[BPF_NLA_OPS], opcodes, 38832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret * sizeof(struct sock_filter)); 38932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else if (mode == EBPF_OBJECT || mode == EBPF_PINNED) { 39032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(annotation, sizeof(annotation), "%s:[%s]", 39132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann basename(file), mode == EBPF_PINNED ? "*fsobj" : 39232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section); 39332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 39432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattr32(n, MAX_MSG, nla_tbl[BPF_NLA_FD], ret); 39532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann addattrstrz(n, MAX_MSG, nla_tbl[BPF_NLA_NAME], annotation); 39632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 39732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 39832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann *ptr_object = file; 39932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann *ptr_uds_name = uds_name; 40032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 40132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann *ptr_argc = argc; 40232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann *ptr_argv = argv; 40332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 40432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 40532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 40632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 4076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#ifdef HAVE_ELF 40832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_prog { 40932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 41032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_insn *insns; 41132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size; 41232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *license; 41332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 41432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 41532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstruct bpf_elf_ctx { 41632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf *elf_fd; 41732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Ehdr elf_hdr; 41832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sym_tab; 41932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *str_tab; 42032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int obj_fd; 42132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_fds[ELF_MAX_MAPS]; 42232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map maps[ELF_MAX_MAPS]; 42332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sym_num; 42432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int map_num; 42532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool *sec_done; 42632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int sec_maps; 42732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char license[ELF_MAX_LICENSE_LEN]; 42832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type; 42932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose; 43032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st stat; 43132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann}; 43232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 4336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_elf_sec_data { 43432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr sec_hdr; 43532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_data; 43632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *sec_name; 4376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 4386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 4396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstruct bpf_map_data { 44032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int *fds; 44132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *obj; 44232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_st *st; 44332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_map *ent; 4446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}; 4456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 4466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* If we provide a small buffer with log level enabled, the kernel 4476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * could fail program load as no buffer space is available for the 4486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * log and thus verifier fails. In case something doesn't pass the 4496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * verifier we still want to hand something descriptive to the user. 4506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann */ 4516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic char bpf_log_buf[65536]; 4526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 45332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic __check_format_string(1, 2) void bpf_dump_error(const char *format, ...) 45411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 45511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_list vl; 45611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 45711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_start(vl, format); 45811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann vfprintf(stderr, format, vl); 45911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann va_end(vl); 46011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 461d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann if (bpf_log_buf[0]) { 462d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann fprintf(stderr, "%s\n", bpf_log_buf); 463d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann memset(bpf_log_buf, 0, sizeof(bpf_log_buf)); 464d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 46511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 46611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 46732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_create(enum bpf_map_type type, unsigned int size_key, 46811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann unsigned int size_value, unsigned int max_elem) 46911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 47011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 47111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .map_type = type, 47211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .key_size = size_key, 47311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .value_size = size_value, 47411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .max_entries = max_elem, 47511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 47611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 47711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 47811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 47911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 48032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_update(int fd, const void *key, const void *value, 481473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann uint64_t flags) 482473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 483473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann union bpf_attr attr = { 484473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann .map_fd = fd, 485473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann .key = bpf_ptr_to_u64(key), 486473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann .value = bpf_ptr_to_u64(value), 487473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann .flags = flags, 488473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann }; 489473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 490473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 491473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 492473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 49311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannstatic int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, 49432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size_t size, const char *license) 49511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 49611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann union bpf_attr attr = { 49711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .prog_type = type, 49811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .insns = bpf_ptr_to_u64(insns), 49932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .insn_cnt = size / sizeof(struct bpf_insn), 50011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .license = bpf_ptr_to_u64(license), 50111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_buf = bpf_ptr_to_u64(bpf_log_buf), 50211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_size = sizeof(bpf_log_buf), 50311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann .log_level = 1, 50411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann }; 50511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 50632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (getenv(BPF_ENV_NOLOG)) { 50732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_buf = 0; 50832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_size = 0; 50932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann attr.log_level = 0; 51032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 51132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 51211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 51311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 51411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 51532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_pin(int fd, const char *pathname) 51611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 51732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann union bpf_attr attr = { 51832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .pathname = bpf_ptr_to_u64(pathname), 51932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .bpf_fd = fd, 52032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 52132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 52232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); 52332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 52411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 52532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_hash(const char *object, uint8_t *out, size_t len) 52632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 52732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct sockaddr_alg alg = { 52832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_family = AF_ALG, 52932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_type = "hash", 53032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .salg_name = "sha1", 53132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 53232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, cfd, ofd, ffd; 53332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat stbuff; 53432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ssize_t size; 53532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 53632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!object || len != 20) 53732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 53832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 53932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann cfd = socket(AF_ALG, SOCK_SEQPACKET, 0); 54032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (cfd < 0) { 54132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot get AF_ALG socket: %s\n", 54232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 54332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return cfd; 54432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 54532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 54632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg)); 54732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 54832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error binding socket: %s\n", strerror(errno)); 54932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 55032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 55232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ofd = accept(cfd, NULL, 0); 55332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ofd < 0) { 55432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error accepting socket: %s\n", 55532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 55632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ofd; 55732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_cfd; 55832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 55932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 56032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ffd = open(object, O_RDONLY); 56132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ffd < 0) { 56232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error opening object %s: %s\n", 56332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann object, strerror(errno)); 56432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = ffd; 56532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ofd; 56632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 56732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 56832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ffd, &stbuff); 56932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 57032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error doing fstat: %s\n", 57132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 57232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 573d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann } 57411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 57532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = sendfile(ofd, ffd, NULL, stbuff.st_size); 57632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != stbuff.st_size) { 57732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n", 57832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, stbuff.st_size, strerror(errno)); 57932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 58032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_ffd; 58132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 58232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 58332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size = read(ofd, out, len); 58432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (size != len) { 58532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n", 58632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann size, len, strerror(errno)); 58732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = -1; 58832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } else { 58932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = 0; 59032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 59132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ffd: 59232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ffd); 59332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_ofd: 59432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ofd); 59532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_cfd: 59632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(cfd); 59732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 59811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 59911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 60032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_get_obj_uid(const char *pathname) 60111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 60232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static bool bpf_uid_cached = false; 60332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char bpf_uid[64]; 60432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint8_t tmp[20]; 60532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 60611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 60732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_uid_cached) 60832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto done; 60911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 61032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); 61132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret) { 61232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Object hashing failed!\n"); 61332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 61432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 61532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 61632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid)); 61732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_uid_cached = true; 61832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmanndone: 61932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_uid; 62011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 62111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 62232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_mnt_fs(const char *target) 62311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 62432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool bind_done = false; 62532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 62632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) { 62732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (errno != EINVAL || bind_done) { 62832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mount --make-private %s failed: %s\n", 62932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann target, strerror(errno)); 63032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 63132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 63211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 63332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mount(target, target, "none", MS_BIND, NULL)) { 63432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mount --bind %s %s failed: %s\n", 63532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann target, target, strerror(errno)); 63632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 63732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 63832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 63932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bind_done = true; 64032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 64132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 64232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (mount("bpf", target, "bpf", 0, NULL)) { 64332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mount -t bpf bpf %s failed: %s\n", 64432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann target, strerror(errno)); 64532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 64632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 64732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 64832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 64911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 65011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 65132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_get_tc_dir(void) 6526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 65332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static bool bpf_mnt_cached = false; 65432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static char bpf_tc_dir[PATH_MAX]; 65532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static const char *mnt; 65632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann static const char * const bpf_known_mnts[] = { 65732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann BPF_DIR_MNT, 65832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 0, 65932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 66032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char bpf_mnt[PATH_MAX] = BPF_DIR_MNT; 66132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char bpf_glo_dir[PATH_MAX]; 66232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 6636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 66432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_mnt_cached) 66532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto done; 66632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 66732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_mnt, sizeof(bpf_mnt), 66832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_known_mnts); 66932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!mnt) { 67032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = getenv(BPF_ENV_MNT); 67132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!mnt) 67232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = BPF_DIR_MNT; 67332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_mnt_fs(mnt); 67432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret) { 67532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = NULL; 67632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 67732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 6786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 6796256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 68032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(bpf_tc_dir, sizeof(bpf_tc_dir), "%s/%s", mnt, BPF_DIR_TC); 68132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = mkdir(bpf_tc_dir, S_IRWXU); 68232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret && errno != EEXIST) { 68332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_tc_dir, 68432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 68532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = NULL; 68632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 68732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 68832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 68932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s", 69032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_tc_dir, BPF_DIR_GLOBALS); 69132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = mkdir(bpf_glo_dir, S_IRWXU); 69232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret && errno != EEXIST) { 69332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir, 69432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 69532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = NULL; 69632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 69732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 69832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 69932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann mnt = bpf_tc_dir; 70032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout: 70132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_mnt_cached = true; 70232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmanndone: 70332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return mnt; 70432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 70532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 70632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_init_env(const char *pathname) 70732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 70832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct rlimit limit = { 70932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_cur = RLIM_INFINITY, 71032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann .rlim_max = RLIM_INFINITY, 71132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann }; 71232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 71332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* Don't bother in case we fail! */ 71432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann setrlimit(RLIMIT_MEMLOCK, &limit); 71532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 71632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_tc_dir()) { 71732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Continuing without mounted eBPF fs. " 71832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "Too old kernel?\n"); 71932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 72032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 72132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 72232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!bpf_get_obj_uid(pathname)) 72332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -1; 72432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 72532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 7266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 7276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 72832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic bool bpf_no_pinning(int pinning) 72911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 73032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 73132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 73232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 73332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return false; 73432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_NONE: 73532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann default: 73632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return true; 73732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 73832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 73932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 74032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_make_pathname(char *pathname, size_t len, const char *name, 74132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int pinning) 74232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 74332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann switch (pinning) { 74432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_OBJECT_NS: 74532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 74632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_get_obj_uid(NULL), name); 74732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 74832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann case PIN_GLOBAL_NS: 74932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, len, "%s/%s/%s", bpf_get_tc_dir(), 75032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann BPF_DIR_GLOBALS, name); 75132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 75232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 75332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 75432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 75532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_probe_pinned(const char *name, int pinning) 75632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 75732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char pathname[PATH_MAX]; 75832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 75932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_no_pinning(pinning) || !bpf_get_tc_dir()) 76032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 76132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 76232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, pinning); 76332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_get(pathname); 76432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 76532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 76632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_place_pinned(int fd, const char *name, int pinning) 76732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 76832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann char pathname[PATH_MAX]; 76932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 77032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 77132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (bpf_no_pinning(pinning) || !bpf_get_tc_dir()) 77232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 77332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 77432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (pinning == PIN_OBJECT_NS) { 77532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann snprintf(pathname, sizeof(pathname), "%s/%s", 77632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_get_tc_dir(), bpf_get_obj_uid(NULL)); 77732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 77832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = mkdir(pathname, S_IRWXU); 77932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret && errno != EEXIST) { 78032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "mkdir %s failed: %s\n", pathname, 78132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 78232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 78332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 78432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 78532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 78632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_make_pathname(pathname, sizeof(pathname), name, pinning); 78732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_obj_pin(fd, pathname); 78832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 78932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 79032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_prog_attach(const char *section, 79132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const struct bpf_elf_prog *prog, bool verbose) 79232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 79332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd; 79432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 79532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann /* We can add pinning here later as well, same as bpf_map_attach(). */ 79632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 79732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_load(prog->type, prog->insns, prog->size, 79832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->license); 79932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 80032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Prog section \'%s\' (type:%u insns:%zu " 80132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "license:\'%s\') %s%s (%d)!\n\n", 80232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann section, prog->type, 80332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->size / sizeof(struct bpf_insn), 80432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog->license, fd < 0 ? "rejected :" : 80532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "loaded", fd < 0 ? strerror(errno) : "", 80632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? errno : fd); 80732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 80832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 80932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 81032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 81132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 81232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_map_attach(const char *name, const struct bpf_elf_map *map, 81332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bool verbose) 81432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 81532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd, ret; 81632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 81732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_probe_pinned(name, map->pinning); 81832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd > 0) { 81932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (verbose) 82032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' loaded as pinned!\n", 82132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name); 82232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 82332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 82432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 82532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann errno = 0; 82632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_map_create(map->type, map->size_key, map->size_value, 82732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->max_elem); 82832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0 || verbose) { 82932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_dump_error("Map \'%s\' (type:%u id:%u pinning:%u " 83032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "ksize:%u vsize:%u max-elems:%u) %s%s (%d)!\n", 83132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann name, map->type, map->id, map->pinning, 83232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map->size_key, map->size_value, map->max_elem, 83332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd < 0 ? "rejected: " : "loaded", fd < 0 ? 83432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno) : "", fd < 0 ? errno : fd); 83532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 83632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 83732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 83832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 83932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_place_pinned(fd, name, map->pinning); 84032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 && errno != EEXIST) { 84132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Could not pin %s map: %s\n", name, 84232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 84332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 84432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 84532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 84632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 84732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 84832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 84932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 85032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_BIND(x) ((x) >> 4) 85132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann#define __ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) 85232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 85332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx, 85432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const GElf_Sym *sym) 85532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 85632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->str_tab->d_buf + sym->st_name; 85732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 85832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 85932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) 86032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 86132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 86211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann int i; 86311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 86432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->sym_num; i++) { 86532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) 86632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 86732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 86832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (__ELF_ST_BIND(sym.st_info) != STB_GLOBAL || 86932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann __ELF_ST_TYPE(sym.st_info) != STT_NOTYPE || 87032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_shndx != ctx->sec_maps || 87132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sym.st_value / sizeof(struct bpf_elf_map) != which) 87232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 87332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 87432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return bpf_str_tab_name(ctx, &sym); 87511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 87632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 87732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return NULL; 87811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 87911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 88032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_attach_all(struct bpf_elf_ctx *ctx) 88111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 88232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *map_name; 88332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, fd; 88411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 88532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ctx->map_num; i++) { 88632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann map_name = bpf_map_fetch_name(ctx, i); 88732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!map_name) 88832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 88911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 89032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_map_attach(map_name, &ctx->maps[i], ctx->verbose); 89132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 89232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 89311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 89432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_fds[i] = fd; 89511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 89611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 89711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 89811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 89911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 90032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_section_data(struct bpf_elf_ctx *ctx, int section, 90132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 90211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 90332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *sec_edata; 90411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann GElf_Shdr sec_hdr; 90511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann Elf_Scn *sec_fd; 90611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann char *sec_name; 90711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 90832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(data, 0, sizeof(*data)); 90911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 91032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_fd = elf_getscn(ctx->elf_fd, section); 91111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_fd) 91211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EINVAL; 91311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (gelf_getshdr(sec_fd, &sec_hdr) != &sec_hdr) 91411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 91511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 91632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sec_name = elf_strptr(ctx->elf_fd, ctx->elf_hdr.e_shstrndx, 91711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_hdr.sh_name); 91811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_name || !sec_hdr.sh_size) 91911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -ENOENT; 92011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 92111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann sec_edata = elf_getdata(sec_fd, NULL); 92211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (!sec_edata || elf_getdata(sec_fd, sec_edata)) 92311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return -EIO; 92411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 92532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(&data->sec_hdr, &sec_hdr, sizeof(sec_hdr)); 92611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 92732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_name = sec_name; 92832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data->sec_data = sec_edata; 92911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 93011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 93111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 93232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_maps(struct bpf_elf_ctx *ctx, int section, 93332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 93411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 93532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size % sizeof(struct bpf_elf_map) != 0) 93632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 93711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 93832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->map_num = data->sec_data->d_size / sizeof(struct bpf_elf_map); 93932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_maps = section; 94032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 94111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 94232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_num > ARRAY_SIZE(ctx->map_fds)) { 94332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Too many BPF maps in ELF section!\n"); 94432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 94532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 94611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 94732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->maps, data->sec_data->d_buf, data->sec_data->d_size); 94832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 94932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 95011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 95132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_license(struct bpf_elf_ctx *ctx, int section, 95232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 95332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 95432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (data->sec_data->d_size > sizeof(ctx->license)) 95532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -ENOMEM; 95611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 95732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memcpy(ctx->license, data->sec_data->d_buf, data->sec_data->d_size); 95832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 95932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 96032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 96111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 96232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_symtab(struct bpf_elf_ctx *ctx, int section, 96332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 96432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 96532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_tab = data->sec_data; 96632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sym_num = data->sec_hdr.sh_size / data->sec_hdr.sh_entsize; 96732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 96811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return 0; 96911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 97011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 97132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section, 97232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data) 97311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 97432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->str_tab = data->sec_data; 97532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[section] = true; 97632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 97732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 97811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 97932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx) 98032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 98132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 98232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, ret = -1; 98311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 98432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 98532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 98611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann if (ret < 0) 98711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 98811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 98932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!strcmp(data.sec_name, ELF_SECTION_MAPS)) 99032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_maps(ctx, i, &data); 99132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (!strcmp(data.sec_name, ELF_SECTION_LICENSE)) 99232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_license(ctx, i, &data); 99332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_SYMTAB) 99432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_symtab(ctx, i, &data); 99532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann else if (data.sec_hdr.sh_type == SHT_STRTAB && 99632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann i != ctx->elf_hdr.e_shstrndx) 99732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_strtab(ctx, i, &data); 99832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 99932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error parsing section %d! Perhaps" 100032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "check with readelf -a?\n", i); 100132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 100211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 100332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 100432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 100532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) { 100632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_maps_attach_all(ctx); 100732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 100832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error loading maps into kernel!\n"); 100932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 101011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 101111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 101211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 101311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann return ret; 101411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 101511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 101632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section) 101711c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 101832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 101932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 102032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, i, fd = -1; 102111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 102232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 102332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 102411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 102511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 102632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 102732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || strcmp(data.sec_name, section)) 102811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 102911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 103032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 103132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 103232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data.sec_data->d_buf; 103332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data.sec_data->d_size; 103432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 103511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 103632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 103732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 103811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 103911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 104032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 104111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 104211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 104311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 104432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 104511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 104611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 104732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_apply_relo_data(struct bpf_elf_ctx *ctx, 104832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_relo, 104932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data *data_insn) 105011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 105132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann Elf_Data *idata = data_insn->sec_data; 105232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Shdr *rhdr = &data_relo->sec_hdr; 105332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize; 105432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_insn *insns = idata->d_buf; 105532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int num_insns = idata->d_size / sizeof(*insns); 105611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 105732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (relo_ent = 0; relo_ent < relo_num; relo_ent++) { 105832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann unsigned int ioff, rmap; 105932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Rel relo; 106032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann GElf_Sym sym; 106132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 106232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo) 106332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 106432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 106532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ioff = relo.r_offset / sizeof(struct bpf_insn); 106632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ioff >= num_insns || 106732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) 106832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 106932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 107032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym) 107132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EIO; 107232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 107332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann rmap = sym.st_value / sizeof(struct bpf_elf_map); 107432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (rmap >= ARRAY_SIZE(ctx->map_fds)) 107532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 107632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[rmap]) 107732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return -EINVAL; 107832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 107932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->verbose) 108032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Map \'%s\' (%d) injected into prog " 108132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann "section \'%s\' at offset %u!\n", 108232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap], 108332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann data_insn->sec_name, ioff); 108411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 108532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].src_reg = BPF_PSEUDO_MAP_FD; 108632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann insns[ioff].imm = ctx->map_fds[rmap]; 108732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 108832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 108932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 109032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 109132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 109232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section) 109332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 109432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data_relo, data_insn; 109532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_prog prog; 109632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret, idx, i, fd = -1; 109732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 109832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 109932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data_relo); 110032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL) 110111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 110211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 110332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann idx = data_relo.sec_hdr.sh_info; 110432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, idx, &data_insn); 110532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0 || strcmp(data_insn.sec_name, section)) 110611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 110732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 110832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn); 110932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 111011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 111111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 111232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&prog, 0, sizeof(prog)); 111332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.type = ctx->type; 111432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.insns = data_insn.sec_data->d_buf; 111532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.size = data_insn.sec_data->d_size; 111632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann prog.license = ctx->license; 111732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 111832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_prog_attach(section, &prog, ctx->verbose); 111932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 112011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann continue; 112111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 112232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 112332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[idx] = true; 112411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann break; 112511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 112611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 112732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 112811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 112911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 113032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section) 1131473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 1132473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann int ret = -1; 1133473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 113432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sym_tab) 113532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog_relo(ctx, section); 1136473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 113732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_prog(ctx, section); 113832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 1139473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return ret; 1140473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1141473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 114232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx) 1143473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann{ 114432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_sec_data data; 114532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann uint32_t map_id, key_id; 114632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd, i, ret; 1147473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 114832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { 114932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->sec_done[i]) 1150473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1151473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 115232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_section_data(ctx, i, &data); 1153473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1154473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1155473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 115632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = sscanf(data.sec_name, "%u/%u", &map_id, &key_id); 115732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret != 2 || map_id >= ARRAY_SIZE(ctx->map_fds) || 115832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann !ctx->map_fds[map_id]) 115932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann continue; 116032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->maps[map_id].type != BPF_MAP_TYPE_PROG_ARRAY || 116132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->maps[map_id].max_elem <= key_id) 1162473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann continue; 1163473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 116432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, data.sec_name); 116532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) 1166473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -EIO; 1167473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 116832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_map_update(ctx->map_fds[map_id], &key_id, 116932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann &fd, BPF_NOEXIST); 1170473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann if (ret < 0) 1171473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return -ENOENT; 1172473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 117332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done[i] = true; 1174473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 1175473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 1176473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann return 0; 1177473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann} 1178473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 117932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_save_finfo(struct bpf_elf_ctx *ctx) 118011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann{ 118132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct stat st; 118232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret; 118311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(&ctx->stat, 0, sizeof(ctx->stat)); 118511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 118632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fstat(ctx->obj_fd, &st); 118732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 118832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Stat of elf file failed: %s\n", 118932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann strerror(errno)); 119032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return; 119132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 119211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 119332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_dev = st.st_dev; 119432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->stat.st_ino = st.st_ino; 119532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 119632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 119732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, 119832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann enum bpf_prog_type type, bool verbose) 119932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 120032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int ret = -EINVAL; 120132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 120232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (elf_version(EV_CURRENT) == EV_NONE || 120332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_init_env(pathname)) 120432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 120532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 120632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann memset(ctx, 0, sizeof(*ctx)); 120732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->verbose = verbose; 120832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->type = type; 120932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 121032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->obj_fd = open(pathname, O_RDONLY); 121132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->obj_fd < 0) 121232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ctx->obj_fd; 121332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 121432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->elf_fd = elf_begin(ctx->obj_fd, ELF_C_READ, NULL); 121532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->elf_fd) { 121611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EINVAL; 121732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out_fd; 121811c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 121911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 122032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (gelf_getehdr(ctx->elf_fd, &ctx->elf_hdr) != 122132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann &ctx->elf_hdr) { 122211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -EIO; 122311c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 122411c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 122511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 122632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ctx->sec_done = calloc(ctx->elf_hdr.e_shnum, 122732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann sizeof(*(ctx->sec_done))); 122832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->sec_done) { 122911c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann ret = -ENOMEM; 123011c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann goto out_elf; 123111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann } 123211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 123332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_save_finfo(ctx); 123432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return 0; 123532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_elf: 123632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 123732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannout_fd: 123832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 123932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 124032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 1241d937a74b6d7818d67b12f2439320bfddcdd35e58Daniel Borkmann 124232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_maps_count(struct bpf_elf_ctx *ctx) 124332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 124432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i, count = 0; 124511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 124632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 124732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (!ctx->map_fds[i]) 124832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann break; 124932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann count++; 125032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 1251473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 125232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return count; 125332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 12546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 125532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_maps_teardown(struct bpf_elf_ctx *ctx) 125632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 125732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int i; 125832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 125932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann for (i = 0; i < ARRAY_SIZE(ctx->map_fds); i++) { 126032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ctx->map_fds[i]) 126132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->map_fds[i]); 1262473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann } 126332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 126432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 126532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) 126632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 126732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (failure) 126832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 1269473d7840c39addf966cf0cc699c2a2b3cbfe4647Daniel Borkmann 127032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann free(ctx->sec_done); 127132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann elf_end(ctx->elf_fd); 127232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(ctx->obj_fd); 127332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann} 12746256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 127532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic struct bpf_elf_ctx __ctx; 12766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 127732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmannstatic int bpf_obj_open(const char *pathname, enum bpf_prog_type type, 127832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann const char *section, bool verbose) 127932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann{ 128032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 128132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann int fd = 0, ret; 12826256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 128332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_elf_ctx_init(ctx, pathname, type, verbose); 128432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 128532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Cannot initialize ELF context!\n"); 128632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 128732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 12886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 128932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fetch_ancillary(ctx); 129032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 129132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching ELF ancillary data!\n"); 129232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 129332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 129432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 129532e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fd = bpf_fetch_prog_sec(ctx, section); 129632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd < 0) { 129732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error fetching program/map!\n"); 129832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = fd; 129932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann goto out; 130032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 130132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 130232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann ret = bpf_fill_prog_arrays(ctx); 130332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) 130432e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann fprintf(stderr, "Error filling program arrays!\n"); 130511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmannout: 130632e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_elf_ctx_destroy(ctx, ret < 0); 130732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (ret < 0) { 130832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann if (fd) 130932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann close(fd); 131032e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return ret; 131132e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann } 131232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann 131332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann return fd; 13146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 131511c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 13166256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int 13174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_send(int fd, struct sockaddr_un *addr, unsigned int addr_len, 13184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann const struct bpf_map_data *aux, unsigned int entries) 13196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 13206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_set_msg msg; 13216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int *cmsg_buf, min_fd; 13226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann char *amsg_buf; 13236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int i; 13246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&msg, 0, sizeof(msg)); 13266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann msg.aux.uds_ver = BPF_SCM_AUX_VER; 13284bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann msg.aux.num_ent = entries; 13296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(msg.aux.obj_name, aux->obj, sizeof(msg.aux.obj_name)); 13316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(&msg.aux.obj_st, aux->st, sizeof(msg.aux.obj_st)); 13326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, addr, addr_len); 13346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 13356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13364bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < entries; i += min_fd) { 13376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int ret; 13386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13394bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i); 13406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 13416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(cmsg_buf, &aux->fds[i], sizeof(aux->fds[0]) * min_fd); 13436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memcpy(amsg_buf, &aux->ent[i], sizeof(aux->ent[0]) * min_fd); 13446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = sendmsg(fd, &msg.hdr, 0); 13466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret <= 0) 13476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret ? : -1; 13486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 13496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 13506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return 0; 135111c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann} 135211c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann 13534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic int 13544bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannbpf_map_set_recv(int fd, int *fds, struct bpf_map_aux *aux, 13554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 13564bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 13574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct bpf_map_set_msg msg; 13584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int *cmsg_buf, min_fd; 13594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann char *amsg_buf, *mmsg_buf; 13604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int needed = 1; 13614bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int i; 13624bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13634bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg_buf = bpf_map_set_init(&msg, NULL, 0); 13644bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann amsg_buf = (char *)msg.aux.ent; 13654bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann mmsg_buf = (char *)&msg.aux; 13664bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13674bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann for (i = 0; i < min(entries, needed); i += min_fd) { 13684bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct cmsghdr *cmsg; 13694bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int ret; 13704bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13714bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = min(entries, entries - i); 13724bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann bpf_map_set_init_single(&msg, min_fd); 13734bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13744bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = recvmsg(fd, &msg.hdr, 0); 13754bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret <= 0) 13764bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret ? : -1; 13774bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13784bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann cmsg = CMSG_FIRSTHDR(&msg.hdr); 13794bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) 13804bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 13814bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.hdr.msg_flags & MSG_CTRUNC) 13824bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EIO; 13834bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (msg.aux.uds_ver != BPF_SCM_AUX_VER) 13844bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -ENOSYS; 13854bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13864bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd); 13874bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (min_fd > entries || min_fd <= 0) 13884bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -EINVAL; 13894bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13904bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd); 13914bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd); 13924bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent)); 13934bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13944bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann needed = aux->num_ent; 13954bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 13964bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 13974bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return 0; 13984bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 13994bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14004bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_send_map_fds(const char *path, const char *obj) 14016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{ 140232e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann struct bpf_elf_ctx *ctx = &__ctx; 14036256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct sockaddr_un addr; 14046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann struct bpf_map_data bpf_aux; 14056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann int fd, ret; 14066256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 14086256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (fd < 0) { 14096256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 14106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strerror(errno)); 14116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 14126256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 14136256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&addr, 0, sizeof(addr)); 14156256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann addr.sun_family = AF_UNIX; 14166256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 14176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14186256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); 14196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) { 14206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann fprintf(stderr, "Cannot connect to %s: %s\n", 14216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 14226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return -1; 14236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann } 14246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann memset(&bpf_aux, 0, sizeof(bpf_aux)); 14266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 142732e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.fds = ctx->map_fds; 142832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.ent = ctx->maps; 142932e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_aux.st = &ctx->stat; 14306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann bpf_aux.obj = obj; 14316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14324bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_send(fd, &addr, sizeof(addr), &bpf_aux, 143332e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_count(ctx)); 14346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann if (ret < 0) 14354bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot send fds to %s: %s\n", 14364bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann path, strerror(errno)); 14374bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 143832e93fb7f66d55d597b52ec3b10fd44a47784114Daniel Borkmann bpf_maps_teardown(ctx); 14394bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann close(fd); 14404bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return ret; 14414bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann} 14424bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14434bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannint bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, 14444bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unsigned int entries) 14454bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{ 14464bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann struct sockaddr_un addr; 14474bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann int fd, ret; 14484bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14494bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fd = socket(AF_UNIX, SOCK_DGRAM, 0); 14504bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (fd < 0) { 14514bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot open socket: %s\n", 14524bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 14534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 14544bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 14554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14564bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann memset(&addr, 0, sizeof(addr)); 14574bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann addr.sun_family = AF_UNIX; 14584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strncpy(addr.sun_path, path, sizeof(addr.sun_path)); 14594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 14614bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) { 14624bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot bind to socket: %s\n", 14634bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann strerror(errno)); 14644bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann return -1; 14654bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann } 14664bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann 14674bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann ret = bpf_map_set_recv(fd, fds, aux, entries); 14684bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann if (ret < 0) 14694bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann fprintf(stderr, "Cannot recv fds from %s: %s\n", 14706256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann path, strerror(errno)); 14716256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann 14724bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann unlink(addr.sun_path); 14736256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann close(fd); 14746256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann return ret; 14756256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann} 147611c39b5e98a163889fe5e1840e1b2a105bc33680Daniel Borkmann#endif /* HAVE_ELF */ 1477