Skip to content

Commit e442290

Browse files
florianlkernel-patches-bot
authored andcommitted
bpf: Lift hashtab key_size limit
Currently key_size of hashtab is limited to MAX_BPF_STACK. As the key of hashtab can also be a value from a per cpu map it can be larger than MAX_BPF_STACK. The use-case for this patch originates to implement allow/disallow lists for files and file paths. The maximum length of file paths is defined by PATH_MAX with 4096 chars including nul. This limit exceeds MAX_BPF_STACK. Changelog: v3: - Rebase v2: - Add a test for bpf side Signed-off-by: Florian Lehner <[email protected]>
1 parent 559cce3 commit e442290

File tree

4 files changed

+79
-12
lines changed

4 files changed

+79
-12
lines changed

kernel/bpf/hashtab.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -390,17 +390,11 @@ static int htab_map_alloc_check(union bpf_attr *attr)
390390
attr->value_size == 0)
391391
return -EINVAL;
392392

393-
if (attr->key_size > MAX_BPF_STACK)
394-
/* eBPF programs initialize keys on stack, so they cannot be
395-
* larger than max stack size
396-
*/
397-
return -E2BIG;
398-
399-
if (attr->value_size >= KMALLOC_MAX_SIZE -
400-
MAX_BPF_STACK - sizeof(struct htab_elem))
401-
/* if value_size is bigger, the user space won't be able to
402-
* access the elements via bpf syscall. This check also makes
403-
* sure that the elem_size doesn't overflow and it's
393+
if ((attr->key_size + attr->value_size) >= KMALLOC_MAX_SIZE -
394+
sizeof(struct htab_elem))
395+
/* if key_size + value_size is bigger, the user space won't be
396+
* able to access the elements via bpf syscall. This check
397+
* also makes sure that the elem_size doesn't overflow and it's
404398
* kmalloc-able later in htab_map_update_elem()
405399
*/
406400
return -E2BIG;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2020 Florian Lehner
3+
4+
#include <test_progs.h>
5+
6+
void test_hash_large_key(void)
7+
{
8+
const char *file = "./test_hash_large_key.o";
9+
int prog_fd, map_fd[2];
10+
struct bpf_object *obj = NULL;
11+
int err = 0;
12+
13+
err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
14+
if (CHECK_FAIL(err)) {
15+
printf("test_hash_large_key: bpf_prog_load errno %d", errno);
16+
goto close_prog;
17+
}
18+
19+
map_fd[0] = bpf_find_map(__func__, obj, "hash_map");
20+
if (CHECK_FAIL(map_fd[0] < 0))
21+
goto close_prog;
22+
map_fd[1] = bpf_find_map(__func__, obj, "key_map");
23+
if (CHECK_FAIL(map_fd[1] < 0))
24+
goto close_prog;
25+
26+
close_prog:
27+
bpf_object__close(obj);
28+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2020 Florian Lehner
3+
4+
#include <linux/bpf.h>
5+
#include <linux/version.h>
6+
#include <bpf/bpf_helpers.h>
7+
8+
struct bigelement {
9+
int a;
10+
char b[4096];
11+
long long c;
12+
};
13+
14+
struct {
15+
__uint(type, BPF_MAP_TYPE_HASH);
16+
__uint(max_entries, 1);
17+
__type(key, struct bigelement);
18+
__type(value, __u32);
19+
} hash_map SEC(".maps");
20+
21+
struct {
22+
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
23+
__uint(max_entries, 1);
24+
__type(key, __u32);
25+
__type(value, struct bigelement);
26+
} key_map SEC(".maps");
27+
28+
SEC("hash_large_key_demo")
29+
int bpf_hash_large_key_test(struct __sk_buf *skb)
30+
{
31+
int zero = 0, err = 1, value = 42;
32+
struct bigelement *key;
33+
34+
key = bpf_map_lookup_elem(&key_map, &zero);
35+
if (!key)
36+
goto err;
37+
38+
if (bpf_map_update_elem(&hash_map, key, &value, BPF_ANY))
39+
goto err;
40+
err = 0;
41+
err:
42+
return err;
43+
}
44+
45+
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/test_maps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ static void test_map_large(void)
12251225
{
12261226
struct bigkey {
12271227
int a;
1228-
char b[116];
1228+
char b[4096];
12291229
long long c;
12301230
} key;
12311231
int fd, i, value;

0 commit comments

Comments
 (0)