bpf.c 21.9 KB
Newer Older
1
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2

3 4 5 6 7 8
/*
 * common eBPF ELF operations.
 *
 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
 * Copyright (C) 2015 Huawei Inc.
W
Wang Nan 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License (not later!)
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not,  see <http://www.gnu.org/licenses>
22 23 24
 */

#include <stdlib.h>
25
#include <string.h>
26 27 28
#include <memory.h>
#include <unistd.h>
#include <asm/unistd.h>
29
#include <errno.h>
30 31
#include <linux/bpf.h>
#include "bpf.h"
E
Eric Leblond 已提交
32
#include "libbpf.h"
33
#include "libbpf_internal.h"
34

35 36 37
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64

38
/*
39
 * When building perf, unistd.h is overridden. __NR_bpf is
40
 * required to be defined explicitly.
41 42 43 44 45 46 47 48
 */
#ifndef __NR_bpf
# if defined(__i386__)
#  define __NR_bpf 357
# elif defined(__x86_64__)
#  define __NR_bpf 321
# elif defined(__aarch64__)
#  define __NR_bpf 280
49 50
# elif defined(__sparc__)
#  define __NR_bpf 349
51 52
# elif defined(__s390__)
#  define __NR_bpf 351
53 54
# elif defined(__arc__)
#  define __NR_bpf 280
55 56 57 58 59
# else
#  error __NR_bpf not defined. libbpf does not support your arch.
# endif
#endif

M
Mickaël Salaün 已提交
60
static inline __u64 ptr_to_u64(const void *ptr)
61 62 63 64
{
	return (__u64) (unsigned long) ptr;
}

M
Mickaël Salaün 已提交
65 66
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
			  unsigned int size)
67 68 69 70
{
	return syscall(__NR_bpf, cmd, attr, size);
}

71 72 73 74 75 76 77 78 79 80 81
static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
{
	int fd;

	do {
		fd = sys_bpf(BPF_PROG_LOAD, attr, size);
	} while (fd < 0 && errno == EAGAIN);

	return fd;
}

82
int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
83 84 85 86 87
{
	union bpf_attr attr;

	memset(&attr, '\0', sizeof(attr));

88 89 90 91 92
	attr.map_type = create_attr->map_type;
	attr.key_size = create_attr->key_size;
	attr.value_size = create_attr->value_size;
	attr.max_entries = create_attr->max_entries;
	attr.map_flags = create_attr->map_flags;
93 94 95
	if (create_attr->name)
		memcpy(attr.map_name, create_attr->name,
		       min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1));
96 97
	attr.numa_node = create_attr->numa_node;
	attr.btf_fd = create_attr->btf_fd;
98 99
	attr.btf_key_type_id = create_attr->btf_key_type_id;
	attr.btf_value_type_id = create_attr->btf_value_type_id;
100
	attr.map_ifindex = create_attr->map_ifindex;
101 102 103 104 105
	if (attr.map_type == BPF_MAP_TYPE_STRUCT_OPS)
		attr.btf_vmlinux_value_type_id =
			create_attr->btf_vmlinux_value_type_id;
	else
		attr.inner_map_fd = create_attr->inner_map_fd;
106

107
	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
108
}
109

110 111 112 113 114 115 116 117 118 119 120 121
int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
			int key_size, int value_size, int max_entries,
			__u32 map_flags, int node)
{
	struct bpf_create_map_attr map_attr = {};

	map_attr.name = name;
	map_attr.map_type = map_type;
	map_attr.map_flags = map_flags;
	map_attr.key_size = key_size;
	map_attr.value_size = value_size;
	map_attr.max_entries = max_entries;
122
	if (node >= 0) {
123 124
		map_attr.numa_node = node;
		map_attr.map_flags |= BPF_F_NUMA_NODE;
125
	}
126

127
	return bpf_create_map_xattr(&map_attr);
128
}
129

130 131 132
int bpf_create_map(enum bpf_map_type map_type, int key_size,
		   int value_size, int max_entries, __u32 map_flags)
{
133 134 135 136 137 138 139 140 141
	struct bpf_create_map_attr map_attr = {};

	map_attr.map_type = map_type;
	map_attr.map_flags = map_flags;
	map_attr.key_size = key_size;
	map_attr.value_size = value_size;
	map_attr.max_entries = max_entries;

	return bpf_create_map_xattr(&map_attr);
142 143
}

144 145 146 147
int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
			int key_size, int value_size, int max_entries,
			__u32 map_flags)
{
148 149 150 151 152 153 154 155 156 157
	struct bpf_create_map_attr map_attr = {};

	map_attr.name = name;
	map_attr.map_type = map_type;
	map_attr.map_flags = map_flags;
	map_attr.key_size = key_size;
	map_attr.value_size = value_size;
	map_attr.max_entries = max_entries;

	return bpf_create_map_xattr(&map_attr);
158 159 160 161
}

int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
			       int key_size, int inner_map_fd, int max_entries,
162
			       __u32 map_flags, int node)
M
Martin KaFai Lau 已提交
163 164 165 166 167 168 169 170 171 172 173
{
	union bpf_attr attr;

	memset(&attr, '\0', sizeof(attr));

	attr.map_type = map_type;
	attr.key_size = key_size;
	attr.value_size = 4;
	attr.inner_map_fd = inner_map_fd;
	attr.max_entries = max_entries;
	attr.map_flags = map_flags;
174 175 176
	if (name)
		memcpy(attr.map_name, name,
		       min(strlen(name), BPF_OBJ_NAME_LEN - 1));
177

178 179 180 181
	if (node >= 0) {
		attr.map_flags |= BPF_F_NUMA_NODE;
		attr.numa_node = node;
	}
M
Martin KaFai Lau 已提交
182 183 184 185

	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
}

186 187 188
int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
			  int key_size, int inner_map_fd, int max_entries,
			  __u32 map_flags)
189
{
190 191 192
	return bpf_create_map_in_map_node(map_type, name, key_size,
					  inner_map_fd, max_entries, map_flags,
					  -1);
193 194
}

195 196 197 198
static void *
alloc_zero_tailing_info(const void *orecord, __u32 cnt,
			__u32 actual_rec_size, __u32 expected_rec_size)
{
199
	__u64 info_len = (__u64)actual_rec_size * cnt;
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
	void *info, *nrecord;
	int i;

	info = malloc(info_len);
	if (!info)
		return NULL;

	/* zero out bytes kernel does not understand */
	nrecord = info;
	for (i = 0; i < cnt; i++) {
		memcpy(nrecord, orecord, expected_rec_size);
		memset(nrecord + expected_rec_size, 0,
		       actual_rec_size - expected_rec_size);
		orecord += actual_rec_size;
		nrecord += actual_rec_size;
	}

	return info;
}

220 221
int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
			   char *log_buf, size_t log_buf_sz)
222
{
223
	void *finfo = NULL, *linfo = NULL;
224
	union bpf_attr attr;
225
	__u32 log_level;
226 227
	int fd;

228 229 230 231
	if (!load_attr || !log_buf != !log_buf_sz)
		return -EINVAL;

	log_level = load_attr->log_level;
232
	if (log_level > (4 | 2 | 1) || (log_level && !log_buf))
233 234
		return -EINVAL;

235
	memset(&attr, 0, sizeof(attr));
236 237
	attr.prog_type = load_attr->prog_type;
	attr.expected_attach_type = load_attr->expected_attach_type;
238 239
	if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
	    attr.prog_type == BPF_PROG_TYPE_LSM) {
240
		attr.attach_btf_id = load_attr->attach_btf_id;
241 242
	} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
		   attr.prog_type == BPF_PROG_TYPE_EXT) {
243
		attr.attach_btf_id = load_attr->attach_btf_id;
244 245
		attr.attach_prog_fd = load_attr->attach_prog_fd;
	} else {
246
		attr.prog_ifindex = load_attr->prog_ifindex;
247 248
		attr.kern_version = load_attr->kern_version;
	}
249 250 251
	attr.insn_cnt = (__u32)load_attr->insns_cnt;
	attr.insns = ptr_to_u64(load_attr->insns);
	attr.license = ptr_to_u64(load_attr->license);
252 253 254 255 256 257 258 259 260 261

	attr.log_level = log_level;
	if (log_level) {
		attr.log_buf = ptr_to_u64(log_buf);
		attr.log_size = log_buf_sz;
	} else {
		attr.log_buf = ptr_to_u64(NULL);
		attr.log_size = 0;
	}

262 263 264 265
	attr.prog_btf_fd = load_attr->prog_btf_fd;
	attr.func_info_rec_size = load_attr->func_info_rec_size;
	attr.func_info_cnt = load_attr->func_info_cnt;
	attr.func_info = ptr_to_u64(load_attr->func_info);
266 267 268
	attr.line_info_rec_size = load_attr->line_info_rec_size;
	attr.line_info_cnt = load_attr->line_info_cnt;
	attr.line_info = ptr_to_u64(load_attr->line_info);
269 270 271
	if (load_attr->name)
		memcpy(attr.prog_name, load_attr->name,
		       min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
272
	attr.prog_flags = load_attr->prog_flags;
273

274
	fd = sys_bpf_prog_load(&attr, sizeof(attr));
275
	if (fd >= 0)
276 277
		return fd;

278 279 280 281
	/* After bpf_prog_load, the kernel may modify certain attributes
	 * to give user space a hint how to deal with loading failure.
	 * Check to see whether we can make some changes and load again.
	 */
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
	while (errno == E2BIG && (!finfo || !linfo)) {
		if (!finfo && attr.func_info_cnt &&
		    attr.func_info_rec_size < load_attr->func_info_rec_size) {
			/* try with corrected func info records */
			finfo = alloc_zero_tailing_info(load_attr->func_info,
							load_attr->func_info_cnt,
							load_attr->func_info_rec_size,
							attr.func_info_rec_size);
			if (!finfo)
				goto done;

			attr.func_info = ptr_to_u64(finfo);
			attr.func_info_rec_size = load_attr->func_info_rec_size;
		} else if (!linfo && attr.line_info_cnt &&
			   attr.line_info_rec_size <
			   load_attr->line_info_rec_size) {
			linfo = alloc_zero_tailing_info(load_attr->line_info,
							load_attr->line_info_cnt,
							load_attr->line_info_rec_size,
							attr.line_info_rec_size);
			if (!linfo)
				goto done;

			attr.line_info = ptr_to_u64(linfo);
			attr.line_info_rec_size = load_attr->line_info_rec_size;
		} else {
			break;
309 310
		}

311
		fd = sys_bpf_prog_load(&attr, sizeof(attr));
312

313
		if (fd >= 0)
314 315 316
			goto done;
	}

317
	if (log_level || !log_buf)
318 319
		goto done;

320 321 322 323 324
	/* Try again with log */
	attr.log_buf = ptr_to_u64(log_buf);
	attr.log_size = log_buf_sz;
	attr.log_level = 1;
	log_buf[0] = 0;
325
	fd = sys_bpf_prog_load(&attr, sizeof(attr));
326 327
done:
	free(finfo);
328
	free(linfo);
329
	return fd;
330
}
331

332 333 334 335 336
int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
		     size_t insns_cnt, const char *license,
		     __u32 kern_version, char *log_buf,
		     size_t log_buf_sz)
{
337 338 339 340 341 342 343 344 345 346 347 348
	struct bpf_load_program_attr load_attr;

	memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
	load_attr.prog_type = type;
	load_attr.expected_attach_type = 0;
	load_attr.name = NULL;
	load_attr.insns = insns;
	load_attr.insns_cnt = insns_cnt;
	load_attr.license = license;
	load_attr.kern_version = kern_version;

	return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
349 350
}

351
int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
D
David Miller 已提交
352 353 354
		       size_t insns_cnt, __u32 prog_flags, const char *license,
		       __u32 kern_version, char *log_buf, size_t log_buf_sz,
		       int log_level)
355 356 357
{
	union bpf_attr attr;

358
	memset(&attr, 0, sizeof(attr));
359 360 361 362 363 364
	attr.prog_type = type;
	attr.insn_cnt = (__u32)insns_cnt;
	attr.insns = ptr_to_u64(insns);
	attr.license = ptr_to_u64(license);
	attr.log_buf = ptr_to_u64(log_buf);
	attr.log_size = log_buf_sz;
365
	attr.log_level = log_level;
366 367
	log_buf[0] = 0;
	attr.kern_version = kern_version;
D
David Miller 已提交
368
	attr.prog_flags = prog_flags;
369

370
	return sys_bpf_prog_load(&attr, sizeof(attr));
371 372
}

373
int bpf_map_update_elem(int fd, const void *key, const void *value,
374
			__u64 flags)
375 376 377
{
	union bpf_attr attr;

378
	memset(&attr, 0, sizeof(attr));
379 380 381 382 383 384 385
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);
	attr.value = ptr_to_u64(value);
	attr.flags = flags;

	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}
386

387
int bpf_map_lookup_elem(int fd, const void *key, void *value)
388 389 390
{
	union bpf_attr attr;

391
	memset(&attr, 0, sizeof(attr));
392 393 394 395 396 397 398
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);
	attr.value = ptr_to_u64(value);

	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}

399 400 401 402
int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
{
	union bpf_attr attr;

403
	memset(&attr, 0, sizeof(attr));
404 405 406 407 408 409 410 411
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);
	attr.value = ptr_to_u64(value);
	attr.flags = flags;

	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}

412 413 414 415
int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
{
	union bpf_attr attr;

416
	memset(&attr, 0, sizeof(attr));
417 418 419 420 421 422 423
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);
	attr.value = ptr_to_u64(value);

	return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
}

424
int bpf_map_delete_elem(int fd, const void *key)
425 426 427
{
	union bpf_attr attr;

428
	memset(&attr, 0, sizeof(attr));
429 430 431 432 433 434
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);

	return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
}

435
int bpf_map_get_next_key(int fd, const void *key, void *next_key)
436 437 438
{
	union bpf_attr attr;

439
	memset(&attr, 0, sizeof(attr));
440 441 442 443 444 445 446
	attr.map_fd = fd;
	attr.key = ptr_to_u64(key);
	attr.next_key = ptr_to_u64(next_key);

	return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
}

447 448 449 450 451 452 453 454 455 456
int bpf_map_freeze(int fd)
{
	union bpf_attr attr;

	memset(&attr, 0, sizeof(attr));
	attr.map_fd = fd;

	return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
}

457 458 459 460 461
static int bpf_map_batch_common(int cmd, int fd, void  *in_batch,
				void *out_batch, void *keys, void *values,
				__u32 *count,
				const struct bpf_map_batch_opts *opts)
{
462
	union bpf_attr attr;
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
	int ret;

	if (!OPTS_VALID(opts, bpf_map_batch_opts))
		return -EINVAL;

	memset(&attr, 0, sizeof(attr));
	attr.batch.map_fd = fd;
	attr.batch.in_batch = ptr_to_u64(in_batch);
	attr.batch.out_batch = ptr_to_u64(out_batch);
	attr.batch.keys = ptr_to_u64(keys);
	attr.batch.values = ptr_to_u64(values);
	attr.batch.count = *count;
	attr.batch.elem_flags  = OPTS_GET(opts, elem_flags, 0);
	attr.batch.flags = OPTS_GET(opts, flags, 0);

	ret = sys_bpf(cmd, &attr, sizeof(attr));
	*count = attr.batch.count;

	return ret;
}

int bpf_map_delete_batch(int fd, void *keys, __u32 *count,
			 const struct bpf_map_batch_opts *opts)
{
	return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
				    NULL, keys, NULL, count, opts);
}

int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
			 void *values, __u32 *count,
			 const struct bpf_map_batch_opts *opts)
{
	return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
				    out_batch, keys, values, count, opts);
}

int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
				    void *keys, void *values, __u32 *count,
				    const struct bpf_map_batch_opts *opts)
{
	return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
				    fd, in_batch, out_batch, keys, values,
				    count, opts);
}

int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count,
			 const struct bpf_map_batch_opts *opts)
{
	return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
				    keys, values, count, opts);
}

515 516 517 518
int bpf_obj_pin(int fd, const char *pathname)
{
	union bpf_attr attr;

519
	memset(&attr, 0, sizeof(attr));
520 521 522 523 524 525 526 527 528 529
	attr.pathname = ptr_to_u64((void *)pathname);
	attr.bpf_fd = fd;

	return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
}

int bpf_obj_get(const char *pathname)
{
	union bpf_attr attr;

530
	memset(&attr, 0, sizeof(attr));
531 532 533 534
	attr.pathname = ptr_to_u64((void *)pathname);

	return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
}
535

536 537
int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
		    unsigned int flags)
538 539 540 541 542 543 544 545 546 547 548
{
	DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
		.flags = flags,
	);

	return bpf_prog_attach_xattr(prog_fd, target_fd, type, &opts);
}

int bpf_prog_attach_xattr(int prog_fd, int target_fd,
			  enum bpf_attach_type type,
			  const struct bpf_prog_attach_opts *opts)
549 550 551
{
	union bpf_attr attr;

552 553 554
	if (!OPTS_VALID(opts, bpf_prog_attach_opts))
		return -EINVAL;

555
	memset(&attr, 0, sizeof(attr));
556
	attr.target_fd	   = target_fd;
557
	attr.attach_bpf_fd = prog_fd;
558
	attr.attach_type   = type;
559 560
	attr.attach_flags  = OPTS_GET(opts, flags, 0);
	attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
561 562 563 564 565 566 567 568

	return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
}

int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
{
	union bpf_attr attr;

569
	memset(&attr, 0, sizeof(attr));
570 571 572 573 574
	attr.target_fd	 = target_fd;
	attr.attach_type = type;

	return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
}
575

576 577 578 579
int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
{
	union bpf_attr attr;

580
	memset(&attr, 0, sizeof(attr));
581 582 583 584 585 586 587
	attr.target_fd	 = target_fd;
	attr.attach_bpf_fd = prog_fd;
	attr.attach_type = type;

	return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
}

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
int bpf_link_create(int prog_fd, int target_fd,
		    enum bpf_attach_type attach_type,
		    const struct bpf_link_create_opts *opts)
{
	union bpf_attr attr;

	if (!OPTS_VALID(opts, bpf_link_create_opts))
		return -EINVAL;

	memset(&attr, 0, sizeof(attr));
	attr.link_create.prog_fd = prog_fd;
	attr.link_create.target_fd = target_fd;
	attr.link_create.attach_type = attach_type;

	return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
}

int bpf_link_update(int link_fd, int new_prog_fd,
		    const struct bpf_link_update_opts *opts)
{
	union bpf_attr attr;

	if (!OPTS_VALID(opts, bpf_link_update_opts))
		return -EINVAL;

	memset(&attr, 0, sizeof(attr));
	attr.link_update.link_fd = link_fd;
	attr.link_update.new_prog_fd = new_prog_fd;
	attr.link_update.flags = OPTS_GET(opts, flags, 0);
	attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);

	return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
}

622 623 624 625 626 627 628 629 630 631
int bpf_iter_create(int link_fd)
{
	union bpf_attr attr;

	memset(&attr, 0, sizeof(attr));
	attr.iter_create.link_fd = link_fd;

	return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr));
}

632 633 634 635 636 637
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
		   __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
{
	union bpf_attr attr;
	int ret;

638
	memset(&attr, 0, sizeof(attr));
639 640 641 642 643 644 645 646 647 648 649 650 651
	attr.query.target_fd	= target_fd;
	attr.query.attach_type	= type;
	attr.query.query_flags	= query_flags;
	attr.query.prog_cnt	= *prog_cnt;
	attr.query.prog_ids	= ptr_to_u64(prog_ids);

	ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
	if (attach_flags)
		*attach_flags = attr.query.attach_flags;
	*prog_cnt = attr.query.prog_cnt;
	return ret;
}

652 653 654 655 656 657 658
int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
		      void *data_out, __u32 *size_out, __u32 *retval,
		      __u32 *duration)
{
	union bpf_attr attr;
	int ret;

659
	memset(&attr, 0, sizeof(attr));
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	attr.test.prog_fd = prog_fd;
	attr.test.data_in = ptr_to_u64(data);
	attr.test.data_out = ptr_to_u64(data_out);
	attr.test.data_size_in = size;
	attr.test.repeat = repeat;

	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
	if (size_out)
		*size_out = attr.test.data_size_out;
	if (retval)
		*retval = attr.test.retval;
	if (duration)
		*duration = attr.test.duration;
	return ret;
}
M
Martin KaFai Lau 已提交
675

L
Lorenz Bauer 已提交
676 677 678 679 680 681 682 683
int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
{
	union bpf_attr attr;
	int ret;

	if (!test_attr->data_out && test_attr->data_size_out > 0)
		return -EINVAL;

684
	memset(&attr, 0, sizeof(attr));
L
Lorenz Bauer 已提交
685 686 687 688 689
	attr.test.prog_fd = test_attr->prog_fd;
	attr.test.data_in = ptr_to_u64(test_attr->data_in);
	attr.test.data_out = ptr_to_u64(test_attr->data_out);
	attr.test.data_size_in = test_attr->data_size_in;
	attr.test.data_size_out = test_attr->data_size_out;
690 691 692 693
	attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in);
	attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out);
	attr.test.ctx_size_in = test_attr->ctx_size_in;
	attr.test.ctx_size_out = test_attr->ctx_size_out;
L
Lorenz Bauer 已提交
694 695 696 697
	attr.test.repeat = test_attr->repeat;

	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
	test_attr->data_size_out = attr.test.data_size_out;
698
	test_attr->ctx_size_out = attr.test.ctx_size_out;
L
Lorenz Bauer 已提交
699 700 701 702 703
	test_attr->retval = attr.test.retval;
	test_attr->duration = attr.test.duration;
	return ret;
}

704
static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
M
Martin KaFai Lau 已提交
705 706 707 708
{
	union bpf_attr attr;
	int err;

709
	memset(&attr, 0, sizeof(attr));
M
Martin KaFai Lau 已提交
710 711
	attr.start_id = start_id;

712
	err = sys_bpf(cmd, &attr, sizeof(attr));
M
Martin KaFai Lau 已提交
713 714 715 716 717 718
	if (!err)
		*next_id = attr.next_id;

	return err;
}

719
int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
M
Martin KaFai Lau 已提交
720
{
721 722
	return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
}
M
Martin KaFai Lau 已提交
723

724 725 726
int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
{
	return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
M
Martin KaFai Lau 已提交
727 728
}

729 730 731 732 733
int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
{
	return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
}

734 735 736 737 738
int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
{
	return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
}

M
Martin KaFai Lau 已提交
739 740 741 742
int bpf_prog_get_fd_by_id(__u32 id)
{
	union bpf_attr attr;

743
	memset(&attr, 0, sizeof(attr));
M
Martin KaFai Lau 已提交
744 745 746 747 748 749 750 751 752
	attr.prog_id = id;

	return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
}

int bpf_map_get_fd_by_id(__u32 id)
{
	union bpf_attr attr;

753
	memset(&attr, 0, sizeof(attr));
M
Martin KaFai Lau 已提交
754 755 756 757 758
	attr.map_id = id;

	return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
}

759 760 761 762
int bpf_btf_get_fd_by_id(__u32 id)
{
	union bpf_attr attr;

763
	memset(&attr, 0, sizeof(attr));
764 765 766 767 768
	attr.btf_id = id;

	return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
}

769 770 771 772 773 774 775 776 777 778 779
int bpf_link_get_fd_by_id(__u32 id)
{
	union bpf_attr attr;

	memset(&attr, 0, sizeof(attr));
	attr.link_id = id;

	return sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr));
}

int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
M
Martin KaFai Lau 已提交
780 781 782 783
{
	union bpf_attr attr;
	int err;

784
	memset(&attr, 0, sizeof(attr));
785
	attr.info.bpf_fd = bpf_fd;
M
Martin KaFai Lau 已提交
786 787 788 789 790 791 792 793 794
	attr.info.info_len = *info_len;
	attr.info.info = ptr_to_u64(info);

	err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
	if (!err)
		*info_len = attr.info.info_len;

	return err;
}
E
Eric Leblond 已提交
795

796 797 798 799
int bpf_raw_tracepoint_open(const char *name, int prog_fd)
{
	union bpf_attr attr;

800
	memset(&attr, 0, sizeof(attr));
801 802 803 804 805 806
	attr.raw_tracepoint.name = ptr_to_u64(name);
	attr.raw_tracepoint.prog_fd = prog_fd;

	return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
}

807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
		 bool do_log)
{
	union bpf_attr attr = {};
	int fd;

	attr.btf = ptr_to_u64(btf);
	attr.btf_size = btf_size;

retry:
	if (do_log && log_buf && log_buf_size) {
		attr.btf_log_level = 1;
		attr.btf_log_size = log_buf_size;
		attr.btf_log_buf = ptr_to_u64(log_buf);
	}

	fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr));
	if (fd == -1 && !do_log && log_buf && log_buf_size) {
		do_log = true;
		goto retry;
	}

	return fd;
}
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853

int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
		      __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
		      __u64 *probe_addr)
{
	union bpf_attr attr = {};
	int err;

	attr.task_fd_query.pid = pid;
	attr.task_fd_query.fd = fd;
	attr.task_fd_query.flags = flags;
	attr.task_fd_query.buf = ptr_to_u64(buf);
	attr.task_fd_query.buf_len = *buf_len;

	err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
	*buf_len = attr.task_fd_query.buf_len;
	*prog_id = attr.task_fd_query.prog_id;
	*fd_type = attr.task_fd_query.fd_type;
	*probe_offset = attr.task_fd_query.probe_offset;
	*probe_addr = attr.task_fd_query.probe_addr;

	return err;
}
854 855 856 857 858 859 860 861 862 863

int bpf_enable_stats(enum bpf_stats_type type)
{
	union bpf_attr attr;

	memset(&attr, 0, sizeof(attr));
	attr.enable_stats.type = type;

	return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr));
}