Skip to content

Commit a31b8cf

Browse files
AsphalttKernel Patches Daemon
authored andcommitted
bpf: Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags
Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags and check them for following APIs: * 'map_lookup_elem()' * 'map_update_elem()' * 'generic_map_lookup_batch()' * 'generic_map_update_batch()' And, get the correct value size for these APIs. Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Leon Hwang <[email protected]>
1 parent 2d3ee75 commit a31b8cf

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

include/linux/bpf.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3768,14 +3768,35 @@ int bpf_prog_get_file_line(struct bpf_prog *prog, unsigned long ip, const char *
37683768
const char **linep, int *nump);
37693769
struct bpf_prog *bpf_prog_find_from_stack(void);
37703770

3771+
static inline bool bpf_map_supports_cpu_flags(enum bpf_map_type map_type)
3772+
{
3773+
return false;
3774+
}
3775+
37713776
static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 allowed_flags)
37723777
{
3773-
if (flags & ~allowed_flags)
3778+
u32 cpu;
3779+
3780+
if ((u32)flags & ~allowed_flags)
37743781
return -EINVAL;
37753782

37763783
if ((flags & BPF_F_LOCK) && !btf_record_has_field(map->record, BPF_SPIN_LOCK))
37773784
return -EINVAL;
37783785

3786+
if (!(flags & BPF_F_CPU) && flags >> 32)
3787+
return -EINVAL;
3788+
3789+
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS)) {
3790+
if (!bpf_map_supports_cpu_flags(map->map_type))
3791+
return -EINVAL;
3792+
if ((flags & BPF_F_CPU) && (flags & BPF_F_ALL_CPUS))
3793+
return -EINVAL;
3794+
3795+
cpu = flags >> 32;
3796+
if ((flags & BPF_F_CPU) && cpu >= num_possible_cpus())
3797+
return -ERANGE;
3798+
}
3799+
37793800
return 0;
37803801
}
37813802

include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,8 @@ enum {
13721372
BPF_NOEXIST = 1, /* create new element if it didn't exist */
13731373
BPF_EXIST = 2, /* update existing element */
13741374
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
1375+
BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
1376+
BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
13751377
};
13761378

13771379
/* flags for BPF_MAP_CREATE command */

kernel/bpf/syscall.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ bool bpf_map_write_active(const struct bpf_map *map)
133133
return atomic64_read(&map->writecnt) != 0;
134134
}
135135

136-
static u32 bpf_map_value_size(const struct bpf_map *map)
137-
{
138-
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
139-
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
140-
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
141-
map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
136+
static u32 bpf_map_value_size(const struct bpf_map *map, u64 flags)
137+
{
138+
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS))
139+
return round_up(map->value_size, 8);
140+
else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
141+
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
142+
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
143+
map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
142144
return round_up(map->value_size, 8) * num_possible_cpus();
143145
else if (IS_FD_MAP(map))
144146
return sizeof(u32);
@@ -1715,15 +1717,15 @@ static int map_lookup_elem(union bpf_attr *attr)
17151717
if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ))
17161718
return -EPERM;
17171719

1718-
err = bpf_map_check_op_flags(map, attr->flags, BPF_F_LOCK);
1720+
err = bpf_map_check_op_flags(map, attr->flags, BPF_F_LOCK | BPF_F_CPU);
17191721
if (err)
17201722
return err;
17211723

17221724
key = __bpf_copy_key(ukey, map->key_size);
17231725
if (IS_ERR(key))
17241726
return PTR_ERR(key);
17251727

1726-
value_size = bpf_map_value_size(map);
1728+
value_size = bpf_map_value_size(map, attr->flags);
17271729

17281730
err = -ENOMEM;
17291731
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
@@ -1790,7 +1792,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
17901792
goto err_put;
17911793
}
17921794

1793-
value_size = bpf_map_value_size(map);
1795+
value_size = bpf_map_value_size(map, attr->flags);
17941796
value = kvmemdup_bpfptr(uvalue, value_size);
17951797
if (IS_ERR(value)) {
17961798
err = PTR_ERR(value);
@@ -1986,11 +1988,12 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,
19861988
void *key, *value;
19871989
int err = 0;
19881990

1989-
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK);
1991+
err = bpf_map_check_op_flags(map, attr->batch.elem_flags,
1992+
BPF_F_LOCK | BPF_F_CPU | BPF_F_ALL_CPUS);
19901993
if (err)
19911994
return err;
19921995

1993-
value_size = bpf_map_value_size(map);
1996+
value_size = bpf_map_value_size(map, attr->batch.elem_flags);
19941997

19951998
max_count = attr->batch.count;
19961999
if (!max_count)
@@ -2045,11 +2048,11 @@ int generic_map_lookup_batch(struct bpf_map *map,
20452048
u32 value_size, cp, max_count;
20462049
int err;
20472050

2048-
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK);
2051+
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK | BPF_F_CPU);
20492052
if (err)
20502053
return err;
20512054

2052-
value_size = bpf_map_value_size(map);
2055+
value_size = bpf_map_value_size(map, attr->batch.elem_flags);
20532056

20542057
max_count = attr->batch.count;
20552058
if (!max_count)
@@ -2171,7 +2174,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
21712174
goto err_put;
21722175
}
21732176

2174-
value_size = bpf_map_value_size(map);
2177+
value_size = bpf_map_value_size(map, 0);
21752178

21762179
err = -ENOMEM;
21772180
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);

tools/include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,8 @@ enum {
13721372
BPF_NOEXIST = 1, /* create new element if it didn't exist */
13731373
BPF_EXIST = 2, /* update existing element */
13741374
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
1375+
BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
1376+
BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
13751377
};
13761378

13771379
/* flags for BPF_MAP_CREATE command */

0 commit comments

Comments
 (0)