Skip to content

Commit 9225587

Browse files
borkmannsmb49
authored andcommitted
bpf: Fix ringbuf memory type confusion when passing to helpers
BugLink: https://bugs.launchpad.net/bugs/2067959 commit a672b2e upstream. The bpf_ringbuf_submit() and bpf_ringbuf_discard() have ARG_PTR_TO_ALLOC_MEM in their bpf_func_proto definition as their first argument, and thus both expect the result from a prior bpf_ringbuf_reserve() call which has a return type of RET_PTR_TO_ALLOC_MEM_OR_NULL. While the non-NULL memory from bpf_ringbuf_reserve() can be passed to other helpers, the two sinks (bpf_ringbuf_submit(), bpf_ringbuf_discard()) right now only enforce a register type of PTR_TO_MEM. This can lead to potential type confusion since it would allow other PTR_TO_MEM memory to be passed into the two sinks which did not come from bpf_ringbuf_reserve(). Add a new MEM_ALLOC composable type attribute for PTR_TO_MEM, and enforce that: - bpf_ringbuf_reserve() returns NULL or PTR_TO_MEM | MEM_ALLOC - bpf_ringbuf_submit() and bpf_ringbuf_discard() only take PTR_TO_MEM | MEM_ALLOC but not plain PTR_TO_MEM arguments via ARG_PTR_TO_ALLOC_MEM - however, other helpers might treat PTR_TO_MEM | MEM_ALLOC as plain PTR_TO_MEM to populate the memory area when they use ARG_PTR_TO_{UNINIT_,}MEM in their func proto description Fixes: 457f443 ("bpf: Implement BPF ring buffer and verifier support for it") Reported-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: John Fastabend <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: Edward Liaw <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Portia Stephens <[email protected]> Signed-off-by: Stefan Bader <[email protected]>
1 parent 6945ebf commit 9225587

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

include/linux/bpf.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,12 @@ enum bpf_type_flag {
321321
*/
322322
MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS),
323323

324-
__BPF_TYPE_LAST_FLAG = MEM_RDONLY,
324+
/* MEM was "allocated" from a different helper, and cannot be mixed
325+
* with regular non-MEM_ALLOC'ed MEM types.
326+
*/
327+
MEM_ALLOC = BIT(2 + BPF_BASE_TYPE_BITS),
328+
329+
__BPF_TYPE_LAST_FLAG = MEM_ALLOC,
325330
};
326331

327332
/* Max number of base types. */
@@ -405,7 +410,7 @@ enum bpf_return_type {
405410
RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET,
406411
RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK,
407412
RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON,
408-
RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_ALLOC_MEM,
413+
RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | MEM_ALLOC | RET_PTR_TO_ALLOC_MEM,
409414
RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID,
410415

411416
/* This must be the last entry. Its purpose is to ensure the enum is

kernel/bpf/verifier.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,8 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
573573

574574
if (type & MEM_RDONLY)
575575
strncpy(prefix, "rdonly_", 16);
576+
if (type & MEM_ALLOC)
577+
strncpy(prefix, "alloc_", 16);
576578

577579
snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s",
578580
prefix, str[base_type(type)], postfix);
@@ -5157,6 +5159,7 @@ static const struct bpf_reg_types mem_types = {
51575159
PTR_TO_MAP_KEY,
51585160
PTR_TO_MAP_VALUE,
51595161
PTR_TO_MEM,
5162+
PTR_TO_MEM | MEM_ALLOC,
51605163
PTR_TO_BUF,
51615164
},
51625165
};
@@ -5174,7 +5177,7 @@ static const struct bpf_reg_types int_ptr_types = {
51745177
static const struct bpf_reg_types fullsock_types = { .types = { PTR_TO_SOCKET } };
51755178
static const struct bpf_reg_types scalar_types = { .types = { SCALAR_VALUE } };
51765179
static const struct bpf_reg_types context_types = { .types = { PTR_TO_CTX } };
5177-
static const struct bpf_reg_types alloc_mem_types = { .types = { PTR_TO_MEM } };
5180+
static const struct bpf_reg_types alloc_mem_types = { .types = { PTR_TO_MEM | MEM_ALLOC } };
51785181
static const struct bpf_reg_types const_map_ptr_types = { .types = { CONST_PTR_TO_MAP } };
51795182
static const struct bpf_reg_types btf_ptr_types = { .types = { PTR_TO_BTF_ID } };
51805183
static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALUE } };
@@ -5345,6 +5348,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
53455348
case PTR_TO_MAP_VALUE:
53465349
case PTR_TO_MEM:
53475350
case PTR_TO_MEM | MEM_RDONLY:
5351+
case PTR_TO_MEM | MEM_ALLOC:
53485352
case PTR_TO_BUF:
53495353
case PTR_TO_BUF | MEM_RDONLY:
53505354
case PTR_TO_STACK:

0 commit comments

Comments
 (0)