bpf: perf_event progs should only use preallocated maps
Make sure that BPF_PROG_TYPE_PERF_EVENT programs only use preallocated hash maps, since doing memory allocation in overflow_handler can crash depending on where nmi got triggered. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0515e5999a
commit
fdc15d388d
kernel/bpf
|
@ -2511,6 +2511,20 @@ process_bpf_exit:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_map_prog_compatibility(struct bpf_map *map,
|
||||||
|
struct bpf_prog *prog)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (prog->type == BPF_PROG_TYPE_PERF_EVENT &&
|
||||||
|
(map->map_type == BPF_MAP_TYPE_HASH ||
|
||||||
|
map->map_type == BPF_MAP_TYPE_PERCPU_HASH) &&
|
||||||
|
(map->map_flags & BPF_F_NO_PREALLOC)) {
|
||||||
|
verbose("perf_event programs can only use preallocated hash map\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* look for pseudo eBPF instructions that access map FDs and
|
/* look for pseudo eBPF instructions that access map FDs and
|
||||||
* replace them with actual map pointers
|
* replace them with actual map pointers
|
||||||
*/
|
*/
|
||||||
|
@ -2518,7 +2532,7 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
|
||||||
{
|
{
|
||||||
struct bpf_insn *insn = env->prog->insnsi;
|
struct bpf_insn *insn = env->prog->insnsi;
|
||||||
int insn_cnt = env->prog->len;
|
int insn_cnt = env->prog->len;
|
||||||
int i, j;
|
int i, j, err;
|
||||||
|
|
||||||
for (i = 0; i < insn_cnt; i++, insn++) {
|
for (i = 0; i < insn_cnt; i++, insn++) {
|
||||||
if (BPF_CLASS(insn->code) == BPF_LDX &&
|
if (BPF_CLASS(insn->code) == BPF_LDX &&
|
||||||
|
@ -2562,6 +2576,12 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
|
||||||
return PTR_ERR(map);
|
return PTR_ERR(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = check_map_prog_compatibility(map, env->prog);
|
||||||
|
if (err) {
|
||||||
|
fdput(f);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* store map pointer inside BPF_LD_IMM64 instruction */
|
/* store map pointer inside BPF_LD_IMM64 instruction */
|
||||||
insn[0].imm = (u32) (unsigned long) map;
|
insn[0].imm = (u32) (unsigned long) map;
|
||||||
insn[1].imm = ((u64) (unsigned long) map) >> 32;
|
insn[1].imm = ((u64) (unsigned long) map) >> 32;
|
||||||
|
|
Loading…
Reference in New Issue