Skip to content

Commit d786aba

Browse files
committed
Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Pull bpf fixes from Alexei Starovoitov: - Fix handling of BPF arena relocations (Andrii Nakryiko) - Fix race in bpf_arch_text_poke() on s390 (Ilya Leoshkevich) - Fix use of virt_to_phys() on arm64 when mmapping BTF (Lorenz Bauer) - Reject %p% format string in bprintf-like BPF helpers (Paul Chaignon) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: libbpf: Fix handling of BPF arena relocations btf: Fix virt_to_phys() on arm64 when mmapping BTF selftests/bpf: Stress test attaching a BPF prog to another BPF prog s390/bpf: Fix bpf_arch_text_poke() with new_addr == NULL again selftests/bpf: Add negative test cases for snprintf bpf: Reject %p% format string in bprintf-like helpers
2 parents c460535 + 0238c45 commit d786aba

File tree

6 files changed

+100
-12
lines changed

6 files changed

+100
-12
lines changed

arch/s390/net/bpf_jit_comp.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,15 @@ static void bpf_jit_plt(struct bpf_plt *plt, void *ret, void *target)
566566
{
567567
memcpy(plt, &bpf_plt, sizeof(*plt));
568568
plt->ret = ret;
569-
plt->target = target;
569+
/*
570+
* (target == NULL) implies that the branch to this PLT entry was
571+
* patched and became a no-op. However, some CPU could have jumped
572+
* to this PLT entry before patching and may be still executing it.
573+
*
574+
* Since the intention in this case is to make the PLT entry a no-op,
575+
* make the target point to the return label instead of NULL.
576+
*/
577+
plt->target = target ?: ret;
570578
}
571579

572580
/*

kernel/bpf/helpers.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -884,18 +884,23 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
884884
if (fmt[i] == 'p') {
885885
sizeof_cur_arg = sizeof(long);
886886

887+
if (fmt[i + 1] == 0 || isspace(fmt[i + 1]) ||
888+
ispunct(fmt[i + 1])) {
889+
if (tmp_buf)
890+
cur_arg = raw_args[num_spec];
891+
goto nocopy_fmt;
892+
}
893+
887894
if ((fmt[i + 1] == 'k' || fmt[i + 1] == 'u') &&
888895
fmt[i + 2] == 's') {
889896
fmt_ptype = fmt[i + 1];
890897
i += 2;
891898
goto fmt_str;
892899
}
893900

894-
if (fmt[i + 1] == 0 || isspace(fmt[i + 1]) ||
895-
ispunct(fmt[i + 1]) || fmt[i + 1] == 'K' ||
901+
if (fmt[i + 1] == 'K' ||
896902
fmt[i + 1] == 'x' || fmt[i + 1] == 's' ||
897903
fmt[i + 1] == 'S') {
898-
/* just kernel pointers */
899904
if (tmp_buf)
900905
cur_arg = raw_args[num_spec];
901906
i++;

kernel/bpf/sysfs_btf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static int btf_sysfs_vmlinux_mmap(struct file *filp, struct kobject *kobj,
2121
{
2222
unsigned long pages = PAGE_ALIGN(attr->size) >> PAGE_SHIFT;
2323
size_t vm_size = vma->vm_end - vma->vm_start;
24-
phys_addr_t addr = virt_to_phys(__start_BTF);
24+
phys_addr_t addr = __pa_symbol(__start_BTF);
2525
unsigned long pfn = addr >> PAGE_SHIFT;
2626

2727
if (attr->private != __start_BTF || !PAGE_ALIGNED(addr))

tools/lib/bpf/libbpf.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ struct bpf_object {
735735

736736
struct usdt_manager *usdt_man;
737737

738-
struct bpf_map *arena_map;
738+
int arena_map_idx;
739739
void *arena_data;
740740
size_t arena_data_sz;
741741

@@ -1517,6 +1517,7 @@ static struct bpf_object *bpf_object__new(const char *path,
15171517
obj->efile.obj_buf_sz = obj_buf_sz;
15181518
obj->efile.btf_maps_shndx = -1;
15191519
obj->kconfig_map_idx = -1;
1520+
obj->arena_map_idx = -1;
15201521

15211522
obj->kern_version = get_kernel_version();
15221523
obj->state = OBJ_OPEN;
@@ -2964,7 +2965,7 @@ static int init_arena_map_data(struct bpf_object *obj, struct bpf_map *map,
29642965
const long page_sz = sysconf(_SC_PAGE_SIZE);
29652966
size_t mmap_sz;
29662967

2967-
mmap_sz = bpf_map_mmap_sz(obj->arena_map);
2968+
mmap_sz = bpf_map_mmap_sz(map);
29682969
if (roundup(data_sz, page_sz) > mmap_sz) {
29692970
pr_warn("elf: sec '%s': declared ARENA map size (%zu) is too small to hold global __arena variables of size %zu\n",
29702971
sec_name, mmap_sz, data_sz);
@@ -3038,12 +3039,12 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict,
30383039
if (map->def.type != BPF_MAP_TYPE_ARENA)
30393040
continue;
30403041

3041-
if (obj->arena_map) {
3042+
if (obj->arena_map_idx >= 0) {
30423043
pr_warn("map '%s': only single ARENA map is supported (map '%s' is also ARENA)\n",
3043-
map->name, obj->arena_map->name);
3044+
map->name, obj->maps[obj->arena_map_idx].name);
30443045
return -EINVAL;
30453046
}
3046-
obj->arena_map = map;
3047+
obj->arena_map_idx = i;
30473048

30483049
if (obj->efile.arena_data) {
30493050
err = init_arena_map_data(obj, map, ARENA_SEC, obj->efile.arena_data_shndx,
@@ -3053,7 +3054,7 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict,
30533054
return err;
30543055
}
30553056
}
3056-
if (obj->efile.arena_data && !obj->arena_map) {
3057+
if (obj->efile.arena_data && obj->arena_map_idx < 0) {
30573058
pr_warn("elf: sec '%s': to use global __arena variables the ARENA map should be explicitly declared in SEC(\".maps\")\n",
30583059
ARENA_SEC);
30593060
return -ENOENT;
@@ -4583,8 +4584,13 @@ static int bpf_program__record_reloc(struct bpf_program *prog,
45834584
if (shdr_idx == obj->efile.arena_data_shndx) {
45844585
reloc_desc->type = RELO_DATA;
45854586
reloc_desc->insn_idx = insn_idx;
4586-
reloc_desc->map_idx = obj->arena_map - obj->maps;
4587+
reloc_desc->map_idx = obj->arena_map_idx;
45874588
reloc_desc->sym_off = sym->st_value;
4589+
4590+
map = &obj->maps[obj->arena_map_idx];
4591+
pr_debug("prog '%s': found arena map %d (%s, sec %d, off %zu) for insn %u\n",
4592+
prog->name, obj->arena_map_idx, map->name, map->sec_idx,
4593+
map->sec_offset, insn_idx);
45884594
return 0;
45894595
}
45904596

tools/testing/selftests/bpf/prog_tests/recursive_attach.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,70 @@ void test_fentry_attach_btf_presence(void)
149149
fentry_recursive_target__destroy(target_skel);
150150
fentry_recursive__destroy(tracing_skel);
151151
}
152+
153+
static void *fentry_target_test_run(void *arg)
154+
{
155+
for (;;) {
156+
int prog_fd = __atomic_load_n((int *)arg, __ATOMIC_SEQ_CST);
157+
LIBBPF_OPTS(bpf_test_run_opts, topts);
158+
int err;
159+
160+
if (prog_fd == -1)
161+
break;
162+
err = bpf_prog_test_run_opts(prog_fd, &topts);
163+
if (!ASSERT_OK(err, "fentry_target test_run"))
164+
break;
165+
}
166+
167+
return NULL;
168+
}
169+
170+
void test_fentry_attach_stress(void)
171+
{
172+
struct fentry_recursive_target *target_skel = NULL;
173+
struct fentry_recursive *tracing_skel = NULL;
174+
struct bpf_program *prog;
175+
int err, i, tgt_prog_fd;
176+
pthread_t thread;
177+
178+
target_skel = fentry_recursive_target__open_and_load();
179+
if (!ASSERT_OK_PTR(target_skel,
180+
"fentry_recursive_target__open_and_load"))
181+
goto close_prog;
182+
tgt_prog_fd = bpf_program__fd(target_skel->progs.fentry_target);
183+
err = pthread_create(&thread, NULL,
184+
fentry_target_test_run, &tgt_prog_fd);
185+
if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
186+
goto close_prog;
187+
188+
for (i = 0; i < 1000; i++) {
189+
tracing_skel = fentry_recursive__open();
190+
if (!ASSERT_OK_PTR(tracing_skel, "fentry_recursive__open"))
191+
goto stop_thread;
192+
193+
prog = tracing_skel->progs.recursive_attach;
194+
err = bpf_program__set_attach_target(prog, tgt_prog_fd,
195+
"fentry_target");
196+
if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
197+
goto stop_thread;
198+
199+
err = fentry_recursive__load(tracing_skel);
200+
if (!ASSERT_OK(err, "fentry_recursive__load"))
201+
goto stop_thread;
202+
203+
err = fentry_recursive__attach(tracing_skel);
204+
if (!ASSERT_OK(err, "fentry_recursive__attach"))
205+
goto stop_thread;
206+
207+
fentry_recursive__destroy(tracing_skel);
208+
tracing_skel = NULL;
209+
}
210+
211+
stop_thread:
212+
__atomic_store_n(&tgt_prog_fd, -1, __ATOMIC_SEQ_CST);
213+
err = pthread_join(thread, NULL);
214+
ASSERT_OK(err, "pthread_join");
215+
close_prog:
216+
fentry_recursive__destroy(tracing_skel);
217+
fentry_recursive_target__destroy(target_skel);
218+
}

tools/testing/selftests/bpf/prog_tests/snprintf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ static void test_snprintf_negative(void)
116116
ASSERT_ERR(load_single_snprintf("%llc"), "invalid specifier 7");
117117
ASSERT_ERR(load_single_snprintf("\x80"), "non ascii character");
118118
ASSERT_ERR(load_single_snprintf("\x1"), "non printable character");
119+
ASSERT_ERR(load_single_snprintf("%p%"), "invalid specifier 8");
120+
ASSERT_ERR(load_single_snprintf("%s%"), "invalid specifier 9");
119121
}
120122

121123
void test_snprintf(void)

0 commit comments

Comments
 (0)