Skip to content

Commit

Permalink
Merge branch 'unsupported-map-lookup'
Browse files Browse the repository at this point in the history
Prashant Bhole says:

====================
Currently when map a lookup fails, user space API can not make any
distinction whether given key was not found or lookup is not supported
by particular map.

In this series we modify return value of maps which do not support
lookup. Lookup on such map implementation will return -EOPNOTSUPP.
bpf() syscall with BPF_MAP_LOOKUP_ELEM command will set EOPNOTSUPP
errno. We also handle this error in bpftool to print appropriate
message.

Patch 1: adds handling of BPF_MAP_LOOKUP ELEM command of bpf syscall
such that errno will set to EOPNOTSUPP when map doesn't support lookup

Patch 2: Modifies the return value of map_lookup_elem() to EOPNOTSUPP
for maps which do not support lookup

Patch 3: Splits do_dump() in bpftool/map.c. Element printing code is
moved out into new function dump_map_elem(). This was done in order to
reduce deep indentation and accomodate further changes.

Patch 4: Changes in bpftool to print strerror() message when lookup
error is occured. This will result in appropriate message like
"Operation not supported" when map doesn't support lookup.

Patch 5: test_verifier: change fixup map naming convention as
suggested by Alexei

Patch 6: Added verifier tests to check whether verifier rejects call
to bpf_map_lookup_elem from bpf program. For all map types those
do not support map lookup.
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
  • Loading branch information
Alexei Starovoitov committed Oct 10, 2018
2 parents 8af03d1 + 7c85c44 commit e0aa5cf
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 231 deletions.
2 changes: 1 addition & 1 deletion kernel/bpf/arraymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ static void fd_array_map_free(struct bpf_map *map)

static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
{
return NULL;
return ERR_PTR(-EOPNOTSUPP);
}

/* only called from syscall */
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/sockmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2096,7 +2096,7 @@ int sockmap_get_from_fd(const union bpf_attr *attr, int type,

static void *sock_map_lookup(struct bpf_map *map, void *key)
{
return NULL;
return ERR_PTR(-EOPNOTSUPP);
}

static int sock_map_update_elem(struct bpf_map *map,
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/stackmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ const struct bpf_func_proto bpf_get_stack_proto = {
/* Called from eBPF program */
static void *stack_map_lookup_elem(struct bpf_map *map, void *key)
{
return NULL;
return ERR_PTR(-EOPNOTSUPP);
}

/* Called from syscall */
Expand Down
9 changes: 7 additions & 2 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,10 +719,15 @@ static int map_lookup_elem(union bpf_attr *attr)
} else {
rcu_read_lock();
ptr = map->ops->map_lookup_elem(map, key);
if (ptr)
if (IS_ERR(ptr)) {
err = PTR_ERR(ptr);
} else if (!ptr) {
err = -ENOENT;
} else {
err = 0;
memcpy(value, ptr, value_size);
}
rcu_read_unlock();
err = ptr ? 0 : -ENOENT;
}

if (err)
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/xskmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void __xsk_map_flush(struct bpf_map *map)

static void *xsk_map_lookup_elem(struct bpf_map *map, void *key)
{
return NULL;
return ERR_PTR(-EOPNOTSUPP);
}

static int xsk_map_update_elem(struct bpf_map *map, void *key, void *value,
Expand Down
102 changes: 68 additions & 34 deletions tools/bpf/bpftool/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,25 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
jsonw_end_object(json_wtr);
}

static void print_entry_error(struct bpf_map_info *info, unsigned char *key,
const char *value)
{
int value_size = strlen(value);
bool single_line, break_names;

break_names = info->key_size > 16 || value_size > 16;
single_line = info->key_size + value_size <= 24 && !break_names;

printf("key:%c", break_names ? '\n' : ' ');
fprint_hex(stdout, key, info->key_size, " ");

printf(single_line ? " " : "\n");

printf("value:%c%s", break_names ? '\n' : ' ', value);

printf("\n");
}

static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
unsigned char *value)
{
Expand Down Expand Up @@ -658,6 +677,54 @@ static int do_show(int argc, char **argv)
return errno == ENOENT ? 0 : -1;
}

static int dump_map_elem(int fd, void *key, void *value,
struct bpf_map_info *map_info, struct btf *btf,
json_writer_t *btf_wtr)
{
int num_elems = 0;
int lookup_errno;

if (!bpf_map_lookup_elem(fd, key, value)) {
if (json_output) {
print_entry_json(map_info, key, value, btf);
} else {
if (btf) {
struct btf_dumper d = {
.btf = btf,
.jw = btf_wtr,
.is_plain_text = true,
};

do_dump_btf(&d, map_info, key, value);
} else {
print_entry_plain(map_info, key, value);
}
num_elems++;
}
return num_elems;
}

/* lookup error handling */
lookup_errno = errno;

if (map_is_map_of_maps(map_info->type) ||
map_is_map_of_progs(map_info->type))
return 0;

if (json_output) {
jsonw_name(json_wtr, "key");
print_hex_data_json(key, map_info->key_size);
jsonw_name(json_wtr, "value");
jsonw_start_object(json_wtr);
jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
jsonw_end_object(json_wtr);
} else {
print_entry_error(map_info, key, strerror(lookup_errno));
}

return 0;
}

static int do_dump(int argc, char **argv)
{
struct bpf_map_info info = {};
Expand Down Expand Up @@ -713,40 +780,7 @@ static int do_dump(int argc, char **argv)
err = 0;
break;
}

if (!bpf_map_lookup_elem(fd, key, value)) {
if (json_output)
print_entry_json(&info, key, value, btf);
else
if (btf) {
struct btf_dumper d = {
.btf = btf,
.jw = btf_wtr,
.is_plain_text = true,
};

do_dump_btf(&d, &info, key, value);
} else {
print_entry_plain(&info, key, value);
}
num_elems++;
} else if (!map_is_map_of_maps(info.type) &&
!map_is_map_of_progs(info.type)) {
if (json_output) {
jsonw_name(json_wtr, "key");
print_hex_data_json(key, info.key_size);
jsonw_name(json_wtr, "value");
jsonw_start_object(json_wtr);
jsonw_string_field(json_wtr, "error",
"can't lookup element");
jsonw_end_object(json_wtr);
} else {
p_info("can't lookup element with key: ");
fprint_hex(stderr, key, info.key_size, " ");
fprintf(stderr, "\n");
}
}

num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr);
prev_key = key;
}

Expand Down
Loading

0 comments on commit e0aa5cf

Please sign in to comment.