Merge branch 'regmap-4.20' into regmap-next
[linux-2.6-block.git] / tools / lib / bpf / bpf.c
CommitLineData
6061a3d6
EL
1// SPDX-License-Identifier: LGPL-2.1
2
e3ed2fef
WN
3/*
4 * common eBPF ELF operations.
5 *
6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
8 * Copyright (C) 2015 Huawei Inc.
203d1cac
WN
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation;
13 * version 2.1 of the License (not later!)
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this program; if not, see <http://www.gnu.org/licenses>
e3ed2fef
WN
22 */
23
24#include <stdlib.h>
25#include <memory.h>
26#include <unistd.h>
27#include <asm/unistd.h>
28#include <linux/bpf.h>
29#include "bpf.h"
949abbe8
EL
30#include "libbpf.h"
31#include "nlattr.h"
32#include <linux/rtnetlink.h>
33#include <linux/if_link.h>
34#include <sys/socket.h>
35#include <errno.h>
e3ed2fef 36
bbf48c18
EL
37#ifndef SOL_NETLINK
38#define SOL_NETLINK 270
39#endif
40
e3ed2fef 41/*
03671057 42 * When building perf, unistd.h is overridden. __NR_bpf is
8f9e05fb 43 * required to be defined explicitly.
e3ed2fef
WN
44 */
45#ifndef __NR_bpf
46# if defined(__i386__)
47# define __NR_bpf 357
48# elif defined(__x86_64__)
49# define __NR_bpf 321
50# elif defined(__aarch64__)
51# define __NR_bpf 280
b0c47807
DM
52# elif defined(__sparc__)
53# define __NR_bpf 349
bad1926d
DB
54# elif defined(__s390__)
55# define __NR_bpf 351
e3ed2fef
WN
56# else
57# error __NR_bpf not defined. libbpf does not support your arch.
58# endif
59#endif
60
949abbe8 61#ifndef min
88cda1c9 62#define min(x, y) ((x) < (y) ? (x) : (y))
949abbe8 63#endif
88cda1c9 64
cdc6a4ba 65static inline __u64 ptr_to_u64(const void *ptr)
7bf98369
WN
66{
67 return (__u64) (unsigned long) ptr;
68}
69
cdc6a4ba
MS
70static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
71 unsigned int size)
e3ed2fef
WN
72{
73 return syscall(__NR_bpf, cmd, attr, size);
74}
75
8a138aed 76int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
e3ed2fef 77{
8a138aed 78 __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
e3ed2fef
WN
79 union bpf_attr attr;
80
81 memset(&attr, '\0', sizeof(attr));
82
8a138aed
MKL
83 attr.map_type = create_attr->map_type;
84 attr.key_size = create_attr->key_size;
85 attr.value_size = create_attr->value_size;
86 attr.max_entries = create_attr->max_entries;
87 attr.map_flags = create_attr->map_flags;
88 memcpy(attr.map_name, create_attr->name,
89 min(name_len, BPF_OBJ_NAME_LEN - 1));
90 attr.numa_node = create_attr->numa_node;
91 attr.btf_fd = create_attr->btf_fd;
61746dbe
MKL
92 attr.btf_key_type_id = create_attr->btf_key_type_id;
93 attr.btf_value_type_id = create_attr->btf_value_type_id;
f0307a7e 94 attr.map_ifindex = create_attr->map_ifindex;
91134d84 95 attr.inner_map_fd = create_attr->inner_map_fd;
8a138aed
MKL
96
97 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
98}
88cda1c9 99
8a138aed
MKL
100int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
101 int key_size, int value_size, int max_entries,
102 __u32 map_flags, int node)
103{
104 struct bpf_create_map_attr map_attr = {};
105
106 map_attr.name = name;
107 map_attr.map_type = map_type;
108 map_attr.map_flags = map_flags;
109 map_attr.key_size = key_size;
110 map_attr.value_size = value_size;
111 map_attr.max_entries = max_entries;
ad17d0e6 112 if (node >= 0) {
8a138aed
MKL
113 map_attr.numa_node = node;
114 map_attr.map_flags |= BPF_F_NUMA_NODE;
ad17d0e6 115 }
e3ed2fef 116
8a138aed 117 return bpf_create_map_xattr(&map_attr);
e3ed2fef 118}
7bf98369 119
ad17d0e6
MKL
120int bpf_create_map(enum bpf_map_type map_type, int key_size,
121 int value_size, int max_entries, __u32 map_flags)
122{
8a138aed
MKL
123 struct bpf_create_map_attr map_attr = {};
124
125 map_attr.map_type = map_type;
126 map_attr.map_flags = map_flags;
127 map_attr.key_size = key_size;
128 map_attr.value_size = value_size;
129 map_attr.max_entries = max_entries;
130
131 return bpf_create_map_xattr(&map_attr);
ad17d0e6
MKL
132}
133
88cda1c9
MKL
134int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
135 int key_size, int value_size, int max_entries,
136 __u32 map_flags)
137{
8a138aed
MKL
138 struct bpf_create_map_attr map_attr = {};
139
140 map_attr.name = name;
141 map_attr.map_type = map_type;
142 map_attr.map_flags = map_flags;
143 map_attr.key_size = key_size;
144 map_attr.value_size = value_size;
145 map_attr.max_entries = max_entries;
146
147 return bpf_create_map_xattr(&map_attr);
88cda1c9
MKL
148}
149
150int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
151 int key_size, int inner_map_fd, int max_entries,
ad17d0e6 152 __u32 map_flags, int node)
fb30d4b7 153{
88cda1c9 154 __u32 name_len = name ? strlen(name) : 0;
fb30d4b7
MKL
155 union bpf_attr attr;
156
157 memset(&attr, '\0', sizeof(attr));
158
159 attr.map_type = map_type;
160 attr.key_size = key_size;
161 attr.value_size = 4;
162 attr.inner_map_fd = inner_map_fd;
163 attr.max_entries = max_entries;
164 attr.map_flags = map_flags;
88cda1c9
MKL
165 memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
166
ad17d0e6
MKL
167 if (node >= 0) {
168 attr.map_flags |= BPF_F_NUMA_NODE;
169 attr.numa_node = node;
170 }
fb30d4b7
MKL
171
172 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
173}
174
88cda1c9
MKL
175int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
176 int key_size, int inner_map_fd, int max_entries,
177 __u32 map_flags)
ad17d0e6 178{
88cda1c9
MKL
179 return bpf_create_map_in_map_node(map_type, name, key_size,
180 inner_map_fd, max_entries, map_flags,
181 -1);
ad17d0e6
MKL
182}
183
d7be143b
AI
184int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
185 char *log_buf, size_t log_buf_sz)
7bf98369 186{
7bf98369 187 union bpf_attr attr;
d7be143b
AI
188 __u32 name_len;
189 int fd;
190
191 if (!load_attr)
192 return -EINVAL;
193
194 name_len = load_attr->name ? strlen(load_attr->name) : 0;
7bf98369
WN
195
196 bzero(&attr, sizeof(attr));
d7be143b
AI
197 attr.prog_type = load_attr->prog_type;
198 attr.expected_attach_type = load_attr->expected_attach_type;
199 attr.insn_cnt = (__u32)load_attr->insns_cnt;
200 attr.insns = ptr_to_u64(load_attr->insns);
201 attr.license = ptr_to_u64(load_attr->license);
7bf98369
WN
202 attr.log_buf = ptr_to_u64(NULL);
203 attr.log_size = 0;
204 attr.log_level = 0;
d7be143b 205 attr.kern_version = load_attr->kern_version;
f0307a7e 206 attr.prog_ifindex = load_attr->prog_ifindex;
d7be143b
AI
207 memcpy(attr.prog_name, load_attr->name,
208 min(name_len, BPF_OBJ_NAME_LEN - 1));
7bf98369
WN
209
210 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
211 if (fd >= 0 || !log_buf || !log_buf_sz)
212 return fd;
213
214 /* Try again with log */
215 attr.log_buf = ptr_to_u64(log_buf);
216 attr.log_size = log_buf_sz;
217 attr.log_level = 1;
218 log_buf[0] = 0;
219 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
220}
43798bf3 221
88cda1c9
MKL
222int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
223 size_t insns_cnt, const char *license,
224 __u32 kern_version, char *log_buf,
225 size_t log_buf_sz)
226{
d7be143b
AI
227 struct bpf_load_program_attr load_attr;
228
229 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
230 load_attr.prog_type = type;
231 load_attr.expected_attach_type = 0;
232 load_attr.name = NULL;
233 load_attr.insns = insns;
234 load_attr.insns_cnt = insns_cnt;
235 load_attr.license = license;
236 load_attr.kern_version = kern_version;
237
238 return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
88cda1c9
MKL
239}
240
91045f5e
DM
241int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
242 size_t insns_cnt, int strict_alignment,
243 const char *license, __u32 kern_version,
d6554904 244 char *log_buf, size_t log_buf_sz, int log_level)
91045f5e
DM
245{
246 union bpf_attr attr;
247
248 bzero(&attr, sizeof(attr));
249 attr.prog_type = type;
250 attr.insn_cnt = (__u32)insns_cnt;
251 attr.insns = ptr_to_u64(insns);
252 attr.license = ptr_to_u64(license);
253 attr.log_buf = ptr_to_u64(log_buf);
254 attr.log_size = log_buf_sz;
d6554904 255 attr.log_level = log_level;
91045f5e
DM
256 log_buf[0] = 0;
257 attr.kern_version = kern_version;
258 attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
259
260 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
261}
262
10ecc728 263int bpf_map_update_elem(int fd, const void *key, const void *value,
83d994d0 264 __u64 flags)
43798bf3
HK
265{
266 union bpf_attr attr;
267
268 bzero(&attr, sizeof(attr));
269 attr.map_fd = fd;
270 attr.key = ptr_to_u64(key);
271 attr.value = ptr_to_u64(value);
272 attr.flags = flags;
273
274 return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
275}
9742da01 276
e5ff7c40 277int bpf_map_lookup_elem(int fd, const void *key, void *value)
9742da01
WN
278{
279 union bpf_attr attr;
280
281 bzero(&attr, sizeof(attr));
282 attr.map_fd = fd;
283 attr.key = ptr_to_u64(key);
284 attr.value = ptr_to_u64(value);
285
286 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
287}
288
e58383b8 289int bpf_map_delete_elem(int fd, const void *key)
9742da01
WN
290{
291 union bpf_attr attr;
292
293 bzero(&attr, sizeof(attr));
294 attr.map_fd = fd;
295 attr.key = ptr_to_u64(key);
296
297 return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
298}
299
5f155c25 300int bpf_map_get_next_key(int fd, const void *key, void *next_key)
9742da01
WN
301{
302 union bpf_attr attr;
303
304 bzero(&attr, sizeof(attr));
305 attr.map_fd = fd;
306 attr.key = ptr_to_u64(key);
307 attr.next_key = ptr_to_u64(next_key);
308
309 return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
310}
311
312int bpf_obj_pin(int fd, const char *pathname)
313{
314 union bpf_attr attr;
315
316 bzero(&attr, sizeof(attr));
317 attr.pathname = ptr_to_u64((void *)pathname);
318 attr.bpf_fd = fd;
319
320 return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
321}
322
323int bpf_obj_get(const char *pathname)
324{
325 union bpf_attr attr;
326
327 bzero(&attr, sizeof(attr));
328 attr.pathname = ptr_to_u64((void *)pathname);
329
330 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
331}
5dc880de 332
464bc0fd
JF
333int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
334 unsigned int flags)
5dc880de
JS
335{
336 union bpf_attr attr;
337
338 bzero(&attr, sizeof(attr));
339 attr.target_fd = target_fd;
464bc0fd 340 attr.attach_bpf_fd = prog_fd;
5dc880de 341 attr.attach_type = type;
7f677633 342 attr.attach_flags = flags;
5dc880de
JS
343
344 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
345}
346
347int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
348{
349 union bpf_attr attr;
350
351 bzero(&attr, sizeof(attr));
352 attr.target_fd = target_fd;
353 attr.attach_type = type;
354
355 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
356}
30848873 357
244d20ef
AS
358int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
359{
360 union bpf_attr attr;
361
362 bzero(&attr, sizeof(attr));
363 attr.target_fd = target_fd;
364 attr.attach_bpf_fd = prog_fd;
365 attr.attach_type = type;
366
367 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
368}
369
5d0cbf9b
AS
370int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
371 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
372{
373 union bpf_attr attr;
374 int ret;
375
376 bzero(&attr, sizeof(attr));
377 attr.query.target_fd = target_fd;
378 attr.query.attach_type = type;
379 attr.query.query_flags = query_flags;
380 attr.query.prog_cnt = *prog_cnt;
381 attr.query.prog_ids = ptr_to_u64(prog_ids);
382
383 ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
384 if (attach_flags)
385 *attach_flags = attr.query.attach_flags;
386 *prog_cnt = attr.query.prog_cnt;
387 return ret;
388}
389
30848873
AS
390int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
391 void *data_out, __u32 *size_out, __u32 *retval,
392 __u32 *duration)
393{
394 union bpf_attr attr;
395 int ret;
396
397 bzero(&attr, sizeof(attr));
398 attr.test.prog_fd = prog_fd;
399 attr.test.data_in = ptr_to_u64(data);
400 attr.test.data_out = ptr_to_u64(data_out);
401 attr.test.data_size_in = size;
402 attr.test.repeat = repeat;
403
404 ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
405 if (size_out)
406 *size_out = attr.test.data_size_out;
407 if (retval)
408 *retval = attr.test.retval;
409 if (duration)
410 *duration = attr.test.duration;
411 return ret;
412}
95b9afd3
MKL
413
414int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
415{
416 union bpf_attr attr;
417 int err;
418
419 bzero(&attr, sizeof(attr));
420 attr.start_id = start_id;
421
422 err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr));
423 if (!err)
424 *next_id = attr.next_id;
425
426 return err;
427}
428
429int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
430{
431 union bpf_attr attr;
432 int err;
433
434 bzero(&attr, sizeof(attr));
435 attr.start_id = start_id;
436
437 err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr));
438 if (!err)
439 *next_id = attr.next_id;
440
441 return err;
442}
443
444int bpf_prog_get_fd_by_id(__u32 id)
445{
446 union bpf_attr attr;
447
448 bzero(&attr, sizeof(attr));
449 attr.prog_id = id;
450
451 return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
452}
453
454int bpf_map_get_fd_by_id(__u32 id)
455{
456 union bpf_attr attr;
457
458 bzero(&attr, sizeof(attr));
459 attr.map_id = id;
460
461 return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
462}
463
cd8b8928
MKL
464int bpf_btf_get_fd_by_id(__u32 id)
465{
466 union bpf_attr attr;
467
468 bzero(&attr, sizeof(attr));
469 attr.btf_id = id;
470
471 return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
472}
473
95b9afd3
MKL
474int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
475{
476 union bpf_attr attr;
477 int err;
478
479 bzero(&attr, sizeof(attr));
95b9afd3
MKL
480 attr.info.bpf_fd = prog_fd;
481 attr.info.info_len = *info_len;
482 attr.info.info = ptr_to_u64(info);
483
484 err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
485 if (!err)
486 *info_len = attr.info.info_len;
487
488 return err;
489}
949abbe8 490
a0fe3e57
AS
491int bpf_raw_tracepoint_open(const char *name, int prog_fd)
492{
493 union bpf_attr attr;
494
495 bzero(&attr, sizeof(attr));
496 attr.raw_tracepoint.name = ptr_to_u64(name);
497 attr.raw_tracepoint.prog_fd = prog_fd;
498
499 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
500}
501
949abbe8
EL
502int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
503{
504 struct sockaddr_nl sa;
505 int sock, seq = 0, len, ret = -1;
506 char buf[4096];
507 struct nlattr *nla, *nla_xdp;
508 struct {
509 struct nlmsghdr nh;
510 struct ifinfomsg ifinfo;
511 char attrbuf[64];
512 } req;
513 struct nlmsghdr *nh;
514 struct nlmsgerr *err;
515 socklen_t addrlen;
bbf48c18 516 int one = 1;
949abbe8
EL
517
518 memset(&sa, 0, sizeof(sa));
519 sa.nl_family = AF_NETLINK;
520
521 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
522 if (sock < 0) {
523 return -errno;
524 }
525
bbf48c18
EL
526 if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
527 &one, sizeof(one)) < 0) {
528 fprintf(stderr, "Netlink error reporting not supported\n");
529 }
530
949abbe8
EL
531 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
532 ret = -errno;
533 goto cleanup;
534 }
535
536 addrlen = sizeof(sa);
537 if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
538 ret = -errno;
539 goto cleanup;
540 }
541
542 if (addrlen != sizeof(sa)) {
543 ret = -LIBBPF_ERRNO__INTERNAL;
544 goto cleanup;
545 }
546
547 memset(&req, 0, sizeof(req));
548 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
549 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
550 req.nh.nlmsg_type = RTM_SETLINK;
551 req.nh.nlmsg_pid = 0;
552 req.nh.nlmsg_seq = ++seq;
553 req.ifinfo.ifi_family = AF_UNSPEC;
554 req.ifinfo.ifi_index = ifindex;
555
556 /* started nested attribute for XDP */
557 nla = (struct nlattr *)(((char *)&req)
558 + NLMSG_ALIGN(req.nh.nlmsg_len));
559 nla->nla_type = NLA_F_NESTED | IFLA_XDP;
560 nla->nla_len = NLA_HDRLEN;
561
562 /* add XDP fd */
563 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
564 nla_xdp->nla_type = IFLA_XDP_FD;
565 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
566 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
567 nla->nla_len += nla_xdp->nla_len;
568
569 /* if user passed in any flags, add those too */
570 if (flags) {
571 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
572 nla_xdp->nla_type = IFLA_XDP_FLAGS;
573 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
574 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
575 nla->nla_len += nla_xdp->nla_len;
576 }
577
578 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
579
580 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
581 ret = -errno;
582 goto cleanup;
583 }
584
585 len = recv(sock, buf, sizeof(buf), 0);
586 if (len < 0) {
587 ret = -errno;
588 goto cleanup;
589 }
590
591 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
592 nh = NLMSG_NEXT(nh, len)) {
593 if (nh->nlmsg_pid != sa.nl_pid) {
594 ret = -LIBBPF_ERRNO__WRNGPID;
595 goto cleanup;
596 }
597 if (nh->nlmsg_seq != seq) {
598 ret = -LIBBPF_ERRNO__INVSEQ;
599 goto cleanup;
600 }
601 switch (nh->nlmsg_type) {
602 case NLMSG_ERROR:
603 err = (struct nlmsgerr *)NLMSG_DATA(nh);
604 if (!err->error)
605 continue;
606 ret = err->error;
bbf48c18 607 nla_dump_errormsg(nh);
949abbe8
EL
608 goto cleanup;
609 case NLMSG_DONE:
610 break;
611 default:
612 break;
613 }
614 }
615
616 ret = 0;
617
618cleanup:
619 close(sock);
620 return ret;
621}
8a138aed
MKL
622
623int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
624 bool do_log)
625{
626 union bpf_attr attr = {};
627 int fd;
628
629 attr.btf = ptr_to_u64(btf);
630 attr.btf_size = btf_size;
631
632retry:
633 if (do_log && log_buf && log_buf_size) {
634 attr.btf_log_level = 1;
635 attr.btf_log_size = log_buf_size;
636 attr.btf_log_buf = ptr_to_u64(log_buf);
637 }
638
639 fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr));
640 if (fd == -1 && !do_log && log_buf && log_buf_size) {
641 do_log = true;
642 goto retry;
643 }
644
645 return fd;
646}
30687ad9
YS
647
648int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
649 __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
650 __u64 *probe_addr)
651{
652 union bpf_attr attr = {};
653 int err;
654
655 attr.task_fd_query.pid = pid;
656 attr.task_fd_query.fd = fd;
657 attr.task_fd_query.flags = flags;
658 attr.task_fd_query.buf = ptr_to_u64(buf);
659 attr.task_fd_query.buf_len = *buf_len;
660
661 err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
662 *buf_len = attr.task_fd_query.buf_len;
663 *prog_id = attr.task_fd_query.prog_id;
664 *fd_type = attr.task_fd_query.fd_type;
665 *probe_offset = attr.task_fd_query.probe_offset;
666 *probe_addr = attr.task_fd_query.probe_addr;
667
668 return err;
669}