Skip to content

Commit d433b3f

Browse files
committed
Merge branch 'libbpf-support-more-map-options'
Craig Gallek says: ==================== libbpf: support more map options The functional change to this series is the ability to use flags when creating maps from object files loaded by libbpf. In order to do this, the first patch updates the library to handle map definitions that differ in size from libbpf's struct bpf_map_def. For object files with a larger map definition, libbpf will continue to load if the unknown fields are all zero, otherwise the map is rejected. If the map definition in the object file is smaller than expected, libbpf will use zero as a default value in the missing fields. ==================== Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents d009313 + fe9b5f7 commit d433b3f

File tree

2 files changed

+43
-30
lines changed

2 files changed

+43
-30
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -579,31 +579,6 @@ bpf_object__init_kversion(struct bpf_object *obj,
579579
return 0;
580580
}
581581

582-
static int
583-
bpf_object__validate_maps(struct bpf_object *obj)
584-
{
585-
int i;
586-
587-
/*
588-
* If there's only 1 map, the only error case should have been
589-
* catched in bpf_object__init_maps().
590-
*/
591-
if (!obj->maps || !obj->nr_maps || (obj->nr_maps == 1))
592-
return 0;
593-
594-
for (i = 1; i < obj->nr_maps; i++) {
595-
const struct bpf_map *a = &obj->maps[i - 1];
596-
const struct bpf_map *b = &obj->maps[i];
597-
598-
if (b->offset - a->offset < sizeof(struct bpf_map_def)) {
599-
pr_warning("corrupted map section in %s: map \"%s\" too small\n",
600-
obj->path, a->name);
601-
return -EINVAL;
602-
}
603-
}
604-
return 0;
605-
}
606-
607582
static int compare_bpf_map(const void *_a, const void *_b)
608583
{
609584
const struct bpf_map *a = _a;
@@ -615,7 +590,7 @@ static int compare_bpf_map(const void *_a, const void *_b)
615590
static int
616591
bpf_object__init_maps(struct bpf_object *obj)
617592
{
618-
int i, map_idx, nr_maps = 0;
593+
int i, map_idx, map_def_sz, nr_maps = 0;
619594
Elf_Scn *scn;
620595
Elf_Data *data;
621596
Elf_Data *symbols = obj->efile.symbols;
@@ -658,6 +633,15 @@ bpf_object__init_maps(struct bpf_object *obj)
658633
if (!nr_maps)
659634
return 0;
660635

636+
/* Assume equally sized map definitions */
637+
map_def_sz = data->d_size / nr_maps;
638+
if (!data->d_size || (data->d_size % nr_maps) != 0) {
639+
pr_warning("unable to determine map definition size "
640+
"section %s, %d maps in %zd bytes\n",
641+
obj->path, nr_maps, data->d_size);
642+
return -EINVAL;
643+
}
644+
661645
obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
662646
if (!obj->maps) {
663647
pr_warning("alloc maps for object failed\n");
@@ -690,7 +674,7 @@ bpf_object__init_maps(struct bpf_object *obj)
690674
obj->efile.strtabidx,
691675
sym.st_name);
692676
obj->maps[map_idx].offset = sym.st_value;
693-
if (sym.st_value + sizeof(struct bpf_map_def) > data->d_size) {
677+
if (sym.st_value + map_def_sz > data->d_size) {
694678
pr_warning("corrupted maps section in %s: last map \"%s\" too small\n",
695679
obj->path, map_name);
696680
return -EINVAL;
@@ -704,12 +688,40 @@ bpf_object__init_maps(struct bpf_object *obj)
704688
pr_debug("map %d is \"%s\"\n", map_idx,
705689
obj->maps[map_idx].name);
706690
def = (struct bpf_map_def *)(data->d_buf + sym.st_value);
707-
obj->maps[map_idx].def = *def;
691+
/*
692+
* If the definition of the map in the object file fits in
693+
* bpf_map_def, copy it. Any extra fields in our version
694+
* of bpf_map_def will default to zero as a result of the
695+
* calloc above.
696+
*/
697+
if (map_def_sz <= sizeof(struct bpf_map_def)) {
698+
memcpy(&obj->maps[map_idx].def, def, map_def_sz);
699+
} else {
700+
/*
701+
* Here the map structure being read is bigger than what
702+
* we expect, truncate if the excess bits are all zero.
703+
* If they are not zero, reject this map as
704+
* incompatible.
705+
*/
706+
char *b;
707+
for (b = ((char *)def) + sizeof(struct bpf_map_def);
708+
b < ((char *)def) + map_def_sz; b++) {
709+
if (*b != 0) {
710+
pr_warning("maps section in %s: \"%s\" "
711+
"has unrecognized, non-zero "
712+
"options\n",
713+
obj->path, map_name);
714+
return -EINVAL;
715+
}
716+
}
717+
memcpy(&obj->maps[map_idx].def, def,
718+
sizeof(struct bpf_map_def));
719+
}
708720
map_idx++;
709721
}
710722

711723
qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), compare_bpf_map);
712-
return bpf_object__validate_maps(obj);
724+
return 0;
713725
}
714726

715727
static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -930,7 +942,7 @@ bpf_object__create_maps(struct bpf_object *obj)
930942
def->key_size,
931943
def->value_size,
932944
def->max_entries,
933-
0);
945+
def->map_flags);
934946
if (*pfd < 0) {
935947
size_t j;
936948
int err = *pfd;

tools/lib/bpf/libbpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ struct bpf_map_def {
207207
unsigned int key_size;
208208
unsigned int value_size;
209209
unsigned int max_entries;
210+
unsigned int map_flags;
210211
};
211212

212213
/*

0 commit comments

Comments
 (0)