mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-15 22:09:06 +08:00
Compare commits
68 Commits
netdata_pa
...
v1.4.3p_ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d1fe77f65 | ||
|
|
fbcb2871fe | ||
|
|
61a6e8edd7 | ||
|
|
4ab7361e64 | ||
|
|
ff856238e2 | ||
|
|
c085e9c364 | ||
|
|
805b689cd2 | ||
|
|
9b789075a9 | ||
|
|
c22d662a95 | ||
|
|
074445067f | ||
|
|
9a1f1f28c6 | ||
|
|
0a519f87ee | ||
|
|
d9f9fd5b22 | ||
|
|
d4d3e68e8d | ||
|
|
0babfb126a | ||
|
|
89ed67d7ab | ||
|
|
8dfa981c53 | ||
|
|
15b461a608 | ||
|
|
ec3c369941 | ||
|
|
89aecd2188 | ||
|
|
02724cfd07 | ||
|
|
3827aa514c | ||
|
|
e5146eff75 | ||
|
|
ed54f30307 | ||
|
|
fe5fe762b9 | ||
|
|
504369cba4 | ||
|
|
ea02e10fc4 | ||
|
|
4ec5e360ae | ||
|
|
cb7bfc5e51 | ||
|
|
e3e84bd7d0 | ||
|
|
f3c4172c61 | ||
|
|
d045f7682b | ||
|
|
b39b7f426f | ||
|
|
e055420033 | ||
|
|
255b705a16 | ||
|
|
6a41f02ad4 | ||
|
|
dd589c3b31 | ||
|
|
045a0372ef | ||
|
|
6c3cf5108e | ||
|
|
b63d2945ff | ||
|
|
d3e18fceec | ||
|
|
22bd976613 | ||
|
|
f9f3fbf72d | ||
|
|
37b8e0eb2d | ||
|
|
f28271ab72 | ||
|
|
b1051d9361 | ||
|
|
43df08cd17 | ||
|
|
4794f18bf4 | ||
|
|
2fdcc365a0 | ||
|
|
52c37177cc | ||
|
|
7cbfddfdf2 | ||
|
|
f2fe16ec95 | ||
|
|
a911ca1e3e | ||
|
|
24924003c6 | ||
|
|
2c6f445a8e | ||
|
|
09397e309a | ||
|
|
62217fb32a | ||
|
|
b521a722b9 | ||
|
|
98de9ace4d | ||
|
|
26d9ab5f78 | ||
|
|
c5219d1b3d | ||
|
|
8d3a3e138b | ||
|
|
9f2853a352 | ||
|
|
d2f83fb976 | ||
|
|
8b9cb7d479 | ||
|
|
b062410166 | ||
|
|
89d8cdf741 | ||
|
|
8a2054f417 |
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,3 +0,0 @@
|
||||
Thank you for considering a contribution!
|
||||
|
||||
Please note that the `libbpf` authoritative source code is developed as part of bpf-next Linux source tree under tools/lib/bpf subdirectory and is periodically synced to Github. As such, all the libbpf changes should be sent to BPF mailing list, please don't open PRs here unless you are changing Github-specific parts of libbpf (e.g., Github-specific Makefile).
|
||||
187775
.github/actions/build-selftests/vmlinux.h
vendored
187775
.github/actions/build-selftests/vmlinux.h
vendored
File diff suppressed because it is too large
Load Diff
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
name: Ubuntu Focal Build (${{ matrix.arch }})
|
||||
name: Ubuntu Build (${{ matrix.arch }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
if: matrix.arch != 'x86'
|
||||
with:
|
||||
distro:
|
||||
ubuntu20.04
|
||||
ubuntu22.04
|
||||
arch:
|
||||
${{ matrix.arch }}
|
||||
setup:
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -17,7 +17,7 @@ permissions:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
2
.github/workflows/pahole.yml
vendored
2
.github/workflows/pahole.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
vmtest:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Kernel LATEST + staging pahole
|
||||
env:
|
||||
STAGING: tmp.master
|
||||
|
||||
18
.mailmap
Normal file
18
.mailmap
Normal file
@@ -0,0 +1,18 @@
|
||||
Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
|
||||
Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com>
|
||||
Benjamin Tissoires <bentiss@kernel.org> <benjamin.tissoires@redhat.com>
|
||||
Björn Töpel <bjorn@kernel.org> <bjorn.topel@intel.com>
|
||||
Changbin Du <changbin.du@intel.com> <changbin.du@gmail.com>
|
||||
Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
|
||||
Dan Carpenter <error27@gmail.com> <dan.carpenter@oracle.com>
|
||||
Geliang Tang <geliang@kernel.org> <geliang.tang@suse.com>
|
||||
Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
|
||||
Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
|
||||
Mark Starovoytov <mstarovo@pm.me> <mstarovoitov@marvell.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
|
||||
Puranjay Mohan <puranjay@kernel.org> <puranjay12@gmail.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin@isovalent.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
|
||||
Vadim Fedorenko <vadim.fedorenko@linux.dev> <vfedorenko@novek.ru>
|
||||
@@ -1 +1 @@
|
||||
443574b033876c85a35de4c65c14f7fe092222b2
|
||||
62da3acd28955e7299babebdfcb14243b789e773
|
||||
|
||||
@@ -1 +1 @@
|
||||
14bb1e8c8d4ad5d9d2febb7d19c70a3cf536e1e5
|
||||
531876c80004ecff7bfdbd8ba6c6b48835ef5e22
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
From c71766e8ff7a7f950522d25896fba758585500df Mon Sep 17 00:00:00 2001
|
||||
From: Song Liu <song@kernel.org>
|
||||
Date: Mon, 22 Apr 2024 21:14:40 -0700
|
||||
Subject: [PATCH] arch/Kconfig: Move SPECULATION_MITIGATIONS to arch/Kconfig
|
||||
|
||||
SPECULATION_MITIGATIONS is currently defined only for x86. As a result,
|
||||
IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) is always false for other
|
||||
archs. f337a6a21e2f effectively set "mitigations=off" by default on
|
||||
non-x86 archs, which is not desired behavior. Jakub observed this
|
||||
change when running bpf selftests on s390 and arm64.
|
||||
|
||||
Fix this by moving SPECULATION_MITIGATIONS to arch/Kconfig so that it is
|
||||
available in all archs and thus can be used safely in kernel/cpu.c
|
||||
|
||||
Fixes: f337a6a21e2f ("x86/cpu: Actually turn off mitigations by default for SPECULATION_MITIGATIONS=n")
|
||||
Cc: stable@vger.kernel.org
|
||||
Cc: Sean Christopherson <seanjc@google.com>
|
||||
Cc: Ingo Molnar <mingo@kernel.org>
|
||||
Cc: Daniel Sneddon <daniel.sneddon@linux.intel.com>
|
||||
Cc: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Song Liu <song@kernel.org>
|
||||
---
|
||||
arch/Kconfig | 10 ++++++++++
|
||||
arch/x86/Kconfig | 10 ----------
|
||||
2 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/Kconfig b/arch/Kconfig
|
||||
index 9f066785bb71..8f4af75005f8 100644
|
||||
--- a/arch/Kconfig
|
||||
+++ b/arch/Kconfig
|
||||
@@ -1609,4 +1609,14 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
|
||||
# strict alignment always, even with -falign-functions.
|
||||
def_bool CC_HAS_MIN_FUNCTION_ALIGNMENT || CC_IS_CLANG
|
||||
|
||||
+menuconfig SPECULATION_MITIGATIONS
|
||||
+ bool "Mitigations for speculative execution vulnerabilities"
|
||||
+ default y
|
||||
+ help
|
||||
+ Say Y here to enable options which enable mitigations for
|
||||
+ speculative execution hardware vulnerabilities.
|
||||
+
|
||||
+ If you say N, all mitigations will be disabled. You really
|
||||
+ should know what you are doing to say so.
|
||||
+
|
||||
endmenu
|
||||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
|
||||
index 39886bab943a..50c890fce5e0 100644
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -2486,16 +2486,6 @@ config PREFIX_SYMBOLS
|
||||
def_bool y
|
||||
depends on CALL_PADDING && !CFI_CLANG
|
||||
|
||||
-menuconfig SPECULATION_MITIGATIONS
|
||||
- bool "Mitigations for speculative execution vulnerabilities"
|
||||
- default y
|
||||
- help
|
||||
- Say Y here to enable options which enable mitigations for
|
||||
- speculative execution hardware vulnerabilities.
|
||||
-
|
||||
- If you say N, all mitigations will be disabled. You really
|
||||
- should know what you are doing to say so.
|
||||
-
|
||||
if SPECULATION_MITIGATIONS
|
||||
|
||||
config MITIGATION_PAGE_TABLE_ISOLATION
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 0daad0a615e687e1247230f3d0c31ae60ba32314 Mon Sep 17 00:00:00 2001
|
||||
From: Andrii Nakryiko <andrii@kernel.org>
|
||||
Date: Tue, 28 May 2024 15:29:38 -0700
|
||||
Subject: [PATCH bpf-next] selftests/bpf: fix inet_csk_accept prototype in
|
||||
test_sk_storage_tracing.c
|
||||
|
||||
Recent kernel change ([0]) changed inet_csk_accept() prototype. Adapt
|
||||
progs/test_sk_storage_tracing.c to take that into account.
|
||||
|
||||
[0] 92ef0fd55ac8 ("net: change proto and proto_ops accept type")
|
||||
|
||||
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
|
||||
---
|
||||
tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
index 02e718f06e0f..40531e56776e 100644
|
||||
--- a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
+++ b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
@@ -84,7 +84,7 @@ int BPF_PROG(trace_tcp_connect, struct sock *sk)
|
||||
}
|
||||
|
||||
SEC("fexit/inet_csk_accept")
|
||||
-int BPF_PROG(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern,
|
||||
+int BPF_PROG(inet_csk_accept, struct sock *sk, struct proto_accept_arg *arg,
|
||||
struct sock *accepted_sk)
|
||||
{
|
||||
set_task_info(accepted_sk);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -41,7 +41,6 @@ task_fd_query_rawtp
|
||||
task_fd_query_tp
|
||||
tc_bpf
|
||||
tcp_estats
|
||||
tcp_rtt
|
||||
test_global_funcs/arg_tag_ctx*
|
||||
tp_attach_query
|
||||
usdt/urand_pid_attach
|
||||
|
||||
@@ -219,6 +219,14 @@ compilation and skeleton generation. Using Libbpf-rs will make building user
|
||||
space part of the BPF application easier. Note that the BPF program themselves
|
||||
must still be written in plain C.
|
||||
|
||||
libbpf logging
|
||||
==============
|
||||
|
||||
By default, libbpf logs informational and warning messages to stderr. The
|
||||
verbosity of these messages can be controlled by setting the environment
|
||||
variable LIBBPF_LOG_LEVEL to either warn, info, or debug. A custom log
|
||||
callback can be set using ``libbpf_set_print()``.
|
||||
|
||||
Additional Documentation
|
||||
========================
|
||||
|
||||
|
||||
@@ -1115,6 +1115,7 @@ enum bpf_attach_type {
|
||||
BPF_CGROUP_UNIX_GETSOCKNAME,
|
||||
BPF_NETKIT_PRIMARY,
|
||||
BPF_NETKIT_PEER,
|
||||
BPF_TRACE_KPROBE_SESSION,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
@@ -1135,6 +1136,7 @@ enum bpf_link_type {
|
||||
BPF_LINK_TYPE_TCX = 11,
|
||||
BPF_LINK_TYPE_UPROBE_MULTI = 12,
|
||||
BPF_LINK_TYPE_NETKIT = 13,
|
||||
BPF_LINK_TYPE_SOCKMAP = 14,
|
||||
__MAX_BPF_LINK_TYPE,
|
||||
};
|
||||
|
||||
@@ -3394,6 +3396,10 @@ union bpf_attr {
|
||||
* for the nexthop. If the src addr cannot be derived,
|
||||
* **BPF_FIB_LKUP_RET_NO_SRC_ADDR** is returned. In this
|
||||
* case, *params*->dmac and *params*->smac are not set either.
|
||||
* **BPF_FIB_LOOKUP_MARK**
|
||||
* Use the mark present in *params*->mark for the fib lookup.
|
||||
* This option should not be used with BPF_FIB_LOOKUP_DIRECT,
|
||||
* as it only has meaning for full lookups.
|
||||
*
|
||||
* *ctx* is either **struct xdp_md** for XDP programs or
|
||||
* **struct sk_buff** tc cls_act programs.
|
||||
@@ -5022,7 +5028,7 @@ union bpf_attr {
|
||||
* bytes will be copied to *dst*
|
||||
* Return
|
||||
* The **hash_algo** is returned on success,
|
||||
* **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
|
||||
* **-EOPNOTSUPP** if IMA is disabled or **-EINVAL** if
|
||||
* invalid arguments are passed.
|
||||
*
|
||||
* struct socket *bpf_sock_from_file(struct file *file)
|
||||
@@ -5508,7 +5514,7 @@ union bpf_attr {
|
||||
* bytes will be copied to *dst*
|
||||
* Return
|
||||
* The **hash_algo** is returned on success,
|
||||
* **-EOPNOTSUP** if the hash calculation failed or **-EINVAL** if
|
||||
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
|
||||
* invalid arguments are passed.
|
||||
*
|
||||
* void *bpf_kptr_xchg(void *map_value, void *ptr)
|
||||
@@ -6201,12 +6207,17 @@ union { \
|
||||
__u64 :64; \
|
||||
} __attribute__((aligned(8)))
|
||||
|
||||
/* The enum used in skb->tstamp_type. It specifies the clock type
|
||||
* of the time stored in the skb->tstamp.
|
||||
*/
|
||||
enum {
|
||||
BPF_SKB_TSTAMP_UNSPEC,
|
||||
BPF_SKB_TSTAMP_DELIVERY_MONO, /* tstamp has mono delivery time */
|
||||
/* For any BPF_SKB_TSTAMP_* that the bpf prog cannot handle,
|
||||
* the bpf prog should handle it like BPF_SKB_TSTAMP_UNSPEC
|
||||
* and try to deduce it by ingress, egress or skb->sk->sk_clockid.
|
||||
BPF_SKB_TSTAMP_UNSPEC = 0, /* DEPRECATED */
|
||||
BPF_SKB_TSTAMP_DELIVERY_MONO = 1, /* DEPRECATED */
|
||||
BPF_SKB_CLOCK_REALTIME = 0,
|
||||
BPF_SKB_CLOCK_MONOTONIC = 1,
|
||||
BPF_SKB_CLOCK_TAI = 2,
|
||||
/* For any future BPF_SKB_CLOCK_* that the bpf prog cannot handle,
|
||||
* the bpf prog can try to deduce it by ingress/egress/skb->sk->sk_clockid.
|
||||
*/
|
||||
};
|
||||
|
||||
@@ -6720,6 +6731,10 @@ struct bpf_link_info {
|
||||
__u32 ifindex;
|
||||
__u32 attach_type;
|
||||
} netkit;
|
||||
struct {
|
||||
__u32 map_id;
|
||||
__u32 attach_type;
|
||||
} sockmap;
|
||||
};
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
@@ -6938,6 +6953,8 @@ enum {
|
||||
* socket transition to LISTEN state.
|
||||
*/
|
||||
BPF_SOCK_OPS_RTT_CB, /* Called on every RTT.
|
||||
* Arg1: measured RTT input (mrtt)
|
||||
* Arg2: updated srtt
|
||||
*/
|
||||
BPF_SOCK_OPS_PARSE_HDR_OPT_CB, /* Parse the header option.
|
||||
* It will be called to handle
|
||||
@@ -7120,6 +7137,7 @@ enum {
|
||||
BPF_FIB_LOOKUP_SKIP_NEIGH = (1U << 2),
|
||||
BPF_FIB_LOOKUP_TBID = (1U << 3),
|
||||
BPF_FIB_LOOKUP_SRC = (1U << 4),
|
||||
BPF_FIB_LOOKUP_MARK = (1U << 5),
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -7152,7 +7170,7 @@ struct bpf_fib_lookup {
|
||||
|
||||
/* output: MTU value */
|
||||
__u16 mtu_result;
|
||||
};
|
||||
} __attribute__((packed, aligned(2)));
|
||||
/* input: L3 device index for lookup
|
||||
* output: device index from FIB lookup
|
||||
*/
|
||||
@@ -7197,8 +7215,19 @@ struct bpf_fib_lookup {
|
||||
__u32 tbid;
|
||||
};
|
||||
|
||||
__u8 smac[6]; /* ETH_ALEN */
|
||||
__u8 dmac[6]; /* ETH_ALEN */
|
||||
union {
|
||||
/* input */
|
||||
struct {
|
||||
__u32 mark; /* policy routing */
|
||||
/* 2 4-byte holes for input */
|
||||
};
|
||||
|
||||
/* output: source and dest mac */
|
||||
struct {
|
||||
__u8 smac[6]; /* ETH_ALEN */
|
||||
__u8 dmac[6]; /* ETH_ALEN */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct bpf_redir_neigh {
|
||||
@@ -7285,6 +7314,10 @@ struct bpf_timer {
|
||||
__u64 __opaque[2];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct bpf_wq {
|
||||
__u64 __opaque[2];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct bpf_dynptr {
|
||||
__u64 __opaque[2];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_FCNTL_H
|
||||
#define _UAPI_LINUX_FCNTL_H
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
#include <linux/openat2.h>
|
||||
|
||||
#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
|
||||
#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
|
||||
|
||||
/*
|
||||
* Cancel a blocking posix lock; internal use only until we expose an
|
||||
* asynchronous lock api to userspace:
|
||||
*/
|
||||
#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
|
||||
|
||||
/* Create a file descriptor with FD_CLOEXEC set. */
|
||||
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
|
||||
|
||||
/*
|
||||
* Request nofications on a directory.
|
||||
* See below for events that may be notified.
|
||||
*/
|
||||
#define F_NOTIFY (F_LINUX_SPECIFIC_BASE+2)
|
||||
|
||||
/*
|
||||
* Set and get of pipe page size array
|
||||
*/
|
||||
#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
|
||||
#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
|
||||
|
||||
/*
|
||||
* Set/Get seals
|
||||
*/
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
/*
|
||||
* Types of seals
|
||||
*/
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */
|
||||
#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */
|
||||
/* (1U << 31) is reserved for signed error codes */
|
||||
|
||||
/*
|
||||
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||
* the specific file.
|
||||
*/
|
||||
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
|
||||
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
|
||||
#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
|
||||
#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
|
||||
|
||||
/*
|
||||
* Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
|
||||
* used to clear any hints previously set.
|
||||
*/
|
||||
#define RWH_WRITE_LIFE_NOT_SET 0
|
||||
#define RWH_WRITE_LIFE_NONE 1
|
||||
#define RWH_WRITE_LIFE_SHORT 2
|
||||
#define RWH_WRITE_LIFE_MEDIUM 3
|
||||
#define RWH_WRITE_LIFE_LONG 4
|
||||
#define RWH_WRITE_LIFE_EXTREME 5
|
||||
|
||||
/*
|
||||
* The originally introduced spelling is remained from the first
|
||||
* versions of the patch set that introduced the feature, see commit
|
||||
* v4.13-rc1~212^2~51.
|
||||
*/
|
||||
#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
|
||||
|
||||
/*
|
||||
* Types of directory notifications that may be requested.
|
||||
*/
|
||||
#define DN_ACCESS 0x00000001 /* File accessed */
|
||||
#define DN_MODIFY 0x00000002 /* File modified */
|
||||
#define DN_CREATE 0x00000004 /* File created */
|
||||
#define DN_DELETE 0x00000008 /* File removed */
|
||||
#define DN_RENAME 0x00000010 /* File renamed */
|
||||
#define DN_ATTRIB 0x00000020 /* File changed attibutes */
|
||||
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
|
||||
|
||||
/*
|
||||
* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
||||
* meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
||||
* unlinkat. The two functions do completely different things and therefore,
|
||||
* the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
||||
* faccessat would be undefined behavior and thus treating it equivalent to
|
||||
* AT_EACCESS is valid undefined behavior.
|
||||
*/
|
||||
#define AT_FDCWD -100 /* Special value used to indicate
|
||||
openat should use the current
|
||||
working directory. */
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
|
||||
#define AT_EACCESS 0x200 /* Test access permitted for
|
||||
effective IDs, not real IDs. */
|
||||
#define AT_REMOVEDIR 0x200 /* Remove directory instead of
|
||||
unlinking file. */
|
||||
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
|
||||
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
|
||||
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
|
||||
|
||||
#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
|
||||
#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
|
||||
#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
|
||||
|
||||
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||
|
||||
/* Flags for name_to_handle_at(2). We reuse AT_ flag space to save bits... */
|
||||
#define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to
|
||||
compare object identity and may not
|
||||
be usable to open_by_handle_at(2) */
|
||||
#if defined(__KERNEL__)
|
||||
#define AT_GETATTR_NOSEC 0x80000000
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI_LINUX_FCNTL_H */
|
||||
@@ -146,6 +146,28 @@ enum {
|
||||
NETDEV_A_QSTATS_TX_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_BYTES,
|
||||
NETDEV_A_QSTATS_RX_ALLOC_FAIL,
|
||||
NETDEV_A_QSTATS_RX_HW_DROPS,
|
||||
NETDEV_A_QSTATS_RX_HW_DROP_OVERRUNS,
|
||||
NETDEV_A_QSTATS_RX_CSUM_COMPLETE,
|
||||
NETDEV_A_QSTATS_RX_CSUM_UNNECESSARY,
|
||||
NETDEV_A_QSTATS_RX_CSUM_NONE,
|
||||
NETDEV_A_QSTATS_RX_CSUM_BAD,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_PACKETS,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_BYTES,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_WIRE_PACKETS,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_WIRE_BYTES,
|
||||
NETDEV_A_QSTATS_RX_HW_DROP_RATELIMITS,
|
||||
NETDEV_A_QSTATS_TX_HW_DROPS,
|
||||
NETDEV_A_QSTATS_TX_HW_DROP_ERRORS,
|
||||
NETDEV_A_QSTATS_TX_CSUM_NONE,
|
||||
NETDEV_A_QSTATS_TX_NEEDS_CSUM,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_BYTES,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES,
|
||||
NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS,
|
||||
NETDEV_A_QSTATS_TX_STOP,
|
||||
NETDEV_A_QSTATS_TX_WAKE,
|
||||
|
||||
__NETDEV_A_QSTATS_MAX,
|
||||
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_OPENAT2_H
|
||||
#define _UAPI_LINUX_OPENAT2_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Arguments for how openat2(2) should open the target path. If only @flags and
|
||||
* @mode are non-zero, then openat2(2) operates very similarly to openat(2).
|
||||
*
|
||||
* However, unlike openat(2), unknown or invalid bits in @flags result in
|
||||
* -EINVAL rather than being silently ignored. @mode must be zero unless one of
|
||||
* {O_CREAT, O_TMPFILE} are set.
|
||||
*
|
||||
* @flags: O_* flags.
|
||||
* @mode: O_CREAT/O_TMPFILE file mode.
|
||||
* @resolve: RESOLVE_* flags.
|
||||
*/
|
||||
struct open_how {
|
||||
__u64 flags;
|
||||
__u64 mode;
|
||||
__u64 resolve;
|
||||
};
|
||||
|
||||
/* how->resolve flags for openat2(2). */
|
||||
#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
|
||||
(includes bind-mounts). */
|
||||
#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
|
||||
"magic-links". */
|
||||
#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
|
||||
(implies OEXT_NO_MAGICLINKS) */
|
||||
#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
|
||||
"..", symlinks, and absolute
|
||||
paths which escape the dirfd. */
|
||||
#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
|
||||
be scoped inside the dirfd
|
||||
(similar to chroot(2)). */
|
||||
#define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
|
||||
completed through cached lookup. May
|
||||
return -EAGAIN if that's not
|
||||
possible. */
|
||||
|
||||
#endif /* _UAPI_LINUX_OPENAT2_H */
|
||||
37
scripts/mailmap-update.sh
Executable file
37
scripts/mailmap-update.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
usage () {
|
||||
echo "USAGE: ./mailmap-update.sh <libbpf-repo> <linux-repo>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
LIBBPF_REPO="${1-""}"
|
||||
LINUX_REPO="${2-""}"
|
||||
|
||||
if [ -z "${LIBBPF_REPO}" ] || [ -z "${LINUX_REPO}" ]; then
|
||||
echo "Error: libbpf or linux repos are not specified"
|
||||
usage
|
||||
fi
|
||||
|
||||
LIBBPF_MAILMAP="${LIBBPF_REPO}/.mailmap"
|
||||
LINUX_MAILMAP="${LINUX_REPO}/.mailmap"
|
||||
|
||||
tmpfile="$(mktemp)"
|
||||
cleanup() {
|
||||
rm -f "${tmpfile}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
grep_lines() {
|
||||
local pattern="$1"
|
||||
local file="$2"
|
||||
grep "${pattern}" "${file}" || true
|
||||
}
|
||||
|
||||
while read -r email; do
|
||||
grep_lines "${email}$" "${LINUX_MAILMAP}" >> "${tmpfile}"
|
||||
done < <(git log --format='<%ae>' | sort -u)
|
||||
|
||||
sort -u "${tmpfile}" > "${LIBBPF_MAILMAP}"
|
||||
@@ -295,6 +295,22 @@ Latest changes to BPF helper definitions.
|
||||
" -- src/bpf_helper_defs.h
|
||||
fi
|
||||
|
||||
echo "Regenerating .mailmap..."
|
||||
cd_to "${LINUX_REPO}"
|
||||
git checkout "${TIP_SYM_REF}"
|
||||
cd_to "${LIBBPF_REPO}"
|
||||
"${LIBBPF_REPO}"/scripts/mailmap-update.sh "${LIBBPF_REPO}" "${LINUX_REPO}"
|
||||
# if anything changed, commit it
|
||||
mailmap_changes=$(git status --porcelain .mailmap | wc -l)
|
||||
if ((${mailmap_changes} == 1)); then
|
||||
git add .mailmap
|
||||
git commit -s -m "sync: update .mailmap
|
||||
|
||||
Update .mailmap based on libbpf's list of contributors and on the latest
|
||||
.mailmap version in the upstream repository.
|
||||
" -- .mailmap
|
||||
fi
|
||||
|
||||
# Use generated cover-letter as a template for "sync commit" with
|
||||
# baseline and checkpoint commits from kernel repo (and leave summary
|
||||
# from cover letter intact, of course)
|
||||
|
||||
@@ -9,7 +9,7 @@ else
|
||||
endif
|
||||
|
||||
LIBBPF_MAJOR_VERSION := 1
|
||||
LIBBPF_MINOR_VERSION := 4
|
||||
LIBBPF_MINOR_VERSION := 5
|
||||
LIBBPF_PATCH_VERSION := 0
|
||||
LIBBPF_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).$(LIBBPF_PATCH_VERSION)
|
||||
LIBBPF_MAJMIN_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).0
|
||||
|
||||
@@ -105,7 +105,7 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
|
||||
*/
|
||||
int probe_memcg_account(int token_fd)
|
||||
{
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
|
||||
BPF_EXIT_INSN(),
|
||||
@@ -766,6 +766,7 @@ int bpf_link_create(int prog_fd, int target_fd,
|
||||
return libbpf_err(-EINVAL);
|
||||
break;
|
||||
case BPF_TRACE_KPROBE_MULTI:
|
||||
case BPF_TRACE_KPROBE_SESSION:
|
||||
attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
|
||||
attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
|
||||
attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef __BPF_CORE_READ_H__
|
||||
#define __BPF_CORE_READ_H__
|
||||
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_helpers.h"
|
||||
|
||||
/*
|
||||
* enum bpf_field_info_kind is passed as a second argument into
|
||||
@@ -104,6 +104,7 @@ enum bpf_enum_value_kind {
|
||||
case 2: val = *(const unsigned short *)p; break; \
|
||||
case 4: val = *(const unsigned int *)p; break; \
|
||||
case 8: val = *(const unsigned long long *)p; break; \
|
||||
default: val = 0; break; \
|
||||
} \
|
||||
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
|
||||
if (__CORE_RELO(s, field, SIGNED)) \
|
||||
|
||||
@@ -1851,6 +1851,10 @@ static long (* const bpf_skb_load_bytes_relative)(const void *skb, __u32 offset,
|
||||
* for the nexthop. If the src addr cannot be derived,
|
||||
* **BPF_FIB_LKUP_RET_NO_SRC_ADDR** is returned. In this
|
||||
* case, *params*->dmac and *params*->smac are not set either.
|
||||
* **BPF_FIB_LOOKUP_MARK**
|
||||
* Use the mark present in *params*->mark for the fib lookup.
|
||||
* This option should not be used with BPF_FIB_LOOKUP_DIRECT,
|
||||
* as it only has meaning for full lookups.
|
||||
*
|
||||
* *ctx* is either **struct xdp_md** for XDP programs or
|
||||
* **struct sk_buff** tc cls_act programs.
|
||||
@@ -3798,7 +3802,7 @@ static __u64 (* const bpf_ktime_get_coarse_ns)(void) = (void *) 160;
|
||||
*
|
||||
* Returns
|
||||
* The **hash_algo** is returned on success,
|
||||
* **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
|
||||
* **-EOPNOTSUPP** if IMA is disabled or **-EINVAL** if
|
||||
* invalid arguments are passed.
|
||||
*/
|
||||
static long (* const bpf_ima_inode_hash)(struct inode *inode, void *dst, __u32 size) = (void *) 161;
|
||||
@@ -4412,7 +4416,7 @@ static long (* const bpf_skb_set_tstamp)(struct __sk_buff *skb, __u64 tstamp, __
|
||||
*
|
||||
* Returns
|
||||
* The **hash_algo** is returned on success,
|
||||
* **-EOPNOTSUP** if the hash calculation failed or **-EINVAL** if
|
||||
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
|
||||
* invalid arguments are passed.
|
||||
*/
|
||||
static long (* const bpf_ima_file_hash)(struct file *file, void *dst, __u32 size) = (void *) 193;
|
||||
|
||||
@@ -137,7 +137,8 @@
|
||||
/*
|
||||
* Helper function to perform a tail call with a constant/immediate map slot.
|
||||
*/
|
||||
#if __clang_major__ >= 8 && defined(__bpf__)
|
||||
#if (defined(__clang__) && __clang_major__ >= 8) || (!defined(__clang__) && __GNUC__ > 12)
|
||||
#if defined(__bpf__)
|
||||
static __always_inline void
|
||||
bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
|
||||
{
|
||||
@@ -165,6 +166,7 @@ bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
@@ -184,10 +186,21 @@ enum libbpf_tristate {
|
||||
#define __kptr __attribute__((btf_type_tag("kptr")))
|
||||
#define __percpu_kptr __attribute__((btf_type_tag("percpu_kptr")))
|
||||
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
#if defined (__clang__)
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(!__builtin_constant_p(!!sym), \
|
||||
#sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
})
|
||||
#elif __GNUC__ > 8
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(__builtin_has_attribute (*sym, __weak__), \
|
||||
#sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
})
|
||||
#else
|
||||
#define bpf_ksym_exists(sym) !!sym
|
||||
#endif
|
||||
|
||||
#define __arg_ctx __attribute__((btf_decl_tag("arg:ctx")))
|
||||
#define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull")))
|
||||
|
||||
@@ -633,18 +633,18 @@ struct pt_regs;
|
||||
#endif
|
||||
|
||||
#define ___bpf_ctx_cast0() ctx
|
||||
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
|
||||
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
|
||||
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
|
||||
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
|
||||
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
|
||||
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
|
||||
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
|
||||
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
|
||||
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
|
||||
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
|
||||
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
|
||||
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
|
||||
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), ctx[0]
|
||||
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), ctx[1]
|
||||
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), ctx[2]
|
||||
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), ctx[3]
|
||||
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), ctx[4]
|
||||
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), ctx[5]
|
||||
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), ctx[6]
|
||||
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), ctx[7]
|
||||
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), ctx[8]
|
||||
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), ctx[9]
|
||||
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), ctx[10]
|
||||
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), ctx[11]
|
||||
#define ___bpf_ctx_cast(args...) ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -786,14 +786,14 @@ ____##name(unsigned long long *ctx ___bpf_ctx_decl(args))
|
||||
struct pt_regs;
|
||||
|
||||
#define ___bpf_kprobe_args0() ctx
|
||||
#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
|
||||
#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
|
||||
#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
|
||||
#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
|
||||
#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
|
||||
#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (void *)PT_REGS_PARM6(ctx)
|
||||
#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (void *)PT_REGS_PARM7(ctx)
|
||||
#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (void *)PT_REGS_PARM8(ctx)
|
||||
#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (unsigned long long)PT_REGS_PARM1(ctx)
|
||||
#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (unsigned long long)PT_REGS_PARM2(ctx)
|
||||
#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (unsigned long long)PT_REGS_PARM3(ctx)
|
||||
#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (unsigned long long)PT_REGS_PARM4(ctx)
|
||||
#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (unsigned long long)PT_REGS_PARM5(ctx)
|
||||
#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (unsigned long long)PT_REGS_PARM6(ctx)
|
||||
#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (unsigned long long)PT_REGS_PARM7(ctx)
|
||||
#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (unsigned long long)PT_REGS_PARM8(ctx)
|
||||
#define ___bpf_kprobe_args(args...) ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -821,7 +821,7 @@ static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
#define ___bpf_kretprobe_args0() ctx
|
||||
#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
||||
#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (unsigned long long)PT_REGS_RC(ctx)
|
||||
#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -845,24 +845,24 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
/* If kernel has CONFIG_ARCH_HAS_SYSCALL_WRAPPER, read pt_regs directly */
|
||||
#define ___bpf_syscall_args0() ctx
|
||||
#define ___bpf_syscall_args1(x) ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (void *)PT_REGS_PARM6_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (void *)PT_REGS_PARM7_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args1(x) ___bpf_syscall_args0(), (unsigned long long)PT_REGS_PARM1_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (unsigned long long)PT_REGS_PARM2_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (unsigned long long)PT_REGS_PARM3_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (unsigned long long)PT_REGS_PARM4_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (unsigned long long)PT_REGS_PARM5_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (unsigned long long)PT_REGS_PARM6_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (unsigned long long)PT_REGS_PARM7_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args(args...) ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
|
||||
|
||||
/* If kernel doesn't have CONFIG_ARCH_HAS_SYSCALL_WRAPPER, we have to BPF_CORE_READ from pt_regs */
|
||||
#define ___bpf_syswrap_args0() ctx
|
||||
#define ___bpf_syswrap_args1(x) ___bpf_syswrap_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (void *)PT_REGS_PARM6_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (void *)PT_REGS_PARM7_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args1(x) ___bpf_syswrap_args0(), (unsigned long long)PT_REGS_PARM1_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (unsigned long long)PT_REGS_PARM2_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (unsigned long long)PT_REGS_PARM3_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (unsigned long long)PT_REGS_PARM4_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (unsigned long long)PT_REGS_PARM5_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (unsigned long long)PT_REGS_PARM6_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (unsigned long long)PT_REGS_PARM7_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args(args...) ___bpf_apply(___bpf_syswrap_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
|
||||
@@ -1929,6 +1929,7 @@ static int btf_dump_int_data(struct btf_dump *d,
|
||||
if (d->typed_dump->is_array_terminated)
|
||||
break;
|
||||
if (*(char *)data == '\0') {
|
||||
btf_dump_type_values(d, "'\\0'");
|
||||
d->typed_dump->is_array_terminated = true;
|
||||
break;
|
||||
}
|
||||
@@ -2031,6 +2032,7 @@ static int btf_dump_array_data(struct btf_dump *d,
|
||||
__u32 i, elem_type_id;
|
||||
__s64 elem_size;
|
||||
bool is_array_member;
|
||||
bool is_array_terminated;
|
||||
|
||||
elem_type_id = array->type;
|
||||
elem_type = skip_mods_and_typedefs(d->btf, elem_type_id, NULL);
|
||||
@@ -2066,12 +2068,15 @@ static int btf_dump_array_data(struct btf_dump *d,
|
||||
*/
|
||||
is_array_member = d->typed_dump->is_array_member;
|
||||
d->typed_dump->is_array_member = true;
|
||||
is_array_terminated = d->typed_dump->is_array_terminated;
|
||||
d->typed_dump->is_array_terminated = false;
|
||||
for (i = 0; i < array->nelems; i++, data += elem_size) {
|
||||
if (d->typed_dump->is_array_terminated)
|
||||
break;
|
||||
btf_dump_dump_type_data(d, NULL, elem_type, elem_type_id, data, 0, 0);
|
||||
}
|
||||
d->typed_dump->is_array_member = is_array_member;
|
||||
d->typed_dump->is_array_terminated = is_array_terminated;
|
||||
d->typed_dump->depth--;
|
||||
btf_dump_data_pfx(d);
|
||||
btf_dump_type_values(d, "]");
|
||||
|
||||
@@ -22,7 +22,7 @@ int probe_fd(int fd)
|
||||
|
||||
static int probe_kern_prog_name(int token_fd)
|
||||
{
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_name);
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
@@ -392,11 +392,41 @@ static int probe_uprobe_multi_link(int token_fd)
|
||||
link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, &link_opts);
|
||||
err = -errno; /* close() can clobber errno */
|
||||
|
||||
if (link_fd >= 0 || err != -EBADF) {
|
||||
if (link_fd >= 0)
|
||||
close(link_fd);
|
||||
close(prog_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initial multi-uprobe support in kernel didn't handle PID filtering
|
||||
* correctly (it was doing thread filtering, not process filtering).
|
||||
* So now we'll detect if PID filtering logic was fixed, and, if not,
|
||||
* we'll pretend multi-uprobes are not supported, if not.
|
||||
* Multi-uprobes are used in USDT attachment logic, and we need to be
|
||||
* conservative here, because multi-uprobe selection happens early at
|
||||
* load time, while the use of PID filtering is known late at
|
||||
* attachment time, at which point it's too late to undo multi-uprobe
|
||||
* selection.
|
||||
*
|
||||
* Creating uprobe with pid == -1 for (invalid) '/' binary will fail
|
||||
* early with -EINVAL on kernels with fixed PID filtering logic;
|
||||
* otherwise -ESRCH would be returned if passed correct binary path
|
||||
* (but we'll just get -BADF, of course).
|
||||
*/
|
||||
link_opts.uprobe_multi.pid = -1; /* invalid PID */
|
||||
link_opts.uprobe_multi.path = "/"; /* invalid path */
|
||||
link_opts.uprobe_multi.offsets = &offset;
|
||||
link_opts.uprobe_multi.cnt = 1;
|
||||
|
||||
link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, &link_opts);
|
||||
err = -errno; /* close() can clobber errno */
|
||||
|
||||
if (link_fd >= 0)
|
||||
close(link_fd);
|
||||
close(prog_fd);
|
||||
|
||||
return link_fd < 0 && err == -EBADF;
|
||||
return link_fd < 0 && err == -EINVAL;
|
||||
}
|
||||
|
||||
static int probe_kern_bpf_cookie(int token_fd)
|
||||
|
||||
187
src/libbpf.c
187
src/libbpf.c
@@ -132,6 +132,7 @@ static const char * const attach_type_name[] = {
|
||||
[BPF_TRACE_UPROBE_MULTI] = "trace_uprobe_multi",
|
||||
[BPF_NETKIT_PRIMARY] = "netkit_primary",
|
||||
[BPF_NETKIT_PEER] = "netkit_peer",
|
||||
[BPF_TRACE_KPROBE_SESSION] = "trace_kprobe_session",
|
||||
};
|
||||
|
||||
static const char * const link_type_name[] = {
|
||||
@@ -149,6 +150,7 @@ static const char * const link_type_name[] = {
|
||||
[BPF_LINK_TYPE_TCX] = "tcx",
|
||||
[BPF_LINK_TYPE_UPROBE_MULTI] = "uprobe_multi",
|
||||
[BPF_LINK_TYPE_NETKIT] = "netkit",
|
||||
[BPF_LINK_TYPE_SOCKMAP] = "sockmap",
|
||||
};
|
||||
|
||||
static const char * const map_type_name[] = {
|
||||
@@ -227,7 +229,30 @@ static const char * const prog_type_name[] = {
|
||||
static int __base_pr(enum libbpf_print_level level, const char *format,
|
||||
va_list args)
|
||||
{
|
||||
if (level == LIBBPF_DEBUG)
|
||||
const char *env_var = "LIBBPF_LOG_LEVEL";
|
||||
static enum libbpf_print_level min_level = LIBBPF_INFO;
|
||||
static bool initialized;
|
||||
|
||||
if (!initialized) {
|
||||
char *verbosity;
|
||||
|
||||
initialized = true;
|
||||
verbosity = getenv(env_var);
|
||||
if (verbosity) {
|
||||
if (strcasecmp(verbosity, "warn") == 0)
|
||||
min_level = LIBBPF_WARN;
|
||||
else if (strcasecmp(verbosity, "debug") == 0)
|
||||
min_level = LIBBPF_DEBUG;
|
||||
else if (strcasecmp(verbosity, "info") == 0)
|
||||
min_level = LIBBPF_INFO;
|
||||
else
|
||||
fprintf(stderr, "libbpf: unrecognized '%s' envvar value: '%s', should be one of 'warn', 'debug', or 'info'.\n",
|
||||
env_var, verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
/* if too verbose, skip logging */
|
||||
if (level > min_level)
|
||||
return 0;
|
||||
|
||||
return vfprintf(stderr, format, args);
|
||||
@@ -1126,6 +1151,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
|
||||
const struct btf_type *mtype, *kern_mtype;
|
||||
__u32 mtype_id, kern_mtype_id;
|
||||
void *mdata, *kern_mdata;
|
||||
struct bpf_program *prog;
|
||||
__s64 msize, kern_msize;
|
||||
__u32 moff, kern_moff;
|
||||
__u32 kern_member_idx;
|
||||
@@ -1143,18 +1169,28 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
|
||||
|
||||
kern_member = find_member_by_name(kern_btf, kern_type, mname);
|
||||
if (!kern_member) {
|
||||
/* Skip all zeros or null fields if they are not
|
||||
* presented in the kernel BTF.
|
||||
*/
|
||||
if (libbpf_is_mem_zeroed(mdata, msize)) {
|
||||
pr_info("struct_ops %s: member %s not found in kernel, skipping it as it's set to zero\n",
|
||||
if (!libbpf_is_mem_zeroed(mdata, msize)) {
|
||||
pr_warn("struct_ops init_kern %s: Cannot find member %s in kernel BTF\n",
|
||||
map->name, mname);
|
||||
continue;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
pr_warn("struct_ops init_kern %s: Cannot find member %s in kernel BTF\n",
|
||||
if (st_ops->progs[i]) {
|
||||
/* If we had declaratively set struct_ops callback, we need to
|
||||
* force its autoload to false, because it doesn't have
|
||||
* a chance of succeeding from POV of the current struct_ops map.
|
||||
* If this program is still referenced somewhere else, though,
|
||||
* then bpf_object_adjust_struct_ops_autoload() will update its
|
||||
* autoload accordingly.
|
||||
*/
|
||||
st_ops->progs[i]->autoload = false;
|
||||
st_ops->progs[i] = NULL;
|
||||
}
|
||||
|
||||
/* Skip all-zero/NULL fields if they are not present in the kernel BTF */
|
||||
pr_info("struct_ops %s: member %s not found in kernel, skipping it as it's set to zero\n",
|
||||
map->name, mname);
|
||||
return -ENOTSUP;
|
||||
continue;
|
||||
}
|
||||
|
||||
kern_member_idx = kern_member - btf_members(kern_type);
|
||||
@@ -1180,13 +1216,19 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
|
||||
}
|
||||
|
||||
if (btf_is_ptr(mtype)) {
|
||||
struct bpf_program *prog;
|
||||
prog = *(void **)mdata;
|
||||
/* just like for !kern_member case above, reset declaratively
|
||||
* set (at compile time) program's autload to false,
|
||||
* if user replaced it with another program or NULL
|
||||
*/
|
||||
if (st_ops->progs[i] && st_ops->progs[i] != prog)
|
||||
st_ops->progs[i]->autoload = false;
|
||||
|
||||
/* Update the value from the shadow type */
|
||||
prog = *(void **)mdata;
|
||||
st_ops->progs[i] = prog;
|
||||
if (!prog)
|
||||
continue;
|
||||
|
||||
if (!is_valid_st_ops_program(obj, prog)) {
|
||||
pr_warn("struct_ops init_kern %s: member %s is not a struct_ops program\n",
|
||||
map->name, mname);
|
||||
@@ -1970,6 +2012,20 @@ static struct extern_desc *find_extern_by_name(const struct bpf_object *obj,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct extern_desc *find_extern_by_name_with_len(const struct bpf_object *obj,
|
||||
const void *name, int len)
|
||||
{
|
||||
const char *ext_name;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < obj->nr_extern; i++) {
|
||||
ext_name = obj->externs[i].name;
|
||||
if (strlen(ext_name) == len && strncmp(ext_name, name, len) == 0)
|
||||
return &obj->externs[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int set_kcfg_value_tri(struct extern_desc *ext, void *ext_val,
|
||||
char value)
|
||||
{
|
||||
@@ -7339,7 +7395,11 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
||||
__u32 log_level = prog->log_level;
|
||||
int ret, err;
|
||||
|
||||
if (prog->type == BPF_PROG_TYPE_UNSPEC) {
|
||||
/* Be more helpful by rejecting programs that can't be validated early
|
||||
* with more meaningful and actionable error message.
|
||||
*/
|
||||
switch (prog->type) {
|
||||
case BPF_PROG_TYPE_UNSPEC:
|
||||
/*
|
||||
* The program type must be set. Most likely we couldn't find a proper
|
||||
* section definition at load time, and thus we didn't infer the type.
|
||||
@@ -7347,6 +7407,15 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
||||
pr_warn("prog '%s': missing BPF prog type, check ELF section name '%s'\n",
|
||||
prog->name, prog->sec_name);
|
||||
return -EINVAL;
|
||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||
if (prog->attach_btf_id == 0) {
|
||||
pr_warn("prog '%s': SEC(\"struct_ops\") program isn't referenced anywhere, did you forget to use it?\n",
|
||||
prog->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!insns || !insns_cnt)
|
||||
@@ -7986,7 +8055,10 @@ static int bpf_object__sanitize_maps(struct bpf_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *ctx)
|
||||
typedef int (*kallsyms_cb_t)(unsigned long long sym_addr, char sym_type,
|
||||
const char *sym_name, void *ctx);
|
||||
|
||||
static int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *ctx)
|
||||
{
|
||||
char sym_type, sym_name[500];
|
||||
unsigned long long sym_addr;
|
||||
@@ -8026,8 +8098,13 @@ static int kallsyms_cb(unsigned long long sym_addr, char sym_type,
|
||||
struct bpf_object *obj = ctx;
|
||||
const struct btf_type *t;
|
||||
struct extern_desc *ext;
|
||||
char *res;
|
||||
|
||||
ext = find_extern_by_name(obj, sym_name);
|
||||
res = strstr(sym_name, ".llvm.");
|
||||
if (sym_type == 'd' && res)
|
||||
ext = find_extern_by_name_with_len(obj, sym_name, res - sym_name);
|
||||
else
|
||||
ext = find_extern_by_name(obj, sym_name);
|
||||
if (!ext || ext->type != EXT_KSYM)
|
||||
return 0;
|
||||
|
||||
@@ -9249,6 +9326,7 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin
|
||||
static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_kprobe_session(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
|
||||
@@ -9265,6 +9343,7 @@ static const struct bpf_sec_def section_defs[] = {
|
||||
SEC_DEF("uretprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
|
||||
SEC_DEF("kprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
|
||||
SEC_DEF("kretprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
|
||||
SEC_DEF("kprobe.session+", KPROBE, BPF_TRACE_KPROBE_SESSION, SEC_NONE, attach_kprobe_session),
|
||||
SEC_DEF("uprobe.multi+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
|
||||
SEC_DEF("uretprobe.multi+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
|
||||
SEC_DEF("uprobe.multi.s+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
|
||||
@@ -9835,16 +9914,28 @@ static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
|
||||
enum bpf_attach_type attach_type,
|
||||
int *btf_obj_fd, int *btf_type_id)
|
||||
{
|
||||
int ret, i;
|
||||
int ret, i, mod_len;
|
||||
const char *fn_name, *mod_name = NULL;
|
||||
|
||||
ret = find_attach_btf_id(obj->btf_vmlinux, attach_name, attach_type);
|
||||
if (ret > 0) {
|
||||
*btf_obj_fd = 0; /* vmlinux BTF */
|
||||
*btf_type_id = ret;
|
||||
return 0;
|
||||
fn_name = strchr(attach_name, ':');
|
||||
if (fn_name) {
|
||||
mod_name = attach_name;
|
||||
mod_len = fn_name - mod_name;
|
||||
fn_name++;
|
||||
}
|
||||
|
||||
if (!mod_name || strncmp(mod_name, "vmlinux", mod_len) == 0) {
|
||||
ret = find_attach_btf_id(obj->btf_vmlinux,
|
||||
mod_name ? fn_name : attach_name,
|
||||
attach_type);
|
||||
if (ret > 0) {
|
||||
*btf_obj_fd = 0; /* vmlinux BTF */
|
||||
*btf_type_id = ret;
|
||||
return 0;
|
||||
}
|
||||
if (ret != -ENOENT)
|
||||
return ret;
|
||||
}
|
||||
if (ret != -ENOENT)
|
||||
return ret;
|
||||
|
||||
ret = load_module_btfs(obj);
|
||||
if (ret)
|
||||
@@ -9853,7 +9944,12 @@ static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
|
||||
for (i = 0; i < obj->btf_module_cnt; i++) {
|
||||
const struct module_btf *mod = &obj->btf_modules[i];
|
||||
|
||||
ret = find_attach_btf_id(mod->btf, attach_name, attach_type);
|
||||
if (mod_name && strncmp(mod->name, mod_name, mod_len) != 0)
|
||||
continue;
|
||||
|
||||
ret = find_attach_btf_id(mod->btf,
|
||||
mod_name ? fn_name : attach_name,
|
||||
attach_type);
|
||||
if (ret > 0) {
|
||||
*btf_obj_fd = mod->fd;
|
||||
*btf_type_id = ret;
|
||||
@@ -11357,13 +11453,14 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
struct kprobe_multi_resolve res = {
|
||||
.pattern = pattern,
|
||||
};
|
||||
enum bpf_attach_type attach_type;
|
||||
struct bpf_link *link = NULL;
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
const unsigned long *addrs;
|
||||
int err, link_fd, prog_fd;
|
||||
bool retprobe, session;
|
||||
const __u64 *cookies;
|
||||
const char **syms;
|
||||
bool retprobe;
|
||||
size_t cnt;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))
|
||||
@@ -11402,6 +11499,12 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
}
|
||||
|
||||
retprobe = OPTS_GET(opts, retprobe, false);
|
||||
session = OPTS_GET(opts, session, false);
|
||||
|
||||
if (retprobe && session)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
attach_type = session ? BPF_TRACE_KPROBE_SESSION : BPF_TRACE_KPROBE_MULTI;
|
||||
|
||||
lopts.kprobe_multi.syms = syms;
|
||||
lopts.kprobe_multi.addrs = addrs;
|
||||
@@ -11416,7 +11519,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
}
|
||||
link->detach = &bpf_link__detach_fd;
|
||||
|
||||
link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts);
|
||||
link_fd = bpf_link_create(prog_fd, 0, attach_type, &lopts);
|
||||
if (link_fd < 0) {
|
||||
err = -errno;
|
||||
pr_warn("prog '%s': failed to attach: %s\n",
|
||||
@@ -11513,7 +11616,7 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
|
||||
|
||||
n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
|
||||
if (n < 1) {
|
||||
pr_warn("kprobe multi pattern is invalid: %s\n", pattern);
|
||||
pr_warn("kprobe multi pattern is invalid: %s\n", spec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -11522,6 +11625,32 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
|
||||
return libbpf_get_error(*link);
|
||||
}
|
||||
|
||||
static int attach_kprobe_session(const struct bpf_program *prog, long cookie,
|
||||
struct bpf_link **link)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts, .session = true);
|
||||
const char *spec;
|
||||
char *pattern;
|
||||
int n;
|
||||
|
||||
*link = NULL;
|
||||
|
||||
/* no auto-attach for SEC("kprobe.session") */
|
||||
if (strcmp(prog->sec_name, "kprobe.session") == 0)
|
||||
return 0;
|
||||
|
||||
spec = prog->sec_name + sizeof("kprobe.session/") - 1;
|
||||
n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
|
||||
if (n < 1) {
|
||||
pr_warn("kprobe session pattern is invalid: %s\n", spec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*link = bpf_program__attach_kprobe_multi_opts(prog, pattern, &opts);
|
||||
free(pattern);
|
||||
return *link ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link)
|
||||
{
|
||||
char *probe_type = NULL, *binary_path = NULL, *func_name = NULL;
|
||||
@@ -12511,6 +12640,12 @@ bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd)
|
||||
return bpf_program_attach_fd(prog, netns_fd, "netns", NULL);
|
||||
}
|
||||
|
||||
struct bpf_link *
|
||||
bpf_program__attach_sockmap(const struct bpf_program *prog, int map_fd)
|
||||
{
|
||||
return bpf_program_attach_fd(prog, map_fd, "sockmap", NULL);
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex)
|
||||
{
|
||||
/* target_fd/target_ifindex use the same field in LINK_CREATE */
|
||||
|
||||
23
src/libbpf.h
23
src/libbpf.h
@@ -98,7 +98,10 @@ typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
|
||||
|
||||
/**
|
||||
* @brief **libbpf_set_print()** sets user-provided log callback function to
|
||||
* be used for libbpf warnings and informational messages.
|
||||
* be used for libbpf warnings and informational messages. If the user callback
|
||||
* is not set, messages are logged to stderr by default. The verbosity of these
|
||||
* messages can be controlled by setting the environment variable
|
||||
* LIBBPF_LOG_LEVEL to either warn, info, or debug.
|
||||
* @param fn The log print function. If NULL, libbpf won't print anything.
|
||||
* @return Pointer to old print function.
|
||||
*
|
||||
@@ -539,10 +542,12 @@ struct bpf_kprobe_multi_opts {
|
||||
size_t cnt;
|
||||
/* create return kprobes */
|
||||
bool retprobe;
|
||||
/* create session kprobes */
|
||||
bool session;
|
||||
size_t :0;
|
||||
};
|
||||
|
||||
#define bpf_kprobe_multi_opts__last_field retprobe
|
||||
#define bpf_kprobe_multi_opts__last_field session
|
||||
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
@@ -795,6 +800,8 @@ bpf_program__attach_cgroup(const struct bpf_program *prog, int cgroup_fd);
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd);
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_sockmap(const struct bpf_program *prog, int map_fd);
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex);
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_freplace(const struct bpf_program *prog,
|
||||
@@ -1293,6 +1300,7 @@ LIBBPF_API int ring_buffer__add(struct ring_buffer *rb, int map_fd,
|
||||
ring_buffer_sample_fn sample_cb, void *ctx);
|
||||
LIBBPF_API int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms);
|
||||
LIBBPF_API int ring_buffer__consume(struct ring_buffer *rb);
|
||||
LIBBPF_API int ring_buffer__consume_n(struct ring_buffer *rb, size_t n);
|
||||
LIBBPF_API int ring_buffer__epoll_fd(const struct ring_buffer *rb);
|
||||
|
||||
/**
|
||||
@@ -1367,6 +1375,17 @@ LIBBPF_API int ring__map_fd(const struct ring *r);
|
||||
*/
|
||||
LIBBPF_API int ring__consume(struct ring *r);
|
||||
|
||||
/**
|
||||
* @brief **ring__consume_n()** consumes up to a requested amount of items from
|
||||
* a ringbuffer without event polling.
|
||||
*
|
||||
* @param r A ringbuffer object.
|
||||
* @param n Maximum amount of items to consume.
|
||||
* @return The number of items consumed, or a negative number if any of the
|
||||
* callbacks return an error.
|
||||
*/
|
||||
LIBBPF_API int ring__consume_n(struct ring *r, size_t n);
|
||||
|
||||
struct user_ring_buffer_opts {
|
||||
size_t sz; /* size of this struct, for forward/backward compatibility */
|
||||
};
|
||||
|
||||
@@ -416,3 +416,10 @@ LIBBPF_1.4.0 {
|
||||
btf__new_split;
|
||||
btf_ext__raw_data;
|
||||
} LIBBPF_1.3.0;
|
||||
|
||||
LIBBPF_1.5.0 {
|
||||
global:
|
||||
bpf_program__attach_sockmap;
|
||||
ring__consume_n;
|
||||
ring_buffer__consume_n;
|
||||
} LIBBPF_1.4.0;
|
||||
|
||||
@@ -518,11 +518,6 @@ int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void
|
||||
__s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
|
||||
__u32 kind);
|
||||
|
||||
typedef int (*kallsyms_cb_t)(unsigned long long sym_addr, char sym_type,
|
||||
const char *sym_name, void *ctx);
|
||||
|
||||
int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *arg);
|
||||
|
||||
/* handle direct returned errors */
|
||||
static inline int libbpf_err(int ret)
|
||||
{
|
||||
@@ -602,13 +597,9 @@ static inline int ensure_good_fd(int fd)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static inline int sys_dup2(int oldfd, int newfd)
|
||||
static inline int sys_dup3(int oldfd, int newfd, int flags)
|
||||
{
|
||||
#ifdef __NR_dup2
|
||||
return syscall(__NR_dup2, oldfd, newfd);
|
||||
#else
|
||||
return syscall(__NR_dup3, oldfd, newfd, 0);
|
||||
#endif
|
||||
return syscall(__NR_dup3, oldfd, newfd, flags);
|
||||
}
|
||||
|
||||
/* Point *fixed_fd* to the same file that *tmp_fd* points to.
|
||||
@@ -619,7 +610,7 @@ static inline int reuse_fd(int fixed_fd, int tmp_fd)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = sys_dup2(tmp_fd, fixed_fd);
|
||||
err = sys_dup3(tmp_fd, fixed_fd, O_CLOEXEC);
|
||||
err = err < 0 ? -errno : 0;
|
||||
close(tmp_fd); /* clean up temporary FD */
|
||||
return err;
|
||||
|
||||
@@ -448,7 +448,8 @@ int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helpe
|
||||
/* If BPF verifier doesn't recognize BPF helper ID (enum bpf_func_id)
|
||||
* at all, it will emit something like "invalid func unknown#181".
|
||||
* If BPF verifier recognizes BPF helper but it's not supported for
|
||||
* given BPF program type, it will emit "unknown func bpf_sys_bpf#166".
|
||||
* given BPF program type, it will emit "unknown func bpf_sys_bpf#166"
|
||||
* or "program of this type cannot use helper bpf_sys_bpf#166".
|
||||
* In both cases, provided combination of BPF program type and BPF
|
||||
* helper is not supported by the kernel.
|
||||
* In all other cases, probe_prog_load() above will either succeed (e.g.,
|
||||
@@ -457,7 +458,8 @@ int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helpe
|
||||
* that), or we'll get some more specific BPF verifier error about
|
||||
* some unsatisfied conditions.
|
||||
*/
|
||||
if (ret == 0 && (strstr(buf, "invalid func ") || strstr(buf, "unknown func ")))
|
||||
if (ret == 0 && (strstr(buf, "invalid func ") || strstr(buf, "unknown func ") ||
|
||||
strstr(buf, "program of this type cannot use helper ")))
|
||||
return 0;
|
||||
return 1; /* assume supported */
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#define __LIBBPF_VERSION_H
|
||||
|
||||
#define LIBBPF_MAJOR_VERSION 1
|
||||
#define LIBBPF_MINOR_VERSION 4
|
||||
#define LIBBPF_MINOR_VERSION 5
|
||||
|
||||
#endif /* __LIBBPF_VERSION_H */
|
||||
|
||||
@@ -231,7 +231,7 @@ static inline int roundup_len(__u32 len)
|
||||
return (len + 7) / 8 * 8;
|
||||
}
|
||||
|
||||
static int64_t ringbuf_process_ring(struct ring *r)
|
||||
static int64_t ringbuf_process_ring(struct ring *r, size_t n)
|
||||
{
|
||||
int *len_ptr, len, err;
|
||||
/* 64-bit to avoid overflow in case of extreme application behavior */
|
||||
@@ -268,12 +268,42 @@ static int64_t ringbuf_process_ring(struct ring *r)
|
||||
}
|
||||
|
||||
smp_store_release(r->consumer_pos, cons_pos);
|
||||
|
||||
if (cnt >= n)
|
||||
goto done;
|
||||
}
|
||||
} while (got_new_data);
|
||||
done:
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Consume available ring buffer(s) data without event polling, up to n
|
||||
* records.
|
||||
*
|
||||
* Returns number of records consumed across all registered ring buffers (or
|
||||
* n, whichever is less), or negative number if any of the callbacks return
|
||||
* error.
|
||||
*/
|
||||
int ring_buffer__consume_n(struct ring_buffer *rb, size_t n)
|
||||
{
|
||||
int64_t err, res = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rb->ring_cnt; i++) {
|
||||
struct ring *ring = rb->rings[i];
|
||||
|
||||
err = ringbuf_process_ring(ring, n);
|
||||
if (err < 0)
|
||||
return libbpf_err(err);
|
||||
res += err;
|
||||
n -= err;
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
}
|
||||
return res > INT_MAX ? INT_MAX : res;
|
||||
}
|
||||
|
||||
/* Consume available ring buffer(s) data without event polling.
|
||||
* Returns number of records consumed across all registered ring buffers (or
|
||||
* INT_MAX, whichever is less), or negative number if any of the callbacks
|
||||
@@ -287,13 +317,15 @@ int ring_buffer__consume(struct ring_buffer *rb)
|
||||
for (i = 0; i < rb->ring_cnt; i++) {
|
||||
struct ring *ring = rb->rings[i];
|
||||
|
||||
err = ringbuf_process_ring(ring);
|
||||
err = ringbuf_process_ring(ring, INT_MAX);
|
||||
if (err < 0)
|
||||
return libbpf_err(err);
|
||||
res += err;
|
||||
if (res > INT_MAX) {
|
||||
res = INT_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (res > INT_MAX)
|
||||
return INT_MAX;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -314,13 +346,13 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
|
||||
__u32 ring_id = rb->events[i].data.fd;
|
||||
struct ring *ring = rb->rings[ring_id];
|
||||
|
||||
err = ringbuf_process_ring(ring);
|
||||
err = ringbuf_process_ring(ring, INT_MAX);
|
||||
if (err < 0)
|
||||
return libbpf_err(err);
|
||||
res += err;
|
||||
}
|
||||
if (res > INT_MAX)
|
||||
return INT_MAX;
|
||||
res = INT_MAX;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -371,17 +403,22 @@ int ring__map_fd(const struct ring *r)
|
||||
return r->map_fd;
|
||||
}
|
||||
|
||||
int ring__consume(struct ring *r)
|
||||
int ring__consume_n(struct ring *r, size_t n)
|
||||
{
|
||||
int64_t res;
|
||||
|
||||
res = ringbuf_process_ring(r);
|
||||
res = ringbuf_process_ring(r, n);
|
||||
if (res < 0)
|
||||
return libbpf_err(res);
|
||||
|
||||
return res > INT_MAX ? INT_MAX : res;
|
||||
}
|
||||
|
||||
int ring__consume(struct ring *r)
|
||||
{
|
||||
return ring__consume_n(r, INT_MAX);
|
||||
}
|
||||
|
||||
static void user_ringbuf_unmap_ring(struct user_ring_buffer *rb)
|
||||
{
|
||||
if (rb->consumer_pos) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#undef _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "str_error.h"
|
||||
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
@@ -15,7 +16,18 @@
|
||||
char *libbpf_strerror_r(int err, char *dst, int len)
|
||||
{
|
||||
int ret = strerror_r(err < 0 ? -err : err, dst, len);
|
||||
if (ret)
|
||||
snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret);
|
||||
/* on glibc <2.13, ret == -1 and errno is set, if strerror_r() can't
|
||||
* handle the error, on glibc >=2.13 *positive* (errno-like) error
|
||||
* code is returned directly
|
||||
*/
|
||||
if (ret == -1)
|
||||
ret = errno;
|
||||
if (ret) {
|
||||
if (ret == EINVAL)
|
||||
/* strerror_r() doesn't recognize this specific error */
|
||||
snprintf(dst, len, "unknown error (%d)", err < 0 ? err : -err);
|
||||
else
|
||||
snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -214,18 +214,18 @@ long bpf_usdt_cookie(struct pt_regs *ctx)
|
||||
|
||||
/* we rely on ___bpf_apply() and ___bpf_narg() macros already defined in bpf_tracing.h */
|
||||
#define ___bpf_usdt_args0() ctx
|
||||
#define ___bpf_usdt_args1(x) ___bpf_usdt_args0(), ({ long _x; bpf_usdt_arg(ctx, 0, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args2(x, args...) ___bpf_usdt_args1(args), ({ long _x; bpf_usdt_arg(ctx, 1, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args3(x, args...) ___bpf_usdt_args2(args), ({ long _x; bpf_usdt_arg(ctx, 2, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args4(x, args...) ___bpf_usdt_args3(args), ({ long _x; bpf_usdt_arg(ctx, 3, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args5(x, args...) ___bpf_usdt_args4(args), ({ long _x; bpf_usdt_arg(ctx, 4, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args6(x, args...) ___bpf_usdt_args5(args), ({ long _x; bpf_usdt_arg(ctx, 5, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args7(x, args...) ___bpf_usdt_args6(args), ({ long _x; bpf_usdt_arg(ctx, 6, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args8(x, args...) ___bpf_usdt_args7(args), ({ long _x; bpf_usdt_arg(ctx, 7, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args9(x, args...) ___bpf_usdt_args8(args), ({ long _x; bpf_usdt_arg(ctx, 8, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args10(x, args...) ___bpf_usdt_args9(args), ({ long _x; bpf_usdt_arg(ctx, 9, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args11(x, args...) ___bpf_usdt_args10(args), ({ long _x; bpf_usdt_arg(ctx, 10, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args12(x, args...) ___bpf_usdt_args11(args), ({ long _x; bpf_usdt_arg(ctx, 11, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args1(x) ___bpf_usdt_args0(), ({ long _x; bpf_usdt_arg(ctx, 0, &_x); _x; })
|
||||
#define ___bpf_usdt_args2(x, args...) ___bpf_usdt_args1(args), ({ long _x; bpf_usdt_arg(ctx, 1, &_x); _x; })
|
||||
#define ___bpf_usdt_args3(x, args...) ___bpf_usdt_args2(args), ({ long _x; bpf_usdt_arg(ctx, 2, &_x); _x; })
|
||||
#define ___bpf_usdt_args4(x, args...) ___bpf_usdt_args3(args), ({ long _x; bpf_usdt_arg(ctx, 3, &_x); _x; })
|
||||
#define ___bpf_usdt_args5(x, args...) ___bpf_usdt_args4(args), ({ long _x; bpf_usdt_arg(ctx, 4, &_x); _x; })
|
||||
#define ___bpf_usdt_args6(x, args...) ___bpf_usdt_args5(args), ({ long _x; bpf_usdt_arg(ctx, 5, &_x); _x; })
|
||||
#define ___bpf_usdt_args7(x, args...) ___bpf_usdt_args6(args), ({ long _x; bpf_usdt_arg(ctx, 6, &_x); _x; })
|
||||
#define ___bpf_usdt_args8(x, args...) ___bpf_usdt_args7(args), ({ long _x; bpf_usdt_arg(ctx, 7, &_x); _x; })
|
||||
#define ___bpf_usdt_args9(x, args...) ___bpf_usdt_args8(args), ({ long _x; bpf_usdt_arg(ctx, 8, &_x); _x; })
|
||||
#define ___bpf_usdt_args10(x, args...) ___bpf_usdt_args9(args), ({ long _x; bpf_usdt_arg(ctx, 9, &_x); _x; })
|
||||
#define ___bpf_usdt_args11(x, args...) ___bpf_usdt_args10(args), ({ long _x; bpf_usdt_arg(ctx, 10, &_x); _x; })
|
||||
#define ___bpf_usdt_args12(x, args...) ___bpf_usdt_args11(args), ({ long _x; bpf_usdt_arg(ctx, 11, &_x); _x; })
|
||||
#define ___bpf_usdt_args(args...) ___bpf_apply(___bpf_usdt_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user