libbpf_probes.c (11995B)
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2/* Copyright (c) 2019 Netronome Systems, Inc. */ 3 4#include <errno.h> 5#include <fcntl.h> 6#include <string.h> 7#include <stdlib.h> 8#include <unistd.h> 9#include <net/if.h> 10#include <sys/utsname.h> 11 12#include <linux/btf.h> 13#include <linux/filter.h> 14#include <linux/kernel.h> 15 16#include "bpf.h" 17#include "libbpf.h" 18#include "libbpf_internal.h" 19 20static bool grep(const char *buffer, const char *pattern) 21{ 22 return !!strstr(buffer, pattern); 23} 24 25static int get_vendor_id(int ifindex) 26{ 27 char ifname[IF_NAMESIZE], path[64], buf[8]; 28 ssize_t len; 29 int fd; 30 31 if (!if_indextoname(ifindex, ifname)) 32 return -1; 33 34 snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname); 35 36 fd = open(path, O_RDONLY | O_CLOEXEC); 37 if (fd < 0) 38 return -1; 39 40 len = read(fd, buf, sizeof(buf)); 41 close(fd); 42 if (len < 0) 43 return -1; 44 if (len >= (ssize_t)sizeof(buf)) 45 return -1; 46 buf[len] = '\0'; 47 48 return strtol(buf, NULL, 0); 49} 50 51static int probe_prog_load(enum bpf_prog_type prog_type, 52 const struct bpf_insn *insns, size_t insns_cnt, 53 char *log_buf, size_t log_buf_sz, 54 __u32 ifindex) 55{ 56 LIBBPF_OPTS(bpf_prog_load_opts, opts, 57 .log_buf = log_buf, 58 .log_size = log_buf_sz, 59 .log_level = log_buf ? 1 : 0, 60 .prog_ifindex = ifindex, 61 ); 62 int fd, err, exp_err = 0; 63 const char *exp_msg = NULL; 64 char buf[4096]; 65 66 switch (prog_type) { 67 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: 68 opts.expected_attach_type = BPF_CGROUP_INET4_CONNECT; 69 break; 70 case BPF_PROG_TYPE_CGROUP_SOCKOPT: 71 opts.expected_attach_type = BPF_CGROUP_GETSOCKOPT; 72 break; 73 case BPF_PROG_TYPE_SK_LOOKUP: 74 opts.expected_attach_type = BPF_SK_LOOKUP; 75 break; 76 case BPF_PROG_TYPE_KPROBE: 77 opts.kern_version = get_kernel_version(); 78 break; 79 case BPF_PROG_TYPE_LIRC_MODE2: 80 opts.expected_attach_type = BPF_LIRC_MODE2; 81 break; 82 case BPF_PROG_TYPE_TRACING: 83 case BPF_PROG_TYPE_LSM: 84 opts.log_buf = buf; 85 opts.log_size = sizeof(buf); 86 opts.log_level = 1; 87 if (prog_type == BPF_PROG_TYPE_TRACING) 88 opts.expected_attach_type = BPF_TRACE_FENTRY; 89 else 90 opts.expected_attach_type = BPF_MODIFY_RETURN; 91 opts.attach_btf_id = 1; 92 93 exp_err = -EINVAL; 94 exp_msg = "attach_btf_id 1 is not a function"; 95 break; 96 case BPF_PROG_TYPE_EXT: 97 opts.log_buf = buf; 98 opts.log_size = sizeof(buf); 99 opts.log_level = 1; 100 opts.attach_btf_id = 1; 101 102 exp_err = -EINVAL; 103 exp_msg = "Cannot replace kernel functions"; 104 break; 105 case BPF_PROG_TYPE_SYSCALL: 106 opts.prog_flags = BPF_F_SLEEPABLE; 107 break; 108 case BPF_PROG_TYPE_STRUCT_OPS: 109 exp_err = -524; /* -ENOTSUPP */ 110 break; 111 case BPF_PROG_TYPE_UNSPEC: 112 case BPF_PROG_TYPE_SOCKET_FILTER: 113 case BPF_PROG_TYPE_SCHED_CLS: 114 case BPF_PROG_TYPE_SCHED_ACT: 115 case BPF_PROG_TYPE_TRACEPOINT: 116 case BPF_PROG_TYPE_XDP: 117 case BPF_PROG_TYPE_PERF_EVENT: 118 case BPF_PROG_TYPE_CGROUP_SKB: 119 case BPF_PROG_TYPE_CGROUP_SOCK: 120 case BPF_PROG_TYPE_LWT_IN: 121 case BPF_PROG_TYPE_LWT_OUT: 122 case BPF_PROG_TYPE_LWT_XMIT: 123 case BPF_PROG_TYPE_SOCK_OPS: 124 case BPF_PROG_TYPE_SK_SKB: 125 case BPF_PROG_TYPE_CGROUP_DEVICE: 126 case BPF_PROG_TYPE_SK_MSG: 127 case BPF_PROG_TYPE_RAW_TRACEPOINT: 128 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE: 129 case BPF_PROG_TYPE_LWT_SEG6LOCAL: 130 case BPF_PROG_TYPE_SK_REUSEPORT: 131 case BPF_PROG_TYPE_FLOW_DISSECTOR: 132 case BPF_PROG_TYPE_CGROUP_SYSCTL: 133 break; 134 default: 135 return -EOPNOTSUPP; 136 } 137 138 fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts); 139 err = -errno; 140 if (fd >= 0) 141 close(fd); 142 if (exp_err) { 143 if (fd >= 0 || err != exp_err) 144 return 0; 145 if (exp_msg && !strstr(buf, exp_msg)) 146 return 0; 147 return 1; 148 } 149 return fd >= 0 ? 1 : 0; 150} 151 152int libbpf_probe_bpf_prog_type(enum bpf_prog_type prog_type, const void *opts) 153{ 154 struct bpf_insn insns[] = { 155 BPF_MOV64_IMM(BPF_REG_0, 0), 156 BPF_EXIT_INSN() 157 }; 158 const size_t insn_cnt = ARRAY_SIZE(insns); 159 int ret; 160 161 if (opts) 162 return libbpf_err(-EINVAL); 163 164 ret = probe_prog_load(prog_type, insns, insn_cnt, NULL, 0, 0); 165 return libbpf_err(ret); 166} 167 168bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex) 169{ 170 struct bpf_insn insns[2] = { 171 BPF_MOV64_IMM(BPF_REG_0, 0), 172 BPF_EXIT_INSN() 173 }; 174 175 /* prefer libbpf_probe_bpf_prog_type() unless offload is requested */ 176 if (ifindex == 0) 177 return libbpf_probe_bpf_prog_type(prog_type, NULL) == 1; 178 179 if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS) 180 /* nfp returns -EINVAL on exit(0) with TC offload */ 181 insns[0].imm = 2; 182 183 errno = 0; 184 probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex); 185 186 return errno != EINVAL && errno != EOPNOTSUPP; 187} 188 189int libbpf__load_raw_btf(const char *raw_types, size_t types_len, 190 const char *str_sec, size_t str_len) 191{ 192 struct btf_header hdr = { 193 .magic = BTF_MAGIC, 194 .version = BTF_VERSION, 195 .hdr_len = sizeof(struct btf_header), 196 .type_len = types_len, 197 .str_off = types_len, 198 .str_len = str_len, 199 }; 200 int btf_fd, btf_len; 201 __u8 *raw_btf; 202 203 btf_len = hdr.hdr_len + hdr.type_len + hdr.str_len; 204 raw_btf = malloc(btf_len); 205 if (!raw_btf) 206 return -ENOMEM; 207 208 memcpy(raw_btf, &hdr, sizeof(hdr)); 209 memcpy(raw_btf + hdr.hdr_len, raw_types, hdr.type_len); 210 memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len); 211 212 btf_fd = bpf_btf_load(raw_btf, btf_len, NULL); 213 214 free(raw_btf); 215 return btf_fd; 216} 217 218static int load_local_storage_btf(void) 219{ 220 const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l"; 221 /* struct bpf_spin_lock { 222 * int val; 223 * }; 224 * struct val { 225 * int cnt; 226 * struct bpf_spin_lock l; 227 * }; 228 */ 229 __u32 types[] = { 230 /* int */ 231 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 232 /* struct bpf_spin_lock */ /* [2] */ 233 BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4), 234 BTF_MEMBER_ENC(15, 1, 0), /* int val; */ 235 /* struct val */ /* [3] */ 236 BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 237 BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */ 238 BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */ 239 }; 240 241 return libbpf__load_raw_btf((char *)types, sizeof(types), 242 strs, sizeof(strs)); 243} 244 245static int probe_map_create(enum bpf_map_type map_type, __u32 ifindex) 246{ 247 LIBBPF_OPTS(bpf_map_create_opts, opts); 248 int key_size, value_size, max_entries; 249 __u32 btf_key_type_id = 0, btf_value_type_id = 0; 250 int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err; 251 252 opts.map_ifindex = ifindex; 253 254 key_size = sizeof(__u32); 255 value_size = sizeof(__u32); 256 max_entries = 1; 257 258 switch (map_type) { 259 case BPF_MAP_TYPE_STACK_TRACE: 260 value_size = sizeof(__u64); 261 break; 262 case BPF_MAP_TYPE_LPM_TRIE: 263 key_size = sizeof(__u64); 264 value_size = sizeof(__u64); 265 opts.map_flags = BPF_F_NO_PREALLOC; 266 break; 267 case BPF_MAP_TYPE_CGROUP_STORAGE: 268 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: 269 key_size = sizeof(struct bpf_cgroup_storage_key); 270 value_size = sizeof(__u64); 271 max_entries = 0; 272 break; 273 case BPF_MAP_TYPE_QUEUE: 274 case BPF_MAP_TYPE_STACK: 275 key_size = 0; 276 break; 277 case BPF_MAP_TYPE_SK_STORAGE: 278 case BPF_MAP_TYPE_INODE_STORAGE: 279 case BPF_MAP_TYPE_TASK_STORAGE: 280 btf_key_type_id = 1; 281 btf_value_type_id = 3; 282 value_size = 8; 283 max_entries = 0; 284 opts.map_flags = BPF_F_NO_PREALLOC; 285 btf_fd = load_local_storage_btf(); 286 if (btf_fd < 0) 287 return btf_fd; 288 break; 289 case BPF_MAP_TYPE_RINGBUF: 290 key_size = 0; 291 value_size = 0; 292 max_entries = 4096; 293 break; 294 case BPF_MAP_TYPE_STRUCT_OPS: 295 /* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */ 296 opts.btf_vmlinux_value_type_id = 1; 297 exp_err = -524; /* -ENOTSUPP */ 298 break; 299 case BPF_MAP_TYPE_BLOOM_FILTER: 300 key_size = 0; 301 max_entries = 1; 302 break; 303 case BPF_MAP_TYPE_HASH: 304 case BPF_MAP_TYPE_ARRAY: 305 case BPF_MAP_TYPE_PROG_ARRAY: 306 case BPF_MAP_TYPE_PERF_EVENT_ARRAY: 307 case BPF_MAP_TYPE_PERCPU_HASH: 308 case BPF_MAP_TYPE_PERCPU_ARRAY: 309 case BPF_MAP_TYPE_CGROUP_ARRAY: 310 case BPF_MAP_TYPE_LRU_HASH: 311 case BPF_MAP_TYPE_LRU_PERCPU_HASH: 312 case BPF_MAP_TYPE_ARRAY_OF_MAPS: 313 case BPF_MAP_TYPE_HASH_OF_MAPS: 314 case BPF_MAP_TYPE_DEVMAP: 315 case BPF_MAP_TYPE_DEVMAP_HASH: 316 case BPF_MAP_TYPE_SOCKMAP: 317 case BPF_MAP_TYPE_CPUMAP: 318 case BPF_MAP_TYPE_XSKMAP: 319 case BPF_MAP_TYPE_SOCKHASH: 320 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: 321 break; 322 case BPF_MAP_TYPE_UNSPEC: 323 default: 324 return -EOPNOTSUPP; 325 } 326 327 if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS || 328 map_type == BPF_MAP_TYPE_HASH_OF_MAPS) { 329 /* TODO: probe for device, once libbpf has a function to create 330 * map-in-map for offload 331 */ 332 if (ifindex) 333 goto cleanup; 334 335 fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, 336 sizeof(__u32), sizeof(__u32), 1, NULL); 337 if (fd_inner < 0) 338 goto cleanup; 339 340 opts.inner_map_fd = fd_inner; 341 } 342 343 if (btf_fd >= 0) { 344 opts.btf_fd = btf_fd; 345 opts.btf_key_type_id = btf_key_type_id; 346 opts.btf_value_type_id = btf_value_type_id; 347 } 348 349 fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts); 350 err = -errno; 351 352cleanup: 353 if (fd >= 0) 354 close(fd); 355 if (fd_inner >= 0) 356 close(fd_inner); 357 if (btf_fd >= 0) 358 close(btf_fd); 359 360 if (exp_err) 361 return fd < 0 && err == exp_err ? 1 : 0; 362 else 363 return fd >= 0 ? 1 : 0; 364} 365 366int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts) 367{ 368 int ret; 369 370 if (opts) 371 return libbpf_err(-EINVAL); 372 373 ret = probe_map_create(map_type, 0); 374 return libbpf_err(ret); 375} 376 377bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) 378{ 379 return probe_map_create(map_type, ifindex) == 1; 380} 381 382int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id, 383 const void *opts) 384{ 385 struct bpf_insn insns[] = { 386 BPF_EMIT_CALL((__u32)helper_id), 387 BPF_EXIT_INSN(), 388 }; 389 const size_t insn_cnt = ARRAY_SIZE(insns); 390 char buf[4096]; 391 int ret; 392 393 if (opts) 394 return libbpf_err(-EINVAL); 395 396 /* we can't successfully load all prog types to check for BPF helper 397 * support, so bail out with -EOPNOTSUPP error 398 */ 399 switch (prog_type) { 400 case BPF_PROG_TYPE_TRACING: 401 case BPF_PROG_TYPE_EXT: 402 case BPF_PROG_TYPE_LSM: 403 case BPF_PROG_TYPE_STRUCT_OPS: 404 return -EOPNOTSUPP; 405 default: 406 break; 407 } 408 409 buf[0] = '\0'; 410 ret = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf), 0); 411 if (ret < 0) 412 return libbpf_err(ret); 413 414 /* If BPF verifier doesn't recognize BPF helper ID (enum bpf_func_id) 415 * at all, it will emit something like "invalid func unknown#181". 416 * If BPF verifier recognizes BPF helper but it's not supported for 417 * given BPF program type, it will emit "unknown func bpf_sys_bpf#166". 418 * In both cases, provided combination of BPF program type and BPF 419 * helper is not supported by the kernel. 420 * In all other cases, probe_prog_load() above will either succeed (e.g., 421 * because BPF helper happens to accept no input arguments or it 422 * accepts one input argument and initial PTR_TO_CTX is fine for 423 * that), or we'll get some more specific BPF verifier error about 424 * some unsatisfied conditions. 425 */ 426 if (ret == 0 && (strstr(buf, "invalid func ") || strstr(buf, "unknown func "))) 427 return 0; 428 return 1; /* assume supported */ 429} 430 431bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, 432 __u32 ifindex) 433{ 434 struct bpf_insn insns[2] = { 435 BPF_EMIT_CALL(id), 436 BPF_EXIT_INSN() 437 }; 438 char buf[4096] = {}; 439 bool res; 440 441 probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf), ifindex); 442 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func "); 443 444 if (ifindex) { 445 switch (get_vendor_id(ifindex)) { 446 case 0x19ee: /* Netronome specific */ 447 res = res && !grep(buf, "not supported by FW") && 448 !grep(buf, "unsupported function id"); 449 break; 450 default: 451 break; 452 } 453 } 454 455 return res; 456} 457 458/* 459 * Probe for availability of kernel commit (5.3): 460 * 461 * c04c0d2b968a ("bpf: increase complexity limit and maximum program size") 462 */ 463bool bpf_probe_large_insn_limit(__u32 ifindex) 464{ 465 struct bpf_insn insns[BPF_MAXINSNS + 1]; 466 int i; 467 468 for (i = 0; i < BPF_MAXINSNS; i++) 469 insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1); 470 insns[BPF_MAXINSNS] = BPF_EXIT_INSN(); 471 472 errno = 0; 473 probe_prog_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0, 474 ifindex); 475 476 return errno != E2BIG && errno != EINVAL; 477}