mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says:
====================
pull-request: bpf-next 2023-10-16
We've added 90 non-merge commits during the last 25 day(s) which contain
a total of 120 files changed, 3519 insertions(+), 895 deletions(-).
The main changes are:
1) Add missed stats for kprobes to retrieve the number of missed kprobe
executions and subsequent executions of BPF programs, from Jiri Olsa.
2) Add cgroup BPF sockaddr hooks for unix sockets. The use case is
for systemd to reimplement the LogNamespace feature which allows
running multiple instances of systemd-journald to process the logs
of different services, from Daan De Meyer.
3) Implement BPF CPUv4 support for s390x BPF JIT, from Ilya Leoshkevich.
4) Improve BPF verifier log output for scalar registers to better
disambiguate their internal state wrt defaults vs min/max values
matching, from Andrii Nakryiko.
5) Extend the BPF fib lookup helpers for IPv4/IPv6 to support retrieving
the source IP address with a new BPF_FIB_LOOKUP_SRC flag,
from Martynas Pumputis.
6) Add support for open-coded task_vma iterator to help with symbolization
for BPF-collected user stacks, from Dave Marchevsky.
7) Add libbpf getters for accessing individual BPF ring buffers which
is useful for polling them individually, for example, from Martin Kelly.
8) Extend AF_XDP selftests to validate the SHARED_UMEM feature,
from Tushar Vyavahare.
9) Improve BPF selftests cross-building support for riscv arch,
from Björn Töpel.
10) Add the ability to pin a BPF timer to the same calling CPU,
from David Vernet.
11) Fix libbpf's bpf_tracing.h macros for riscv to use the generic
implementation of PT_REGS_SYSCALL_REGS() to access syscall arguments,
from Alexandre Ghiti.
12) Extend libbpf to support symbol versioning for uprobes, from Hengqi Chen.
13) Fix bpftool's skeleton code generation to guarantee that ELF data
is 8 byte aligned, from Ian Rogers.
14) Inherit system-wide cpu_mitigations_off() setting for Spectre v1/v4
security mitigations in BPF verifier, from Yafang Shao.
15) Annotate struct bpf_stack_map with __counted_by attribute to prepare
BPF side for upcoming __counted_by compiler support, from Kees Cook.
* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (90 commits)
bpf: Ensure proper register state printing for cond jumps
bpf: Disambiguate SCALAR register state output in verifier logs
selftests/bpf: Make align selftests more robust
selftests/bpf: Improve missed_kprobe_recursion test robustness
selftests/bpf: Improve percpu_alloc test robustness
selftests/bpf: Add tests for open-coded task_vma iter
bpf: Introduce task_vma open-coded iterator kfuncs
selftests/bpf: Rename bpf_iter_task_vma.c to bpf_iter_task_vmas.c
bpf: Don't explicitly emit BTF for struct btf_iter_num
bpf: Change syscall_nr type to int in struct syscall_tp_t
net/bpf: Avoid unused "sin_addr_len" warning when CONFIG_CGROUP_BPF is not set
bpf: Avoid unnecessary audit log for CPU security mitigations
selftests/bpf: Add tests for cgroup unix socket address hooks
selftests/bpf: Make sure mount directory exists
documentation/bpf: Document cgroup unix socket address hooks
bpftool: Add support for cgroup unix socket address hooks
libbpf: Add support for cgroup unix socket address hooks
bpf: Implement cgroup sockaddr hooks for unix sockets
bpf: Add bpf_sock_addr_set_sun_path() to allow writing unix sockaddr from bpf
bpf: Propagate modified uaddrlen from cgroup sockaddr programs
...
====================
Link: https://lore.kernel.org/r/20231016204803.30153-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -71,6 +71,7 @@ two flavors of JITs, the newer eBPF JIT currently supported on:
|
||||
- s390x
|
||||
- riscv64
|
||||
- riscv32
|
||||
- loongarch64
|
||||
|
||||
And the older cBPF JIT supported on the following archs:
|
||||
|
||||
|
||||
@@ -56,6 +56,16 @@ described in more detail in the footnotes.
|
||||
| | ``BPF_CGROUP_UDP6_RECVMSG`` | ``cgroup/recvmsg6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP6_SENDMSG`` | ``cgroup/sendmsg6`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_CONNECT`` | ``cgroup/connect_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_SENDMSG`` | ``cgroup/sendmsg_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_RECVMSG`` | ``cgroup/recvmsg_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_GETPEERNAME`` | ``cgroup/getpeername_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_GETSOCKNAME`` | ``cgroup/getsockname_unix`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SOCK`` | ``BPF_CGROUP_INET4_POST_BIND`` | ``cgroup/post_bind4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
|
||||
@@ -650,8 +650,8 @@ before a conversion to the new layout is being done behind the scenes!
|
||||
|
||||
Currently, the classic BPF format is being used for JITing on most
|
||||
32-bit architectures, whereas x86-64, aarch64, s390x, powerpc64,
|
||||
sparc64, arm32, riscv64, riscv32 perform JIT compilation from eBPF
|
||||
instruction set.
|
||||
sparc64, arm32, riscv64, riscv32, loongarch64 perform JIT compilation
|
||||
from eBPF instruction set.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
+202
-63
@@ -670,15 +670,18 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
|
||||
static int get_probe_mem_regno(const u8 *insn)
|
||||
{
|
||||
/*
|
||||
* insn must point to llgc, llgh, llgf or lg, which have destination
|
||||
* register at the same position.
|
||||
* insn must point to llgc, llgh, llgf, lg, lgb, lgh or lgf, which have
|
||||
* destination register at the same position.
|
||||
*/
|
||||
if (insn[0] != 0xe3) /* common llgc, llgh, llgf and lg prefix */
|
||||
if (insn[0] != 0xe3) /* common prefix */
|
||||
return -1;
|
||||
if (insn[5] != 0x90 && /* llgc */
|
||||
insn[5] != 0x91 && /* llgh */
|
||||
insn[5] != 0x16 && /* llgf */
|
||||
insn[5] != 0x04) /* lg */
|
||||
insn[5] != 0x04 && /* lg */
|
||||
insn[5] != 0x77 && /* lgb */
|
||||
insn[5] != 0x15 && /* lgh */
|
||||
insn[5] != 0x14) /* lgf */
|
||||
return -1;
|
||||
return insn[1] >> 4;
|
||||
}
|
||||
@@ -776,6 +779,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
int i, bool extra_pass, u32 stack_depth)
|
||||
{
|
||||
struct bpf_insn *insn = &fp->insnsi[i];
|
||||
s16 branch_oc_off = insn->off;
|
||||
u32 dst_reg = insn->dst_reg;
|
||||
u32 src_reg = insn->src_reg;
|
||||
int last, insn_count = 1;
|
||||
@@ -788,22 +792,55 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
int err;
|
||||
|
||||
if (BPF_CLASS(insn->code) == BPF_LDX &&
|
||||
BPF_MODE(insn->code) == BPF_PROBE_MEM)
|
||||
(BPF_MODE(insn->code) == BPF_PROBE_MEM ||
|
||||
BPF_MODE(insn->code) == BPF_PROBE_MEMSX))
|
||||
probe_prg = jit->prg;
|
||||
|
||||
switch (insn->code) {
|
||||
/*
|
||||
* BPF_MOV
|
||||
*/
|
||||
case BPF_ALU | BPF_MOV | BPF_X: /* dst = (u32) src */
|
||||
/* llgfr %dst,%src */
|
||||
EMIT4(0xb9160000, dst_reg, src_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
case BPF_ALU | BPF_MOV | BPF_X:
|
||||
switch (insn->off) {
|
||||
case 0: /* DST = (u32) SRC */
|
||||
/* llgfr %dst,%src */
|
||||
EMIT4(0xb9160000, dst_reg, src_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case 8: /* DST = (u32)(s8) SRC */
|
||||
/* lbr %dst,%src */
|
||||
EMIT4(0xb9260000, dst_reg, src_reg);
|
||||
/* llgfr %dst,%dst */
|
||||
EMIT4(0xb9160000, dst_reg, dst_reg);
|
||||
break;
|
||||
case 16: /* DST = (u32)(s16) SRC */
|
||||
/* lhr %dst,%src */
|
||||
EMIT4(0xb9270000, dst_reg, src_reg);
|
||||
/* llgfr %dst,%dst */
|
||||
EMIT4(0xb9160000, dst_reg, dst_reg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
|
||||
/* lgr %dst,%src */
|
||||
EMIT4(0xb9040000, dst_reg, src_reg);
|
||||
case BPF_ALU64 | BPF_MOV | BPF_X:
|
||||
switch (insn->off) {
|
||||
case 0: /* DST = SRC */
|
||||
/* lgr %dst,%src */
|
||||
EMIT4(0xb9040000, dst_reg, src_reg);
|
||||
break;
|
||||
case 8: /* DST = (s8) SRC */
|
||||
/* lgbr %dst,%src */
|
||||
EMIT4(0xb9060000, dst_reg, src_reg);
|
||||
break;
|
||||
case 16: /* DST = (s16) SRC */
|
||||
/* lghr %dst,%src */
|
||||
EMIT4(0xb9070000, dst_reg, src_reg);
|
||||
break;
|
||||
case 32: /* DST = (s32) SRC */
|
||||
/* lgfr %dst,%src */
|
||||
EMIT4(0xb9140000, dst_reg, src_reg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */
|
||||
/* llilf %dst,imm */
|
||||
@@ -912,66 +949,115 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
/*
|
||||
* BPF_DIV / BPF_MOD
|
||||
*/
|
||||
case BPF_ALU | BPF_DIV | BPF_X: /* dst = (u32) dst / (u32) src */
|
||||
case BPF_ALU | BPF_MOD | BPF_X: /* dst = (u32) dst % (u32) src */
|
||||
case BPF_ALU | BPF_DIV | BPF_X:
|
||||
case BPF_ALU | BPF_MOD | BPF_X:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
/* lhi %w0,0 */
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dlr %w0,%src */
|
||||
EMIT4(0xb9970000, REG_W0, src_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) src */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dlr %w0,%src */
|
||||
EMIT4(0xb9970000, REG_W0, src_reg);
|
||||
break;
|
||||
case 1: /* dst = (u32) ((s32) dst {/,%} (s32) src) */
|
||||
/* lgfr %r1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* dsgfr %r0,%src */
|
||||
EMIT4(0xb91d0000, REG_W0, src_reg);
|
||||
break;
|
||||
}
|
||||
/* llgfr %dst,%rc */
|
||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
}
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % src */
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, src_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} src */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlgr %w0,%src */
|
||||
EMIT4(0xb9870000, REG_W0, src_reg);
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) src */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dsgr %w0,%src */
|
||||
EMIT4(0xb90d0000, REG_W0, src_reg);
|
||||
break;
|
||||
}
|
||||
/* lgr %dst,%rc */
|
||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||
break;
|
||||
}
|
||||
case BPF_ALU | BPF_DIV | BPF_K: /* dst = (u32) dst / (u32) imm */
|
||||
case BPF_ALU | BPF_MOD | BPF_K: /* dst = (u32) dst % (u32) imm */
|
||||
case BPF_ALU | BPF_DIV | BPF_K:
|
||||
case BPF_ALU | BPF_MOD | BPF_K:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
if (imm == 1) {
|
||||
if (BPF_OP(insn->code) == BPF_MOD)
|
||||
/* lhgi %dst,0 */
|
||||
/* lghi %dst,0 */
|
||||
EMIT4_IMM(0xa7090000, dst_reg, 0);
|
||||
else
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
}
|
||||
/* lhi %w0,0 */
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
if (!is_first_pass(jit) && can_use_ldisp_for_lit32(jit)) {
|
||||
/* dl %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0, REG_L,
|
||||
EMIT_CONST_U32(imm));
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) imm */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dl %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U32(imm));
|
||||
break;
|
||||
case 1: /* dst = (s32) dst {/,%} (s32) imm */
|
||||
/* lgfr %r1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* dsgf %r0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x001d, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U32(imm));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* lgfrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlr %w0,%dst */
|
||||
EMIT4(0xb9970000, REG_W0, dst_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) imm */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* lrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40d0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlr %w0,%dst */
|
||||
EMIT4(0xb9970000, REG_W0, dst_reg);
|
||||
break;
|
||||
case 1: /* dst = (s32) dst {/,%} (s32) imm */
|
||||
/* lgfr %w1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* lgfrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dsgr %w0,%dst */
|
||||
EMIT4(0xb90d0000, REG_W0, dst_reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* llgfr %dst,%rc */
|
||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||
@@ -979,8 +1065,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
insn_count = 2;
|
||||
break;
|
||||
}
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % imm */
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K:
|
||||
case BPF_ALU64 | BPF_MOD | BPF_K:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
@@ -990,21 +1076,50 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4_IMM(0xa7090000, dst_reg, 0);
|
||||
break;
|
||||
}
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) {
|
||||
/* dlg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L,
|
||||
EMIT_CONST_U64(imm));
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} imm */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U64(imm));
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) imm */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dsg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x000d, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U64(imm));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, dst_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} imm */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, dst_reg);
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) imm */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dsgr %w0,%dst */
|
||||
EMIT4(0xb90d0000, REG_W0, dst_reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* lgr %dst,%rc */
|
||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||
@@ -1217,6 +1332,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
}
|
||||
break;
|
||||
case BPF_ALU | BPF_END | BPF_FROM_LE:
|
||||
case BPF_ALU64 | BPF_END | BPF_FROM_LE:
|
||||
switch (imm) {
|
||||
case 16: /* dst = (u16) cpu_to_le16(dst) */
|
||||
/* lrvr %dst,%dst */
|
||||
@@ -1374,6 +1490,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_B: /* dst = *(s8 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
|
||||
/* lgb %dst,0(off,%src) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0077, dst_reg, src_reg, REG_0, off);
|
||||
jit->seen |= SEEN_MEM;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
|
||||
/* llgh %dst,0(off,%src) */
|
||||
@@ -1382,6 +1504,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_H: /* dst = *(s16 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
|
||||
/* lgh %dst,0(off,%src) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0015, dst_reg, src_reg, REG_0, off);
|
||||
jit->seen |= SEEN_MEM;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
|
||||
/* llgf %dst,off(%src) */
|
||||
@@ -1390,6 +1518,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_W: /* dst = *(s32 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
|
||||
/* lgf %dst,off(%src) */
|
||||
jit->seen |= SEEN_MEM;
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0014, dst_reg, src_reg, REG_0, off);
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
|
||||
/* lg %dst,0(off,%src) */
|
||||
@@ -1570,6 +1704,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
* instruction itself (loop) and for BPF with offset 0 we
|
||||
* branch to the instruction behind the branch.
|
||||
*/
|
||||
case BPF_JMP32 | BPF_JA: /* if (true) */
|
||||
branch_oc_off = imm;
|
||||
fallthrough;
|
||||
case BPF_JMP | BPF_JA: /* if (true) */
|
||||
mask = 0xf000; /* j */
|
||||
goto branch_oc;
|
||||
@@ -1738,14 +1875,16 @@ branch_xu:
|
||||
break;
|
||||
branch_oc:
|
||||
if (!is_first_pass(jit) &&
|
||||
can_use_rel(jit, addrs[i + off + 1])) {
|
||||
can_use_rel(jit, addrs[i + branch_oc_off + 1])) {
|
||||
/* brc mask,off */
|
||||
EMIT4_PCREL_RIC(0xa7040000,
|
||||
mask >> 12, addrs[i + off + 1]);
|
||||
mask >> 12,
|
||||
addrs[i + branch_oc_off + 1]);
|
||||
} else {
|
||||
/* brcl mask,off */
|
||||
EMIT6_PCREL_RILC(0xc0040000,
|
||||
mask >> 12, addrs[i + off + 1]);
|
||||
mask >> 12,
|
||||
addrs[i + branch_oc_off + 1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -28,19 +28,24 @@ enum cgroup_bpf_attach_type {
|
||||
CGROUP_INET6_BIND,
|
||||
CGROUP_INET4_CONNECT,
|
||||
CGROUP_INET6_CONNECT,
|
||||
CGROUP_UNIX_CONNECT,
|
||||
CGROUP_INET4_POST_BIND,
|
||||
CGROUP_INET6_POST_BIND,
|
||||
CGROUP_UDP4_SENDMSG,
|
||||
CGROUP_UDP6_SENDMSG,
|
||||
CGROUP_UNIX_SENDMSG,
|
||||
CGROUP_SYSCTL,
|
||||
CGROUP_UDP4_RECVMSG,
|
||||
CGROUP_UDP6_RECVMSG,
|
||||
CGROUP_UNIX_RECVMSG,
|
||||
CGROUP_GETSOCKOPT,
|
||||
CGROUP_SETSOCKOPT,
|
||||
CGROUP_INET4_GETPEERNAME,
|
||||
CGROUP_INET6_GETPEERNAME,
|
||||
CGROUP_UNIX_GETPEERNAME,
|
||||
CGROUP_INET4_GETSOCKNAME,
|
||||
CGROUP_INET6_GETSOCKNAME,
|
||||
CGROUP_UNIX_GETSOCKNAME,
|
||||
CGROUP_INET_SOCK_RELEASE,
|
||||
CGROUP_LSM_START,
|
||||
CGROUP_LSM_END = CGROUP_LSM_START + CGROUP_LSM_NUM - 1,
|
||||
|
||||
+54
-36
@@ -48,19 +48,24 @@ to_cgroup_bpf_attach_type(enum bpf_attach_type attach_type)
|
||||
CGROUP_ATYPE(CGROUP_INET6_BIND);
|
||||
CGROUP_ATYPE(CGROUP_INET4_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_INET6_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_INET4_POST_BIND);
|
||||
CGROUP_ATYPE(CGROUP_INET6_POST_BIND);
|
||||
CGROUP_ATYPE(CGROUP_UDP4_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_UDP6_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_SYSCTL);
|
||||
CGROUP_ATYPE(CGROUP_UDP4_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_UDP6_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_GETSOCKOPT);
|
||||
CGROUP_ATYPE(CGROUP_SETSOCKOPT);
|
||||
CGROUP_ATYPE(CGROUP_INET4_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET6_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET4_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET6_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET_SOCK_RELEASE);
|
||||
default:
|
||||
return CGROUP_BPF_ATTACH_TYPE_INVALID;
|
||||
@@ -120,6 +125,7 @@ int __cgroup_bpf_run_filter_sk(struct sock *sk,
|
||||
|
||||
int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
||||
struct sockaddr *uaddr,
|
||||
int *uaddrlen,
|
||||
enum cgroup_bpf_attach_type atype,
|
||||
void *t_ctx,
|
||||
u32 *flags);
|
||||
@@ -230,22 +236,22 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) \
|
||||
BPF_CGROUP_RUN_SK_PROG(sk, CGROUP_INET6_POST_BIND)
|
||||
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) \
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, atype) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
NULL, NULL); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, NULL, NULL); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) \
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, atype, t_ctx) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) { \
|
||||
lock_sock(sk); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
t_ctx, NULL); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, t_ctx, NULL); \
|
||||
release_sock(sk); \
|
||||
} \
|
||||
__ret; \
|
||||
@@ -256,14 +262,14 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
||||
* (at bit position 0) is to indicate CAP_NET_BIND_SERVICE capability check
|
||||
* should be bypassed (BPF_RET_BIND_NO_CAP_NET_BIND_SERVICE).
|
||||
*/
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, atype, bind_flags) \
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, uaddrlen, atype, bind_flags) \
|
||||
({ \
|
||||
u32 __flags = 0; \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) { \
|
||||
lock_sock(sk); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
NULL, &__flags); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, NULL, &__flags); \
|
||||
release_sock(sk); \
|
||||
if (__flags & BPF_RET_BIND_NO_CAP_NET_BIND_SERVICE) \
|
||||
*bind_flags |= BIND_NO_CAP_NET_BIND_SERVICE; \
|
||||
@@ -276,29 +282,38 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
||||
cgroup_bpf_enabled(CGROUP_INET6_CONNECT)) && \
|
||||
(sk)->sk_prot->pre_connect)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, CGROUP_INET4_CONNECT)
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, CGROUP_INET4_CONNECT)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, CGROUP_INET6_CONNECT)
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, CGROUP_INET6_CONNECT)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_INET4_CONNECT, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_INET4_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_INET6_CONNECT, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_INET6_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP4_SENDMSG, t_ctx)
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP6_SENDMSG, t_ctx)
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP4_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP4_RECVMSG, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP6_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP6_RECVMSG, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP4_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP6_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_RECVMSG, NULL)
|
||||
|
||||
/* The SOCK_OPS"_SK" macro should be used when sock_ops->sk is not a
|
||||
* fullsock and its parent fullsock cannot be traced by
|
||||
@@ -477,24 +492,27 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
|
||||
}
|
||||
|
||||
#define cgroup_bpf_enabled(atype) (0)
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, atype, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, atype) ({ 0; })
|
||||
#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0)
|
||||
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_SOCK_RELEASE(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, atype, flags) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, uaddrlen, atype, flags) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(atype, major, minor, access) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos) ({ 0; })
|
||||
|
||||
+18
-2
@@ -2164,12 +2164,12 @@ static inline bool bpf_allow_uninit_stack(void)
|
||||
|
||||
static inline bool bpf_bypass_spec_v1(void)
|
||||
{
|
||||
return perfmon_capable();
|
||||
return cpu_mitigations_off() || perfmon_capable();
|
||||
}
|
||||
|
||||
static inline bool bpf_bypass_spec_v4(void)
|
||||
{
|
||||
return perfmon_capable();
|
||||
return cpu_mitigations_off() || perfmon_capable();
|
||||
}
|
||||
|
||||
int bpf_map_new_fd(struct bpf_map *map, int flags);
|
||||
@@ -2922,6 +2922,22 @@ static inline int sock_map_bpf_prog_query(const union bpf_attr *attr,
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
|
||||
|
||||
static __always_inline void
|
||||
bpf_prog_inc_misses_counters(const struct bpf_prog_array *array)
|
||||
{
|
||||
const struct bpf_prog_array_item *item;
|
||||
struct bpf_prog *prog;
|
||||
|
||||
if (unlikely(!array))
|
||||
return;
|
||||
|
||||
item = &array->items[0];
|
||||
while ((prog = READ_ONCE(item->prog))) {
|
||||
bpf_prog_inc_misses_counter(prog);
|
||||
item++;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)
|
||||
void bpf_sk_reuseport_detach(struct sock *sk);
|
||||
int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key,
|
||||
|
||||
@@ -736,7 +736,7 @@ static inline void bpf_compute_and_save_data_end(
|
||||
cb->data_end = skb->data + skb_headlen(skb);
|
||||
}
|
||||
|
||||
/* Restore data saved by bpf_compute_data_pointers(). */
|
||||
/* Restore data saved by bpf_compute_and_save_data_end(). */
|
||||
static inline void bpf_restore_data_end(
|
||||
struct sk_buff *skb, void *saved_data_end)
|
||||
{
|
||||
@@ -1329,6 +1329,7 @@ struct bpf_sock_addr_kern {
|
||||
*/
|
||||
u64 tmp_reg;
|
||||
void *t_ctx; /* Attach type specific context. */
|
||||
u32 uaddrlen;
|
||||
};
|
||||
|
||||
struct bpf_sock_ops_kern {
|
||||
|
||||
@@ -761,7 +761,8 @@ struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);
|
||||
void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);
|
||||
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
||||
u32 *fd_type, const char **buf,
|
||||
u64 *probe_offset, u64 *probe_addr);
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed);
|
||||
int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
#else
|
||||
@@ -801,7 +802,7 @@ static inline void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
|
||||
static inline int bpf_get_perf_event_info(const struct perf_event *event,
|
||||
u32 *prog_id, u32 *fd_type,
|
||||
const char **buf, u64 *probe_offset,
|
||||
u64 *probe_addr)
|
||||
u64 *probe_addr, unsigned long *missed)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -877,6 +878,7 @@ extern void perf_kprobe_destroy(struct perf_event *event);
|
||||
extern int bpf_get_kprobe_info(const struct perf_event *event,
|
||||
u32 *fd_type, const char **symbol,
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed,
|
||||
bool perf_type_tracepoint);
|
||||
#endif
|
||||
#ifdef CONFIG_UPROBE_EVENTS
|
||||
|
||||
@@ -85,6 +85,11 @@ struct ipv6_bpf_stub {
|
||||
sockptr_t optval, unsigned int optlen);
|
||||
int (*ipv6_getsockopt)(struct sock *sk, int level, int optname,
|
||||
sockptr_t optval, sockptr_t optlen);
|
||||
int (*ipv6_dev_get_saddr)(struct net *net,
|
||||
const struct net_device *dst_dev,
|
||||
const struct in6_addr *daddr,
|
||||
unsigned int prefs,
|
||||
struct in6_addr *saddr);
|
||||
};
|
||||
extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly;
|
||||
|
||||
|
||||
@@ -1047,6 +1047,11 @@ enum bpf_attach_type {
|
||||
BPF_TCX_INGRESS,
|
||||
BPF_TCX_EGRESS,
|
||||
BPF_TRACE_UPROBE_MULTI,
|
||||
BPF_CGROUP_UNIX_CONNECT,
|
||||
BPF_CGROUP_UNIX_SENDMSG,
|
||||
BPF_CGROUP_UNIX_RECVMSG,
|
||||
BPF_CGROUP_UNIX_GETPEERNAME,
|
||||
BPF_CGROUP_UNIX_GETSOCKNAME,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
@@ -2704,8 +2709,8 @@ union bpf_attr {
|
||||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **setsockopt()**.
|
||||
* It supports the following *level*\ s:
|
||||
@@ -2943,8 +2948,8 @@ union bpf_attr {
|
||||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **getsockopt()**.
|
||||
* It supports the same set of *optname*\ s that is supported by
|
||||
@@ -3264,6 +3269,11 @@ union bpf_attr {
|
||||
* and *params*->smac will not be set as output. A common
|
||||
* use case is to call **bpf_redirect_neigh**\ () after
|
||||
* doing **bpf_fib_lookup**\ ().
|
||||
* **BPF_FIB_LOOKUP_SRC**
|
||||
* Derive and set source IP addr in *params*->ipv{4,6}_src
|
||||
* 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.
|
||||
*
|
||||
* *ctx* is either **struct xdp_md** for XDP programs or
|
||||
* **struct sk_buff** tc cls_act programs.
|
||||
@@ -5096,6 +5106,8 @@ union bpf_attr {
|
||||
* **BPF_F_TIMER_ABS**
|
||||
* Start the timer in absolute expire value instead of the
|
||||
* default relative one.
|
||||
* **BPF_F_TIMER_CPU_PIN**
|
||||
* Timer will be pinned to the CPU of the caller.
|
||||
*
|
||||
* Return
|
||||
* 0 on success.
|
||||
@@ -6532,6 +6544,7 @@ struct bpf_link_info {
|
||||
__aligned_u64 addrs;
|
||||
__u32 count; /* in/out: kprobe_multi function count */
|
||||
__u32 flags;
|
||||
__u64 missed;
|
||||
} kprobe_multi;
|
||||
struct {
|
||||
__u32 type; /* enum bpf_perf_event_type */
|
||||
@@ -6547,6 +6560,7 @@ struct bpf_link_info {
|
||||
__u32 name_len;
|
||||
__u32 offset; /* offset from func_name */
|
||||
__u64 addr;
|
||||
__u64 missed;
|
||||
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
|
||||
struct {
|
||||
__aligned_u64 tp_name; /* in/out */
|
||||
@@ -6960,6 +6974,7 @@ enum {
|
||||
BPF_FIB_LOOKUP_OUTPUT = (1U << 1),
|
||||
BPF_FIB_LOOKUP_SKIP_NEIGH = (1U << 2),
|
||||
BPF_FIB_LOOKUP_TBID = (1U << 3),
|
||||
BPF_FIB_LOOKUP_SRC = (1U << 4),
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -6972,6 +6987,7 @@ enum {
|
||||
BPF_FIB_LKUP_RET_UNSUPP_LWT, /* fwd requires encapsulation */
|
||||
BPF_FIB_LKUP_RET_NO_NEIGH, /* no neighbor entry for nh */
|
||||
BPF_FIB_LKUP_RET_FRAG_NEEDED, /* fragmentation required to fwd */
|
||||
BPF_FIB_LKUP_RET_NO_SRC_ADDR, /* failed to derive IP src addr */
|
||||
};
|
||||
|
||||
struct bpf_fib_lookup {
|
||||
@@ -7006,6 +7022,9 @@ struct bpf_fib_lookup {
|
||||
__u32 rt_metric;
|
||||
};
|
||||
|
||||
/* input: source address to consider for lookup
|
||||
* output: source address result from lookup
|
||||
*/
|
||||
union {
|
||||
__be32 ipv4_src;
|
||||
__u32 ipv6_src[4]; /* in6_addr; network order */
|
||||
@@ -7307,9 +7326,11 @@ struct bpf_core_relo {
|
||||
* Flags to control bpf_timer_start() behaviour.
|
||||
* - BPF_F_TIMER_ABS: Timeout passed is absolute time, by default it is
|
||||
* relative to current time.
|
||||
* - BPF_F_TIMER_CPU_PIN: Timer will be pinned to the CPU of the caller.
|
||||
*/
|
||||
enum {
|
||||
BPF_F_TIMER_ABS = (1ULL << 0),
|
||||
BPF_F_TIMER_CPU_PIN = (1ULL << 1),
|
||||
};
|
||||
|
||||
/* BPF numbers iterator state */
|
||||
|
||||
@@ -793,8 +793,6 @@ __bpf_kfunc int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end)
|
||||
BUILD_BUG_ON(sizeof(struct bpf_iter_num_kern) != sizeof(struct bpf_iter_num));
|
||||
BUILD_BUG_ON(__alignof__(struct bpf_iter_num_kern) != __alignof__(struct bpf_iter_num));
|
||||
|
||||
BTF_TYPE_EMIT(struct btf_iter_num);
|
||||
|
||||
/* start == end is legit, it's an empty range and we'll just get NULL
|
||||
* on first (and any subsequent) bpf_iter_num_next() call
|
||||
*/
|
||||
|
||||
@@ -7850,6 +7850,7 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
|
||||
case BPF_PROG_TYPE_SYSCALL:
|
||||
return BTF_KFUNC_HOOK_SYSCALL;
|
||||
case BPF_PROG_TYPE_CGROUP_SKB:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
return BTF_KFUNC_HOOK_CGROUP_SKB;
|
||||
case BPF_PROG_TYPE_SCHED_ACT:
|
||||
return BTF_KFUNC_HOOK_SCHED_ACT;
|
||||
|
||||
+24
-4
@@ -1450,18 +1450,22 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
|
||||
* provided by user sockaddr
|
||||
* @sk: sock struct that will use sockaddr
|
||||
* @uaddr: sockaddr struct provided by user
|
||||
* @uaddrlen: Pointer to the size of the sockaddr struct provided by user. It is
|
||||
* read-only for AF_INET[6] uaddr but can be modified for AF_UNIX
|
||||
* uaddr.
|
||||
* @atype: The type of program to be executed
|
||||
* @t_ctx: Pointer to attach type specific context
|
||||
* @flags: Pointer to u32 which contains higher bits of BPF program
|
||||
* return value (OR'ed together).
|
||||
*
|
||||
* socket is expected to be of type INET or INET6.
|
||||
* socket is expected to be of type INET, INET6 or UNIX.
|
||||
*
|
||||
* This function will return %-EPERM if an attached program is found and
|
||||
* returned value != 1 during execution. In all other cases, 0 is returned.
|
||||
*/
|
||||
int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
||||
struct sockaddr *uaddr,
|
||||
int *uaddrlen,
|
||||
enum cgroup_bpf_attach_type atype,
|
||||
void *t_ctx,
|
||||
u32 *flags)
|
||||
@@ -1473,21 +1477,31 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
||||
};
|
||||
struct sockaddr_storage unspec;
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
/* Check socket family since not all sockets represent network
|
||||
* endpoint (e.g. AF_UNIX).
|
||||
*/
|
||||
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
|
||||
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6 &&
|
||||
sk->sk_family != AF_UNIX)
|
||||
return 0;
|
||||
|
||||
if (!ctx.uaddr) {
|
||||
memset(&unspec, 0, sizeof(unspec));
|
||||
ctx.uaddr = (struct sockaddr *)&unspec;
|
||||
ctx.uaddrlen = 0;
|
||||
} else {
|
||||
ctx.uaddrlen = *uaddrlen;
|
||||
}
|
||||
|
||||
cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
|
||||
return bpf_prog_run_array_cg(&cgrp->bpf, atype, &ctx, bpf_prog_run,
|
||||
0, flags);
|
||||
ret = bpf_prog_run_array_cg(&cgrp->bpf, atype, &ctx, bpf_prog_run,
|
||||
0, flags);
|
||||
|
||||
if (!ret && uaddr)
|
||||
*uaddrlen = ctx.uaddrlen;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_addr);
|
||||
|
||||
@@ -2520,10 +2534,13 @@ cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return NULL;
|
||||
default:
|
||||
return &bpf_get_retval_proto;
|
||||
@@ -2535,10 +2552,13 @@ cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return NULL;
|
||||
default:
|
||||
return &bpf_set_retval_proto;
|
||||
|
||||
@@ -1272,7 +1272,7 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla
|
||||
|
||||
if (in_nmi())
|
||||
return -EOPNOTSUPP;
|
||||
if (flags > BPF_F_TIMER_ABS)
|
||||
if (flags & ~(BPF_F_TIMER_ABS | BPF_F_TIMER_CPU_PIN))
|
||||
return -EINVAL;
|
||||
__bpf_spin_lock_irqsave(&timer->lock);
|
||||
t = timer->timer;
|
||||
@@ -1286,6 +1286,9 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla
|
||||
else
|
||||
mode = HRTIMER_MODE_REL_SOFT;
|
||||
|
||||
if (flags & BPF_F_TIMER_CPU_PIN)
|
||||
mode |= HRTIMER_MODE_PINNED;
|
||||
|
||||
hrtimer_start(&t->timer, ns_to_ktime(nsecs), mode);
|
||||
out:
|
||||
__bpf_spin_unlock_irqrestore(&timer->lock);
|
||||
@@ -2549,6 +2552,9 @@ BTF_ID_FLAGS(func, bpf_dynptr_slice_rdwr, KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_num_new, KF_ITER_NEW)
|
||||
BTF_ID_FLAGS(func, bpf_iter_num_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_num_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_vma_new, KF_ITER_NEW | KF_RCU)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_vma_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_vma_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_adjust)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_is_null)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
|
||||
|
||||
@@ -28,7 +28,7 @@ struct bpf_stack_map {
|
||||
void *elems;
|
||||
struct pcpu_freelist freelist;
|
||||
u32 n_buckets;
|
||||
struct stack_map_bucket *buckets[];
|
||||
struct stack_map_bucket *buckets[] __counted_by(n_buckets);
|
||||
};
|
||||
|
||||
static inline bool stack_map_use_build_id(struct bpf_map *map)
|
||||
|
||||
+23
-6
@@ -2446,14 +2446,19 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
|
||||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -3374,7 +3379,7 @@ static void bpf_perf_link_dealloc(struct bpf_link *link)
|
||||
static int bpf_perf_link_fill_common(const struct perf_event *event,
|
||||
char __user *uname, u32 ulen,
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
u32 *fd_type)
|
||||
u32 *fd_type, unsigned long *missed)
|
||||
{
|
||||
const char *buf;
|
||||
u32 prog_id;
|
||||
@@ -3385,7 +3390,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,
|
||||
return -EINVAL;
|
||||
|
||||
err = bpf_get_perf_event_info(event, &prog_id, fd_type, &buf,
|
||||
probe_offset, probe_addr);
|
||||
probe_offset, probe_addr, missed);
|
||||
if (err)
|
||||
return err;
|
||||
if (!uname)
|
||||
@@ -3408,6 +3413,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,
|
||||
static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
||||
struct bpf_link_info *info)
|
||||
{
|
||||
unsigned long missed;
|
||||
char __user *uname;
|
||||
u64 addr, offset;
|
||||
u32 ulen, type;
|
||||
@@ -3416,7 +3422,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
||||
uname = u64_to_user_ptr(info->perf_event.kprobe.func_name);
|
||||
ulen = info->perf_event.kprobe.name_len;
|
||||
err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
|
||||
&type);
|
||||
&type, &missed);
|
||||
if (err)
|
||||
return err;
|
||||
if (type == BPF_FD_TYPE_KRETPROBE)
|
||||
@@ -3425,6 +3431,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
||||
info->perf_event.type = BPF_PERF_EVENT_KPROBE;
|
||||
|
||||
info->perf_event.kprobe.offset = offset;
|
||||
info->perf_event.kprobe.missed = missed;
|
||||
if (!kallsyms_show_value(current_cred()))
|
||||
addr = 0;
|
||||
info->perf_event.kprobe.addr = addr;
|
||||
@@ -3444,7 +3451,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
|
||||
uname = u64_to_user_ptr(info->perf_event.uprobe.file_name);
|
||||
ulen = info->perf_event.uprobe.name_len;
|
||||
err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
|
||||
&type);
|
||||
&type, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -3480,7 +3487,7 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event,
|
||||
uname = u64_to_user_ptr(info->perf_event.tracepoint.tp_name);
|
||||
ulen = info->perf_event.tracepoint.name_len;
|
||||
info->perf_event.type = BPF_PERF_EVENT_TRACEPOINT;
|
||||
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL);
|
||||
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int bpf_perf_link_fill_perf_event(const struct perf_event *event,
|
||||
@@ -3676,14 +3683,19 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
|
||||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
return BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
return BPF_PROG_TYPE_SOCK_OPS;
|
||||
@@ -3949,14 +3961,19 @@ static int bpf_prog_query(const union bpf_attr *attr,
|
||||
case BPF_CGROUP_INET6_POST_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_DEVICE:
|
||||
case BPF_CGROUP_SYSCTL:
|
||||
@@ -4822,7 +4839,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr,
|
||||
|
||||
err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
|
||||
&buf, &probe_offset,
|
||||
&probe_addr);
|
||||
&probe_addr, NULL);
|
||||
if (!err)
|
||||
err = bpf_task_fd_query_copy(attr, uattr, prog_id,
|
||||
fd_type, buf,
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/bpf_mem_alloc.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include "mmap_unlock_work.h"
|
||||
|
||||
static const char * const iter_task_type_names[] = {
|
||||
@@ -803,6 +805,95 @@ const struct bpf_func_proto bpf_find_vma_proto = {
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
struct bpf_iter_task_vma_kern_data {
|
||||
struct task_struct *task;
|
||||
struct mm_struct *mm;
|
||||
struct mmap_unlock_irq_work *work;
|
||||
struct vma_iterator vmi;
|
||||
};
|
||||
|
||||
struct bpf_iter_task_vma {
|
||||
/* opaque iterator state; having __u64 here allows to preserve correct
|
||||
* alignment requirements in vmlinux.h, generated from BTF
|
||||
*/
|
||||
__u64 __opaque[1];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/* Non-opaque version of bpf_iter_task_vma */
|
||||
struct bpf_iter_task_vma_kern {
|
||||
struct bpf_iter_task_vma_kern_data *data;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
|
||||
__bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,
|
||||
struct task_struct *task, u64 addr)
|
||||
{
|
||||
struct bpf_iter_task_vma_kern *kit = (void *)it;
|
||||
bool irq_work_busy = false;
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct bpf_iter_task_vma_kern) != sizeof(struct bpf_iter_task_vma));
|
||||
BUILD_BUG_ON(__alignof__(struct bpf_iter_task_vma_kern) != __alignof__(struct bpf_iter_task_vma));
|
||||
|
||||
/* is_iter_reg_valid_uninit guarantees that kit hasn't been initialized
|
||||
* before, so non-NULL kit->data doesn't point to previously
|
||||
* bpf_mem_alloc'd bpf_iter_task_vma_kern_data
|
||||
*/
|
||||
kit->data = bpf_mem_alloc(&bpf_global_ma, sizeof(struct bpf_iter_task_vma_kern_data));
|
||||
if (!kit->data)
|
||||
return -ENOMEM;
|
||||
|
||||
kit->data->task = get_task_struct(task);
|
||||
kit->data->mm = task->mm;
|
||||
if (!kit->data->mm) {
|
||||
err = -ENOENT;
|
||||
goto err_cleanup_iter;
|
||||
}
|
||||
|
||||
/* kit->data->work == NULL is valid after bpf_mmap_unlock_get_irq_work */
|
||||
irq_work_busy = bpf_mmap_unlock_get_irq_work(&kit->data->work);
|
||||
if (irq_work_busy || !mmap_read_trylock(kit->data->mm)) {
|
||||
err = -EBUSY;
|
||||
goto err_cleanup_iter;
|
||||
}
|
||||
|
||||
vma_iter_init(&kit->data->vmi, kit->data->mm, addr);
|
||||
return 0;
|
||||
|
||||
err_cleanup_iter:
|
||||
if (kit->data->task)
|
||||
put_task_struct(kit->data->task);
|
||||
bpf_mem_free(&bpf_global_ma, kit->data);
|
||||
/* NULL kit->data signals failed bpf_iter_task_vma initialization */
|
||||
kit->data = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
__bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it)
|
||||
{
|
||||
struct bpf_iter_task_vma_kern *kit = (void *)it;
|
||||
|
||||
if (!kit->data) /* bpf_iter_task_vma_new failed */
|
||||
return NULL;
|
||||
return vma_next(&kit->data->vmi);
|
||||
}
|
||||
|
||||
__bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
|
||||
{
|
||||
struct bpf_iter_task_vma_kern *kit = (void *)it;
|
||||
|
||||
if (kit->data) {
|
||||
bpf_mmap_unlock_mm(kit->data->work, kit->data->mm);
|
||||
put_task_struct(kit->data->task);
|
||||
bpf_mem_free(&bpf_global_ma, kit->data);
|
||||
}
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
|
||||
DEFINE_PER_CPU(struct mmap_unlock_irq_work, mmap_unlock_work);
|
||||
|
||||
static void do_mmap_read_unlock(struct irq_work *entry)
|
||||
|
||||
+56
-25
@@ -1342,6 +1342,50 @@ static void scrub_spilled_slot(u8 *stype)
|
||||
*stype = STACK_MISC;
|
||||
}
|
||||
|
||||
static void print_scalar_ranges(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg,
|
||||
const char **sep)
|
||||
{
|
||||
struct {
|
||||
const char *name;
|
||||
u64 val;
|
||||
bool omit;
|
||||
} minmaxs[] = {
|
||||
{"smin", reg->smin_value, reg->smin_value == S64_MIN},
|
||||
{"smax", reg->smax_value, reg->smax_value == S64_MAX},
|
||||
{"umin", reg->umin_value, reg->umin_value == 0},
|
||||
{"umax", reg->umax_value, reg->umax_value == U64_MAX},
|
||||
{"smin32", (s64)reg->s32_min_value, reg->s32_min_value == S32_MIN},
|
||||
{"smax32", (s64)reg->s32_max_value, reg->s32_max_value == S32_MAX},
|
||||
{"umin32", reg->u32_min_value, reg->u32_min_value == 0},
|
||||
{"umax32", reg->u32_max_value, reg->u32_max_value == U32_MAX},
|
||||
}, *m1, *m2, *mend = &minmaxs[ARRAY_SIZE(minmaxs)];
|
||||
bool neg1, neg2;
|
||||
|
||||
for (m1 = &minmaxs[0]; m1 < mend; m1++) {
|
||||
if (m1->omit)
|
||||
continue;
|
||||
|
||||
neg1 = m1->name[0] == 's' && (s64)m1->val < 0;
|
||||
|
||||
verbose(env, "%s%s=", *sep, m1->name);
|
||||
*sep = ",";
|
||||
|
||||
for (m2 = m1 + 2; m2 < mend; m2 += 2) {
|
||||
if (m2->omit || m2->val != m1->val)
|
||||
continue;
|
||||
/* don't mix negatives with positives */
|
||||
neg2 = m2->name[0] == 's' && (s64)m2->val < 0;
|
||||
if (neg2 != neg1)
|
||||
continue;
|
||||
m2->omit = true;
|
||||
verbose(env, "%s=", m2->name);
|
||||
}
|
||||
|
||||
verbose(env, m1->name[0] == 's' ? "%lld" : "%llu", m1->val);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_verifier_state(struct bpf_verifier_env *env,
|
||||
const struct bpf_func_state *state,
|
||||
bool print_all)
|
||||
@@ -1405,34 +1449,13 @@ static void print_verifier_state(struct bpf_verifier_env *env,
|
||||
*/
|
||||
verbose_a("imm=%llx", reg->var_off.value);
|
||||
} else {
|
||||
if (reg->smin_value != reg->umin_value &&
|
||||
reg->smin_value != S64_MIN)
|
||||
verbose_a("smin=%lld", (long long)reg->smin_value);
|
||||
if (reg->smax_value != reg->umax_value &&
|
||||
reg->smax_value != S64_MAX)
|
||||
verbose_a("smax=%lld", (long long)reg->smax_value);
|
||||
if (reg->umin_value != 0)
|
||||
verbose_a("umin=%llu", (unsigned long long)reg->umin_value);
|
||||
if (reg->umax_value != U64_MAX)
|
||||
verbose_a("umax=%llu", (unsigned long long)reg->umax_value);
|
||||
print_scalar_ranges(env, reg, &sep);
|
||||
if (!tnum_is_unknown(reg->var_off)) {
|
||||
char tn_buf[48];
|
||||
|
||||
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
|
||||
verbose_a("var_off=%s", tn_buf);
|
||||
}
|
||||
if (reg->s32_min_value != reg->smin_value &&
|
||||
reg->s32_min_value != S32_MIN)
|
||||
verbose_a("s32_min=%d", (int)(reg->s32_min_value));
|
||||
if (reg->s32_max_value != reg->smax_value &&
|
||||
reg->s32_max_value != S32_MAX)
|
||||
verbose_a("s32_max=%d", (int)(reg->s32_max_value));
|
||||
if (reg->u32_min_value != reg->umin_value &&
|
||||
reg->u32_min_value != U32_MIN)
|
||||
verbose_a("u32_min=%d", (int)(reg->u32_min_value));
|
||||
if (reg->u32_max_value != reg->umax_value &&
|
||||
reg->u32_max_value != U32_MAX)
|
||||
verbose_a("u32_max=%d", (int)(reg->u32_max_value));
|
||||
}
|
||||
#undef verbose_a
|
||||
|
||||
@@ -1516,7 +1539,8 @@ static void print_verifier_state(struct bpf_verifier_env *env,
|
||||
if (state->in_async_callback_fn)
|
||||
verbose(env, " async_cb");
|
||||
verbose(env, "\n");
|
||||
mark_verifier_state_clean(env);
|
||||
if (!print_all)
|
||||
mark_verifier_state_clean(env);
|
||||
}
|
||||
|
||||
static inline u32 vlog_alignment(u32 pos)
|
||||
@@ -3114,7 +3138,7 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
|
||||
|
||||
if (class == BPF_LDX) {
|
||||
if (t != SRC_OP)
|
||||
return BPF_SIZE(code) == BPF_DW;
|
||||
return BPF_SIZE(code) == BPF_DW || BPF_MODE(code) == BPF_MEMSX;
|
||||
/* LDX source must be ptr. */
|
||||
return true;
|
||||
}
|
||||
@@ -14383,6 +14407,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
!sanitize_speculative_path(env, insn, *insn_idx + 1,
|
||||
*insn_idx))
|
||||
return -EFAULT;
|
||||
if (env->log.level & BPF_LOG_LEVEL)
|
||||
print_insn_state(env, this_branch->frame[this_branch->curframe]);
|
||||
*insn_idx += insn->off;
|
||||
return 0;
|
||||
} else if (pred == 0) {
|
||||
@@ -14395,6 +14421,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
*insn_idx + insn->off + 1,
|
||||
*insn_idx))
|
||||
return -EFAULT;
|
||||
if (env->log.level & BPF_LOG_LEVEL)
|
||||
print_insn_state(env, this_branch->frame[this_branch->curframe]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14795,10 +14823,13 @@ static int check_return_code(struct bpf_verifier_env *env, int regno)
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET4_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET4_GETSOCKNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETSOCKNAME)
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETSOCKNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_GETSOCKNAME)
|
||||
range = tnum_range(1, 1);
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_INET4_BIND ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_BIND)
|
||||
|
||||
@@ -117,6 +117,9 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
|
||||
* and don't send kprobe event into ring-buffer,
|
||||
* so return zero here
|
||||
*/
|
||||
rcu_read_lock();
|
||||
bpf_prog_inc_misses_counters(rcu_dereference(call->prog_array));
|
||||
rcu_read_unlock();
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -2384,7 +2387,8 @@ int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
|
||||
|
||||
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
||||
u32 *fd_type, const char **buf,
|
||||
u64 *probe_offset, u64 *probe_addr)
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed)
|
||||
{
|
||||
bool is_tracepoint, is_syscall_tp;
|
||||
struct bpf_prog *prog;
|
||||
@@ -2419,7 +2423,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
||||
#ifdef CONFIG_KPROBE_EVENTS
|
||||
if (flags & TRACE_EVENT_FL_KPROBE)
|
||||
err = bpf_get_kprobe_info(event, fd_type, buf,
|
||||
probe_offset, probe_addr,
|
||||
probe_offset, probe_addr, missed,
|
||||
event->attr.type == PERF_TYPE_TRACEPOINT);
|
||||
#endif
|
||||
#ifdef CONFIG_UPROBE_EVENTS
|
||||
@@ -2614,6 +2618,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
|
||||
kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
|
||||
info->kprobe_multi.count = kmulti_link->cnt;
|
||||
info->kprobe_multi.flags = kmulti_link->flags;
|
||||
info->kprobe_multi.missed = kmulti_link->fp.nmissed;
|
||||
|
||||
if (!uaddrs)
|
||||
return 0;
|
||||
@@ -2710,6 +2715,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
|
||||
int err;
|
||||
|
||||
if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) {
|
||||
bpf_prog_inc_misses_counter(link->link.prog);
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user