Skip to content

Commit c7d4274

Browse files
author
Martin KaFai Lau
committed
Merge branch 'bpf: arena prerequisites'
Alexei Starovoitov says: ==================== These are bpf_arena prerequisite patches. Useful on its own. Alexei Starovoitov (5): bpf: Allow kfuncs return 'void *' bpf: Recognize '__map' suffix in kfunc arguments bpf: Plumb get_unmapped_area() callback into bpf_map_ops libbpf: Allow specifying 64-bit integers in map BTF. bpf: Tell bpf programs kernel's PAGE_SIZE ==================== Signed-off-by: Martin KaFai Lau <[email protected]>
2 parents e63985e + fe50641 commit c7d4274

File tree

7 files changed

+96
-12
lines changed

7 files changed

+96
-12
lines changed

include/linux/bpf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ struct bpf_map_ops {
139139
int (*map_mmap)(struct bpf_map *map, struct vm_area_struct *vma);
140140
__poll_t (*map_poll)(struct bpf_map *map, struct file *filp,
141141
struct poll_table_struct *pts);
142+
unsigned long (*map_get_unmapped_area)(struct file *filep, unsigned long addr,
143+
unsigned long len, unsigned long pgoff,
144+
unsigned long flags);
142145

143146
/* Functions called by bpf_local_storage maps */
144147
int (*map_local_storage_charge)(struct bpf_local_storage_map *smap,

kernel/bpf/core.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,18 @@ void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, uns
8888
return NULL;
8989
}
9090

91+
/* tell bpf programs that include vmlinux.h kernel's PAGE_SIZE */
92+
enum page_size_enum {
93+
__PAGE_SIZE = PAGE_SIZE
94+
};
95+
9196
struct bpf_prog *bpf_prog_alloc_no_stats(unsigned int size, gfp_t gfp_extra_flags)
9297
{
9398
gfp_t gfp_flags = bpf_memcg_flags(GFP_KERNEL | __GFP_ZERO | gfp_extra_flags);
9499
struct bpf_prog_aux *aux;
95100
struct bpf_prog *fp;
96101

97-
size = round_up(size, PAGE_SIZE);
102+
size = round_up(size, __PAGE_SIZE);
98103
fp = __vmalloc(size, gfp_flags);
99104
if (fp == NULL)
100105
return NULL;

kernel/bpf/syscall.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,21 @@ static __poll_t bpf_map_poll(struct file *filp, struct poll_table_struct *pts)
937937
return EPOLLERR;
938938
}
939939

940+
static unsigned long bpf_get_unmapped_area(struct file *filp, unsigned long addr,
941+
unsigned long len, unsigned long pgoff,
942+
unsigned long flags)
943+
{
944+
struct bpf_map *map = filp->private_data;
945+
946+
if (map->ops->map_get_unmapped_area)
947+
return map->ops->map_get_unmapped_area(filp, addr, len, pgoff, flags);
948+
#ifdef CONFIG_MMU
949+
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
950+
#else
951+
return addr;
952+
#endif
953+
}
954+
940955
const struct file_operations bpf_map_fops = {
941956
#ifdef CONFIG_PROC_FS
942957
.show_fdinfo = bpf_map_show_fdinfo,
@@ -946,6 +961,7 @@ const struct file_operations bpf_map_fops = {
946961
.write = bpf_dummy_write,
947962
.mmap = bpf_map_mmap,
948963
.poll = bpf_map_poll,
964+
.get_unmapped_area = bpf_get_unmapped_area,
949965
};
950966

951967
int bpf_map_new_fd(struct bpf_map *map, int flags)

kernel/bpf/verifier.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10752,6 +10752,11 @@ static bool is_kfunc_arg_ignore(const struct btf *btf, const struct btf_param *a
1075210752
return btf_param_match_suffix(btf, arg, "__ign");
1075310753
}
1075410754

10755+
static bool is_kfunc_arg_map(const struct btf *btf, const struct btf_param *arg)
10756+
{
10757+
return btf_param_match_suffix(btf, arg, "__map");
10758+
}
10759+
1075510760
static bool is_kfunc_arg_alloc_obj(const struct btf *btf, const struct btf_param *arg)
1075610761
{
1075710762
return btf_param_match_suffix(btf, arg, "__alloc");
@@ -10921,6 +10926,7 @@ enum kfunc_ptr_arg_type {
1092110926
KF_ARG_PTR_TO_RB_NODE,
1092210927
KF_ARG_PTR_TO_NULL,
1092310928
KF_ARG_PTR_TO_CONST_STR,
10929+
KF_ARG_PTR_TO_MAP,
1092410930
};
1092510931

1092610932
enum special_kfunc_type {
@@ -11074,6 +11080,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
1107411080
if (is_kfunc_arg_const_str(meta->btf, &args[argno]))
1107511081
return KF_ARG_PTR_TO_CONST_STR;
1107611082

11083+
if (is_kfunc_arg_map(meta->btf, &args[argno]))
11084+
return KF_ARG_PTR_TO_MAP;
11085+
1107711086
if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) {
1107811087
if (!btf_type_is_struct(ref_t)) {
1107911088
verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n",
@@ -11674,6 +11683,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1167411683
switch (kf_arg_type) {
1167511684
case KF_ARG_PTR_TO_NULL:
1167611685
continue;
11686+
case KF_ARG_PTR_TO_MAP:
1167711687
case KF_ARG_PTR_TO_ALLOC_BTF_ID:
1167811688
case KF_ARG_PTR_TO_BTF_ID:
1167911689
if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta))
@@ -11890,6 +11900,12 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1189011900
if (ret < 0)
1189111901
return ret;
1189211902
break;
11903+
case KF_ARG_PTR_TO_MAP:
11904+
/* If argument has '__map' suffix expect 'struct bpf_map *' */
11905+
ref_id = *reg2btf_ids[CONST_PTR_TO_MAP];
11906+
ref_t = btf_type_by_id(btf_vmlinux, ref_id);
11907+
ref_tname = btf_name_by_offset(btf, ref_t->name_off);
11908+
fallthrough;
1189311909
case KF_ARG_PTR_TO_BTF_ID:
1189411910
/* Only base_type is checked, further checks are done here */
1189511911
if ((base_type(reg->type) != PTR_TO_BTF_ID ||
@@ -12364,6 +12380,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1236412380
meta.func_name);
1236512381
return -EFAULT;
1236612382
}
12383+
} else if (btf_type_is_void(ptr_type)) {
12384+
/* kfunc returning 'void *' is equivalent to returning scalar */
12385+
mark_reg_unknown(env, regs, BPF_REG_0);
1236712386
} else if (!__btf_type_is_struct(ptr_type)) {
1236812387
if (!meta.r0_size) {
1236912388
__u32 sz;

tools/bpf/bpftool/gen.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ static const struct btf_type *find_type_for_map(struct btf *btf, const char *map
248248
return NULL;
249249
}
250250

251-
static bool is_internal_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
251+
static bool is_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
252252
{
253253
if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
254254
return false;
@@ -274,7 +274,7 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
274274

275275
bpf_object__for_each_map(map, obj) {
276276
/* only generate definitions for memory-mapped internal maps */
277-
if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
277+
if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
278278
continue;
279279

280280
sec = find_type_for_map(btf, map_ident);
@@ -327,7 +327,7 @@ static int codegen_subskel_datasecs(struct bpf_object *obj, const char *obj_name
327327

328328
bpf_object__for_each_map(map, obj) {
329329
/* only generate definitions for memory-mapped internal maps */
330-
if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
330+
if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
331331
continue;
332332

333333
sec = find_type_for_map(btf, map_ident);
@@ -504,7 +504,7 @@ static void codegen_asserts(struct bpf_object *obj, const char *obj_name)
504504
", obj_name);
505505

506506
bpf_object__for_each_map(map, obj) {
507-
if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
507+
if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
508508
continue;
509509

510510
sec = find_type_for_map(btf, map_ident);
@@ -720,7 +720,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
720720
const void *mmap_data = NULL;
721721
size_t mmap_size = 0;
722722

723-
if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
723+
if (!is_mmapable_map(map, ident, sizeof(ident)))
724724
continue;
725725

726726
codegen("\
@@ -782,7 +782,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
782782
bpf_object__for_each_map(map, obj) {
783783
const char *mmap_flags;
784784

785-
if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
785+
if (!is_mmapable_map(map, ident, sizeof(ident)))
786786
continue;
787787

788788
if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG)
@@ -871,7 +871,7 @@ codegen_maps_skeleton(struct bpf_object *obj, size_t map_cnt, bool mmaped)
871871
",
872872
i, bpf_map__name(map), i, ident);
873873
/* memory-mapped internal maps */
874-
if (mmaped && is_internal_mmapable_map(map, ident, sizeof(ident))) {
874+
if (mmaped && is_mmapable_map(map, ident, sizeof(ident))) {
875875
printf("\ts->maps[%zu].mmaped = (void **)&obj->%s;\n",
876876
i, ident);
877877
}
@@ -1617,7 +1617,7 @@ static int do_subskeleton(int argc, char **argv)
16171617
/* Also count all maps that have a name */
16181618
map_cnt++;
16191619

1620-
if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
1620+
if (!is_mmapable_map(map, ident, sizeof(ident)))
16211621
continue;
16221622

16231623
map_type_id = bpf_map__btf_value_type_id(map);
@@ -1739,7 +1739,7 @@ static int do_subskeleton(int argc, char **argv)
17391739

17401740
/* walk through each symbol and emit the runtime representation */
17411741
bpf_object__for_each_map(map, obj) {
1742-
if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
1742+
if (!is_mmapable_map(map, ident, sizeof(ident)))
17431743
continue;
17441744

17451745
map_type_id = bpf_map__btf_value_type_id(map);

tools/lib/bpf/bpf_helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define __uint(name, val) int (*name)[val]
1414
#define __type(name, val) typeof(val) *name
1515
#define __array(name, val) typeof(val) *name[]
16+
#define __ulong(name, val) enum { ___bpf_concat(__unique_value, __COUNTER__) = val } name
1617

1718
/*
1819
* Helper macro to place programs, maps, license in

tools/lib/bpf/libbpf.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,46 @@ static bool get_map_field_int(const char *map_name, const struct btf *btf,
23352335
return true;
23362336
}
23372337

2338+
static bool get_map_field_long(const char *map_name, const struct btf *btf,
2339+
const struct btf_member *m, __u64 *res)
2340+
{
2341+
const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL);
2342+
const char *name = btf__name_by_offset(btf, m->name_off);
2343+
2344+
if (btf_is_ptr(t)) {
2345+
__u32 res32;
2346+
bool ret;
2347+
2348+
ret = get_map_field_int(map_name, btf, m, &res32);
2349+
if (ret)
2350+
*res = (__u64)res32;
2351+
return ret;
2352+
}
2353+
2354+
if (!btf_is_enum(t) && !btf_is_enum64(t)) {
2355+
pr_warn("map '%s': attr '%s': expected ENUM or ENUM64, got %s.\n",
2356+
map_name, name, btf_kind_str(t));
2357+
return false;
2358+
}
2359+
2360+
if (btf_vlen(t) != 1) {
2361+
pr_warn("map '%s': attr '%s': invalid __ulong\n",
2362+
map_name, name);
2363+
return false;
2364+
}
2365+
2366+
if (btf_is_enum(t)) {
2367+
const struct btf_enum *e = btf_enum(t);
2368+
2369+
*res = e->val;
2370+
} else {
2371+
const struct btf_enum64 *e = btf_enum64(t);
2372+
2373+
*res = btf_enum64_value(e);
2374+
}
2375+
return true;
2376+
}
2377+
23382378
static int pathname_concat(char *buf, size_t buf_sz, const char *path, const char *name)
23392379
{
23402380
int len;
@@ -2568,9 +2608,9 @@ int parse_btf_map_def(const char *map_name, struct btf *btf,
25682608
map_def->pinning = val;
25692609
map_def->parts |= MAP_DEF_PINNING;
25702610
} else if (strcmp(name, "map_extra") == 0) {
2571-
__u32 map_extra;
2611+
__u64 map_extra;
25722612

2573-
if (!get_map_field_int(map_name, btf, m, &map_extra))
2613+
if (!get_map_field_long(map_name, btf, m, &map_extra))
25742614
return -EINVAL;
25752615
map_def->map_extra = map_extra;
25762616
map_def->parts |= MAP_DEF_MAP_EXTRA;

0 commit comments

Comments
 (0)