Skip to content

Commit b115653

Browse files
committed
Daniel Borkmann says: ==================== pull-request: bpf-next 2024-06-06 We've added 54 non-merge commits during the last 10 day(s) which contain a total of 50 files changed, 1887 insertions(+), 527 deletions(-). The main changes are: 1) Add a user space notification mechanism via epoll when a struct_ops object is getting detached/unregistered, from Kui-Feng Lee. 2) Big batch of BPF selftest refactoring for sockmap and BPF congctl tests, from Geliang Tang. 3) Add BTF field (type and string fields, right now) iterator support to libbpf instead of using existing callback-based approaches, from Andrii Nakryiko. 4) Extend BPF selftests for the latter with a new btf_field_iter selftest, from Alan Maguire. 5) Add new kfuncs for a generic, open-coded bits iterator, from Yafang Shao. 6) Fix BPF selftests' kallsyms_find() helper under kernels configured with CONFIG_LTO_CLANG_THIN, from Yonghong Song. 7) Remove a bunch of unused structs in BPF selftests, from David Alan Gilbert. 8) Convert test_sockmap section names into names understood by libbpf so it can deduce program type and attach type, from Jakub Sitnicki. 9) Extend libbpf with the ability to configure log verbosity via LIBBPF_LOG_LEVEL environment variable, from Mykyta Yatsenko. 10) Fix BPF selftests with regards to bpf_cookie and find_vma flakiness in nested VMs, from Song Liu. 11) Extend riscv32/64 JITs to introduce shift/add helpers to generate Zba optimization, from Xiao Wang. 12) Enable BPF programs to declare arrays and struct fields with kptr, bpf_rb_root, and bpf_list_head, from Kui-Feng Lee. * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (54 commits) selftests/bpf: Drop useless arguments of do_test in bpf_tcp_ca selftests/bpf: Use start_test in test_dctcp in bpf_tcp_ca selftests/bpf: Use start_test in test_dctcp_fallback in bpf_tcp_ca selftests/bpf: Add start_test helper in bpf_tcp_ca selftests/bpf: Use connect_to_fd_opts in do_test in bpf_tcp_ca libbpf: Auto-attach struct_ops BPF maps in BPF skeleton selftests/bpf: Add btf_field_iter selftests selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT libbpf: Remove callback-based type/string BTF field visitor helpers bpftool: Use BTF field iterator in btfgen libbpf: Make use of BTF field iterator in BTF handling code libbpf: Make use of BTF field iterator in BPF linker code libbpf: Add BTF field iterator selftests/bpf: Ignore .llvm.<hash> suffix in kallsyms_find() selftests/bpf: Fix bpf_cookie and find_vma in nested VM selftests/bpf: Test global bpf_list_head arrays. selftests/bpf: Test global bpf_rb_root arrays and fields in nested struct types. selftests/bpf: Test kptr arrays and kptrs in nested struct fields. bpf: limit the number of levels of a nested struct type. bpf: look into the types of the fields of a struct type recursively. ... ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 93d4e8b + f85af9d commit b115653

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1887
-527
lines changed

Documentation/bpf/libbpf/libbpf_overview.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ compilation and skeleton generation. Using Libbpf-rs will make building user
219219
space part of the BPF application easier. Note that the BPF program themselves
220220
must still be written in plain C.
221221

222+
libbpf logging
223+
==============
224+
225+
By default, libbpf logs informational and warning messages to stderr. The
226+
verbosity of these messages can be controlled by setting the environment
227+
variable LIBBPF_LOG_LEVEL to either warn, info, or debug. A custom log
228+
callback can be set using ``libbpf_set_print()``.
229+
222230
Additional Documentation
223231
========================
224232

arch/riscv/net/bpf_jit.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,17 @@ static inline u16 rvc_swsp(u32 imm8, u8 rs2)
742742
return rv_css_insn(0x6, imm, rs2, 0x2);
743743
}
744744

745+
/* RVZBA instructions. */
746+
static inline u32 rvzba_sh2add(u8 rd, u8 rs1, u8 rs2)
747+
{
748+
return rv_r_insn(0x10, rs2, rs1, 0x4, rd, 0x33);
749+
}
750+
751+
static inline u32 rvzba_sh3add(u8 rd, u8 rs1, u8 rs2)
752+
{
753+
return rv_r_insn(0x10, rs2, rs1, 0x6, rd, 0x33);
754+
}
755+
745756
/* RVZBB instructions. */
746757
static inline u32 rvzbb_sextb(u8 rd, u8 rs1)
747758
{
@@ -1095,6 +1106,28 @@ static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
10951106
emit(rv_sw(rs1, off, rs2), ctx);
10961107
}
10971108

1109+
static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1110+
{
1111+
if (rvzba_enabled()) {
1112+
emit(rvzba_sh2add(rd, rs1, rs2), ctx);
1113+
return;
1114+
}
1115+
1116+
emit_slli(rd, rs1, 2, ctx);
1117+
emit_add(rd, rd, rs2, ctx);
1118+
}
1119+
1120+
static inline void emit_sh3add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1121+
{
1122+
if (rvzba_enabled()) {
1123+
emit(rvzba_sh3add(rd, rs1, rs2), ctx);
1124+
return;
1125+
}
1126+
1127+
emit_slli(rd, rs1, 3, ctx);
1128+
emit_add(rd, rd, rs2, ctx);
1129+
}
1130+
10981131
/* RV64-only helper functions. */
10991132
#if __riscv_xlen == 64
11001133

arch/riscv/net/bpf_jit_comp32.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,8 +811,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
811811
* if (!prog)
812812
* goto out;
813813
*/
814-
emit(rv_slli(RV_REG_T0, lo(idx_reg), 2), ctx);
815-
emit(rv_add(RV_REG_T0, RV_REG_T0, lo(arr_reg)), ctx);
814+
emit_sh2add(RV_REG_T0, lo(idx_reg), lo(arr_reg), ctx);
816815
off = offsetof(struct bpf_array, ptrs);
817816
if (is_12b_check(off, insn))
818817
return -1;

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
380380
* if (!prog)
381381
* goto out;
382382
*/
383-
emit_slli(RV_REG_T2, RV_REG_A2, 3, ctx);
384-
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_A1, ctx);
383+
emit_sh3add(RV_REG_T2, RV_REG_A2, RV_REG_A1, ctx);
385384
off = offsetof(struct bpf_array, ptrs);
386385
if (is_12b_check(off, insn))
387386
return -1;
@@ -1099,12 +1098,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
10991098
/* Load current CPU number in T1 */
11001099
emit_ld(RV_REG_T1, offsetof(struct thread_info, cpu),
11011100
RV_REG_TP, ctx);
1102-
/* << 3 because offsets are 8 bytes */
1103-
emit_slli(RV_REG_T1, RV_REG_T1, 3, ctx);
11041101
/* Load address of __per_cpu_offset array in T2 */
11051102
emit_addr(RV_REG_T2, (u64)&__per_cpu_offset, extra_pass, ctx);
1106-
/* Add offset of current CPU to __per_cpu_offset */
1107-
emit_add(RV_REG_T1, RV_REG_T2, RV_REG_T1, ctx);
1103+
/* Get address of __per_cpu_offset[cpu] in T1 */
1104+
emit_sh3add(RV_REG_T1, RV_REG_T1, RV_REG_T2, ctx);
11081105
/* Load __per_cpu_offset[cpu] in T1 */
11091106
emit_ld(RV_REG_T1, 0, RV_REG_T1, ctx);
11101107
/* Add the offset to Rd */

include/linux/bpf.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ struct bpf_link_ops {
16121612
struct bpf_link_info *info);
16131613
int (*update_map)(struct bpf_link *link, struct bpf_map *new_map,
16141614
struct bpf_map *old_map);
1615+
__poll_t (*poll)(struct file *file, struct poll_table_struct *pts);
16151616
};
16161617

16171618
struct bpf_tramp_link {
@@ -1730,9 +1731,9 @@ struct bpf_struct_ops {
17301731
int (*init_member)(const struct btf_type *t,
17311732
const struct btf_member *member,
17321733
void *kdata, const void *udata);
1733-
int (*reg)(void *kdata);
1734-
void (*unreg)(void *kdata);
1735-
int (*update)(void *kdata, void *old_kdata);
1734+
int (*reg)(void *kdata, struct bpf_link *link);
1735+
void (*unreg)(void *kdata, struct bpf_link *link);
1736+
int (*update)(void *kdata, void *old_kdata, struct bpf_link *link);
17361737
int (*validate)(void *kdata);
17371738
void *cfi_stubs;
17381739
struct module *owner;
@@ -2333,6 +2334,7 @@ int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer);
23332334
int bpf_link_settle(struct bpf_link_primer *primer);
23342335
void bpf_link_cleanup(struct bpf_link_primer *primer);
23352336
void bpf_link_inc(struct bpf_link *link);
2337+
struct bpf_link *bpf_link_inc_not_zero(struct bpf_link *link);
23362338
void bpf_link_put(struct bpf_link *link);
23372339
int bpf_link_new_fd(struct bpf_link *link);
23382340
struct bpf_link *bpf_link_get_from_fd(u32 ufd);
@@ -2704,6 +2706,11 @@ static inline void bpf_link_inc(struct bpf_link *link)
27042706
{
27052707
}
27062708

2709+
static inline struct bpf_link *bpf_link_inc_not_zero(struct bpf_link *link)
2710+
{
2711+
return NULL;
2712+
}
2713+
27072714
static inline void bpf_link_put(struct bpf_link *link)
27082715
{
27092716
}

kernel/bpf/bpf_struct_ops.c

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/mutex.h>
1313
#include <linux/btf_ids.h>
1414
#include <linux/rcupdate_wait.h>
15+
#include <linux/poll.h>
1516

1617
struct bpf_struct_ops_value {
1718
struct bpf_struct_ops_common_value common;
@@ -56,6 +57,7 @@ struct bpf_struct_ops_map {
5657
struct bpf_struct_ops_link {
5758
struct bpf_link link;
5859
struct bpf_map __rcu *map;
60+
wait_queue_head_t wait_hup;
5961
};
6062

6163
static DEFINE_MUTEX(update_mutex);
@@ -757,7 +759,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
757759
goto unlock;
758760
}
759761

760-
err = st_ops->reg(kdata);
762+
err = st_ops->reg(kdata, NULL);
761763
if (likely(!err)) {
762764
/* This refcnt increment on the map here after
763765
* 'st_ops->reg()' is secure since the state of the
@@ -805,7 +807,7 @@ static long bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key)
805807
BPF_STRUCT_OPS_STATE_TOBEFREE);
806808
switch (prev_state) {
807809
case BPF_STRUCT_OPS_STATE_INUSE:
808-
st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data);
810+
st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, NULL);
809811
bpf_map_put(map);
810812
return 0;
811813
case BPF_STRUCT_OPS_STATE_TOBEFREE:
@@ -1057,10 +1059,7 @@ static void bpf_struct_ops_map_link_dealloc(struct bpf_link *link)
10571059
st_map = (struct bpf_struct_ops_map *)
10581060
rcu_dereference_protected(st_link->map, true);
10591061
if (st_map) {
1060-
/* st_link->map can be NULL if
1061-
* bpf_struct_ops_link_create() fails to register.
1062-
*/
1063-
st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data);
1062+
st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, link);
10641063
bpf_map_put(&st_map->map);
10651064
}
10661065
kfree(st_link);
@@ -1075,7 +1074,8 @@ static void bpf_struct_ops_map_link_show_fdinfo(const struct bpf_link *link,
10751074
st_link = container_of(link, struct bpf_struct_ops_link, link);
10761075
rcu_read_lock();
10771076
map = rcu_dereference(st_link->map);
1078-
seq_printf(seq, "map_id:\t%d\n", map->id);
1077+
if (map)
1078+
seq_printf(seq, "map_id:\t%d\n", map->id);
10791079
rcu_read_unlock();
10801080
}
10811081

@@ -1088,7 +1088,8 @@ static int bpf_struct_ops_map_link_fill_link_info(const struct bpf_link *link,
10881088
st_link = container_of(link, struct bpf_struct_ops_link, link);
10891089
rcu_read_lock();
10901090
map = rcu_dereference(st_link->map);
1091-
info->struct_ops.map_id = map->id;
1091+
if (map)
1092+
info->struct_ops.map_id = map->id;
10921093
rcu_read_unlock();
10931094
return 0;
10941095
}
@@ -1113,6 +1114,10 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
11131114
mutex_lock(&update_mutex);
11141115

11151116
old_map = rcu_dereference_protected(st_link->map, lockdep_is_held(&update_mutex));
1117+
if (!old_map) {
1118+
err = -ENOLINK;
1119+
goto err_out;
1120+
}
11161121
if (expected_old_map && old_map != expected_old_map) {
11171122
err = -EPERM;
11181123
goto err_out;
@@ -1125,7 +1130,7 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
11251130
goto err_out;
11261131
}
11271132

1128-
err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data);
1133+
err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data, link);
11291134
if (err)
11301135
goto err_out;
11311136

@@ -1139,11 +1144,53 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
11391144
return err;
11401145
}
11411146

1147+
static int bpf_struct_ops_map_link_detach(struct bpf_link *link)
1148+
{
1149+
struct bpf_struct_ops_link *st_link = container_of(link, struct bpf_struct_ops_link, link);
1150+
struct bpf_struct_ops_map *st_map;
1151+
struct bpf_map *map;
1152+
1153+
mutex_lock(&update_mutex);
1154+
1155+
map = rcu_dereference_protected(st_link->map, lockdep_is_held(&update_mutex));
1156+
if (!map) {
1157+
mutex_unlock(&update_mutex);
1158+
return 0;
1159+
}
1160+
st_map = container_of(map, struct bpf_struct_ops_map, map);
1161+
1162+
st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, link);
1163+
1164+
RCU_INIT_POINTER(st_link->map, NULL);
1165+
/* Pair with bpf_map_get() in bpf_struct_ops_link_create() or
1166+
* bpf_map_inc() in bpf_struct_ops_map_link_update().
1167+
*/
1168+
bpf_map_put(&st_map->map);
1169+
1170+
mutex_unlock(&update_mutex);
1171+
1172+
wake_up_interruptible_poll(&st_link->wait_hup, EPOLLHUP);
1173+
1174+
return 0;
1175+
}
1176+
1177+
static __poll_t bpf_struct_ops_map_link_poll(struct file *file,
1178+
struct poll_table_struct *pts)
1179+
{
1180+
struct bpf_struct_ops_link *st_link = file->private_data;
1181+
1182+
poll_wait(file, &st_link->wait_hup, pts);
1183+
1184+
return rcu_access_pointer(st_link->map) ? 0 : EPOLLHUP;
1185+
}
1186+
11421187
static const struct bpf_link_ops bpf_struct_ops_map_lops = {
11431188
.dealloc = bpf_struct_ops_map_link_dealloc,
1189+
.detach = bpf_struct_ops_map_link_detach,
11441190
.show_fdinfo = bpf_struct_ops_map_link_show_fdinfo,
11451191
.fill_link_info = bpf_struct_ops_map_link_fill_link_info,
11461192
.update_map = bpf_struct_ops_map_link_update,
1193+
.poll = bpf_struct_ops_map_link_poll,
11471194
};
11481195

11491196
int bpf_struct_ops_link_create(union bpf_attr *attr)
@@ -1176,13 +1223,21 @@ int bpf_struct_ops_link_create(union bpf_attr *attr)
11761223
if (err)
11771224
goto err_out;
11781225

1179-
err = st_map->st_ops_desc->st_ops->reg(st_map->kvalue.data);
1226+
init_waitqueue_head(&link->wait_hup);
1227+
1228+
/* Hold the update_mutex such that the subsystem cannot
1229+
* do link->ops->detach() before the link is fully initialized.
1230+
*/
1231+
mutex_lock(&update_mutex);
1232+
err = st_map->st_ops_desc->st_ops->reg(st_map->kvalue.data, &link->link);
11801233
if (err) {
1234+
mutex_unlock(&update_mutex);
11811235
bpf_link_cleanup(&link_primer);
11821236
link = NULL;
11831237
goto err_out;
11841238
}
11851239
RCU_INIT_POINTER(link->map, map);
1240+
mutex_unlock(&update_mutex);
11861241

11871242
return bpf_link_settle(&link_primer);
11881243

0 commit comments

Comments
 (0)