Commit 958b4cd8 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says:

====================
pull-request: bpf 2018-07-28

The following pull-request contains BPF updates for your *net* tree.

The main changes are:

1) API fixes for libbpf's BTF mapping of map key/value types in order
   to make them compatible with iproute2's BPF_ANNOTATE_KV_PAIR()
   markings, from Martin.

2) Fix AF_XDP to not report POLLIN prematurely by using the non-cached
   consumer pointer of the RX queue, from Björn.

3) Fix __xdp_return() to check for NULL pointer after the rhashtable
   lookup that retrieves the allocator object, from Taehee.

4) Fix x86-32 JIT to adjust ebp register in prologue and epilogue
   by 4 bytes which got removed from overall stack usage, from Wang.

5) Fix bpf_skb_load_bytes_relative() length check to use actual
   packet length, from Daniel.

6) Fix uninitialized return code in libbpf bpf_perf_event_read_simple()
   handler, from Thomas.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b0753408 71eb5255
...@@ -1441,8 +1441,8 @@ static void emit_prologue(u8 **pprog, u32 stack_depth) ...@@ -1441,8 +1441,8 @@ static void emit_prologue(u8 **pprog, u32 stack_depth)
/* sub esp,STACK_SIZE */ /* sub esp,STACK_SIZE */
EMIT2_off32(0x81, 0xEC, STACK_SIZE); EMIT2_off32(0x81, 0xEC, STACK_SIZE);
/* sub ebp,SCRATCH_SIZE+4+12*/ /* sub ebp,SCRATCH_SIZE+12*/
EMIT3(0x83, add_1reg(0xE8, IA32_EBP), SCRATCH_SIZE + 16); EMIT3(0x83, add_1reg(0xE8, IA32_EBP), SCRATCH_SIZE + 12);
/* xor ebx,ebx */ /* xor ebx,ebx */
EMIT2(0x31, add_2reg(0xC0, IA32_EBX, IA32_EBX)); EMIT2(0x31, add_2reg(0xC0, IA32_EBX, IA32_EBX));
...@@ -1475,8 +1475,8 @@ static void emit_epilogue(u8 **pprog, u32 stack_depth) ...@@ -1475,8 +1475,8 @@ static void emit_epilogue(u8 **pprog, u32 stack_depth)
/* mov edx,dword ptr [ebp+off]*/ /* mov edx,dword ptr [ebp+off]*/
EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), STACK_VAR(r0[1])); EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), STACK_VAR(r0[1]));
/* add ebp,SCRATCH_SIZE+4+12*/ /* add ebp,SCRATCH_SIZE+12*/
EMIT3(0x83, add_1reg(0xC0, IA32_EBP), SCRATCH_SIZE + 16); EMIT3(0x83, add_1reg(0xC0, IA32_EBP), SCRATCH_SIZE + 12);
/* mov ebx,dword ptr [ebp-12]*/ /* mov ebx,dword ptr [ebp-12]*/
EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), -12); EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), -12);
......
...@@ -378,7 +378,7 @@ static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf, ...@@ -378,7 +378,7 @@ static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
return -EINVAL; return -EINVAL;
value_type = btf_type_id_size(btf, &btf_value_id, &value_size); value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
if (!value_type || value_size > map->value_size) if (!value_type || value_size != map->value_size)
return -EINVAL; return -EINVAL;
return 0; return 0;
......
...@@ -1519,9 +1519,9 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, ...@@ -1519,9 +1519,9 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
{ {
bool is_union = BTF_INFO_KIND(t->info) == BTF_KIND_UNION; bool is_union = BTF_INFO_KIND(t->info) == BTF_KIND_UNION;
const struct btf_member *member; const struct btf_member *member;
u32 meta_needed, last_offset;
struct btf *btf = env->btf; struct btf *btf = env->btf;
u32 struct_size = t->size; u32 struct_size = t->size;
u32 meta_needed;
u16 i; u16 i;
meta_needed = btf_type_vlen(t) * sizeof(*member); meta_needed = btf_type_vlen(t) * sizeof(*member);
...@@ -1534,6 +1534,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, ...@@ -1534,6 +1534,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
btf_verifier_log_type(env, t, NULL); btf_verifier_log_type(env, t, NULL);
last_offset = 0;
for_each_member(i, t, member) { for_each_member(i, t, member) {
if (!btf_name_offset_valid(btf, member->name_off)) { if (!btf_name_offset_valid(btf, member->name_off)) {
btf_verifier_log_member(env, t, member, btf_verifier_log_member(env, t, member,
...@@ -1555,6 +1556,16 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, ...@@ -1555,6 +1556,16 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
return -EINVAL; return -EINVAL;
} }
/*
* ">" instead of ">=" because the last member could be
* "char a[0];"
*/
if (last_offset > member->offset) {
btf_verifier_log_member(env, t, member,
"Invalid member bits_offset");
return -EINVAL;
}
if (BITS_ROUNDUP_BYTES(member->offset) > struct_size) { if (BITS_ROUNDUP_BYTES(member->offset) > struct_size) {
btf_verifier_log_member(env, t, member, btf_verifier_log_member(env, t, member,
"Memmber bits_offset exceeds its struct size"); "Memmber bits_offset exceeds its struct size");
...@@ -1562,6 +1573,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, ...@@ -1562,6 +1573,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
} }
btf_verifier_log_member(env, t, member, NULL); btf_verifier_log_member(env, t, member, NULL);
last_offset = member->offset;
} }
return meta_needed; return meta_needed;
......
...@@ -1712,24 +1712,26 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = { ...@@ -1712,24 +1712,26 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = {
BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb, BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb,
u32, offset, void *, to, u32, len, u32, start_header) u32, offset, void *, to, u32, len, u32, start_header)
{ {
u8 *end = skb_tail_pointer(skb);
u8 *net = skb_network_header(skb);
u8 *mac = skb_mac_header(skb);
u8 *ptr; u8 *ptr;
if (unlikely(offset > 0xffff || len > skb_headlen(skb))) if (unlikely(offset > 0xffff || len > (end - mac)))
goto err_clear; goto err_clear;
switch (start_header) { switch (start_header) {
case BPF_HDR_START_MAC: case BPF_HDR_START_MAC:
ptr = skb_mac_header(skb) + offset; ptr = mac + offset;
break; break;
case BPF_HDR_START_NET: case BPF_HDR_START_NET:
ptr = skb_network_header(skb) + offset; ptr = net + offset;
break; break;
default: default:
goto err_clear; goto err_clear;
} }
if (likely(ptr >= skb_mac_header(skb) && if (likely(ptr >= mac && ptr + len <= end)) {
ptr + len <= skb_tail_pointer(skb))) {
memcpy(to, ptr, len); memcpy(to, ptr, len);
return 0; return 0;
} }
......
...@@ -217,7 +217,7 @@ static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog, ...@@ -217,7 +217,7 @@ static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog,
if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME]) if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME])
return -EINVAL; return -EINVAL;
prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_KERNEL); prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_ATOMIC);
if (!prog->name) if (!prog->name)
return -ENOMEM; return -ENOMEM;
......
...@@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct, ...@@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
rcu_read_lock(); rcu_read_lock();
/* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */ /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params); xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
xa->zc_alloc->free(xa->zc_alloc, handle); if (!WARN_ON_ONCE(!xa))
xa->zc_alloc->free(xa->zc_alloc, handle);
rcu_read_unlock(); rcu_read_unlock();
default: default:
/* Not possible, checked in xdp_rxq_info_reg_mem_model() */ /* Not possible, checked in xdp_rxq_info_reg_mem_model() */
......
...@@ -250,7 +250,7 @@ static inline bool xskq_full_desc(struct xsk_queue *q) ...@@ -250,7 +250,7 @@ static inline bool xskq_full_desc(struct xsk_queue *q)
static inline bool xskq_empty_desc(struct xsk_queue *q) static inline bool xskq_empty_desc(struct xsk_queue *q)
{ {
return xskq_nb_free(q, q->prod_tail, 1) == q->nentries; return xskq_nb_free(q, q->prod_tail, q->nentries) == q->nentries;
} }
void xskq_set_umem(struct xsk_queue *q, struct xdp_umem_props *umem_props); void xskq_set_umem(struct xsk_queue *q, struct xdp_umem_props *umem_props);
......
...@@ -76,7 +76,7 @@ struct btf_type { ...@@ -76,7 +76,7 @@ struct btf_type {
*/ */
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
/* Attributes stored in the BTF_INT_ENCODING */ /* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED (1 << 0) #define BTF_INT_SIGNED (1 << 0)
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
/* Copyright (c) 2018 Facebook */ /* Copyright (c) 2018 Facebook */
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
...@@ -27,13 +26,13 @@ struct btf { ...@@ -27,13 +26,13 @@ struct btf {
struct btf_type **types; struct btf_type **types;
const char *strings; const char *strings;
void *nohdr_data; void *nohdr_data;
uint32_t nr_types; __u32 nr_types;
uint32_t types_size; __u32 types_size;
uint32_t data_size; __u32 data_size;
int fd; int fd;
}; };
static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset) static const char *btf_name_by_offset(const struct btf *btf, __u32 offset)
{ {
if (offset < btf->hdr->str_len) if (offset < btf->hdr->str_len)
return &btf->strings[offset]; return &btf->strings[offset];
...@@ -45,7 +44,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t) ...@@ -45,7 +44,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
{ {
if (btf->types_size - btf->nr_types < 2) { if (btf->types_size - btf->nr_types < 2) {
struct btf_type **new_types; struct btf_type **new_types;
u32 expand_by, new_size; __u32 expand_by, new_size;
if (btf->types_size == BTF_MAX_NR_TYPES) if (btf->types_size == BTF_MAX_NR_TYPES)
return -E2BIG; return -E2BIG;
...@@ -72,7 +71,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t) ...@@ -72,7 +71,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log) static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
{ {
const struct btf_header *hdr = btf->hdr; const struct btf_header *hdr = btf->hdr;
u32 meta_left; __u32 meta_left;
if (btf->data_size < sizeof(struct btf_header)) { if (btf->data_size < sizeof(struct btf_header)) {
elog("BTF header not found\n"); elog("BTF header not found\n");
...@@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) ...@@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
while (next_type < end_type) { while (next_type < end_type) {
struct btf_type *t = next_type; struct btf_type *t = next_type;
uint16_t vlen = BTF_INFO_VLEN(t->info); __u16 vlen = BTF_INFO_VLEN(t->info);
int err; int err;
next_type += sizeof(*t); next_type += sizeof(*t);
...@@ -190,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) ...@@ -190,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
return 0; return 0;
} }
static const struct btf_type *btf_type_by_id(const struct btf *btf, const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
uint32_t type_id)
{ {
if (type_id > btf->nr_types) if (type_id > btf->nr_types)
return NULL; return NULL;
...@@ -209,7 +207,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t) ...@@ -209,7 +207,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t)
return !t || btf_type_is_void(t); return !t || btf_type_is_void(t);
} }
static int64_t btf_type_size(const struct btf_type *t) static __s64 btf_type_size(const struct btf_type *t)
{ {
switch (BTF_INFO_KIND(t->info)) { switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_INT: case BTF_KIND_INT:
...@@ -226,15 +224,15 @@ static int64_t btf_type_size(const struct btf_type *t) ...@@ -226,15 +224,15 @@ static int64_t btf_type_size(const struct btf_type *t)
#define MAX_RESOLVE_DEPTH 32 #define MAX_RESOLVE_DEPTH 32
int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
{ {
const struct btf_array *array; const struct btf_array *array;
const struct btf_type *t; const struct btf_type *t;
uint32_t nelems = 1; __u32 nelems = 1;
int64_t size = -1; __s64 size = -1;
int i; int i;
t = btf_type_by_id(btf, type_id); t = btf__type_by_id(btf, type_id);
for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
i++) { i++) {
size = btf_type_size(t); size = btf_type_size(t);
...@@ -259,7 +257,7 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) ...@@ -259,7 +257,7 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
return -EINVAL; return -EINVAL;
} }
t = btf_type_by_id(btf, type_id); t = btf__type_by_id(btf, type_id);
} }
if (size < 0) if (size < 0)
...@@ -271,9 +269,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) ...@@ -271,9 +269,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
return nelems * size; return nelems * size;
} }
int32_t btf__find_by_name(const struct btf *btf, const char *type_name) __s32 btf__find_by_name(const struct btf *btf, const char *type_name)
{ {
uint32_t i; __u32 i;
if (!strcmp(type_name, "void")) if (!strcmp(type_name, "void"))
return 0; return 0;
...@@ -302,10 +300,9 @@ void btf__free(struct btf *btf) ...@@ -302,10 +300,9 @@ void btf__free(struct btf *btf)
free(btf); free(btf);
} }
struct btf *btf__new(uint8_t *data, uint32_t size, struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
btf_print_fn_t err_log)
{ {
uint32_t log_buf_size = 0; __u32 log_buf_size = 0;
char *log_buf = NULL; char *log_buf = NULL;
struct btf *btf; struct btf *btf;
int err; int err;
......
...@@ -4,19 +4,21 @@ ...@@ -4,19 +4,21 @@
#ifndef __BPF_BTF_H #ifndef __BPF_BTF_H
#define __BPF_BTF_H #define __BPF_BTF_H
#include <stdint.h> #include <linux/types.h>
#define BTF_ELF_SEC ".BTF" #define BTF_ELF_SEC ".BTF"
struct btf; struct btf;
struct btf_type;
typedef int (*btf_print_fn_t)(const char *, ...) typedef int (*btf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2))); __attribute__((format(printf, 1, 2)));
void btf__free(struct btf *btf); void btf__free(struct btf *btf);
struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log); struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
int32_t btf__find_by_name(const struct btf *btf, const char *type_name); __s32 btf__find_by_name(const struct btf *btf, const char *type_name);
int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id); const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
int btf__fd(const struct btf *btf); int btf__fd(const struct btf *btf);
#endif #endif
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -216,8 +217,8 @@ struct bpf_map { ...@@ -216,8 +217,8 @@ struct bpf_map {
size_t offset; size_t offset;
int map_ifindex; int map_ifindex;
struct bpf_map_def def; struct bpf_map_def def;
uint32_t btf_key_type_id; __u32 btf_key_type_id;
uint32_t btf_value_type_id; __u32 btf_value_type_id;
void *priv; void *priv;
bpf_map_clear_priv_t clear_priv; bpf_map_clear_priv_t clear_priv;
}; };
...@@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, ...@@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
{ {
const struct btf_type *container_type;
const struct btf_member *key, *value;
struct bpf_map_def *def = &map->def; struct bpf_map_def *def = &map->def;
const size_t max_name = 256; const size_t max_name = 256;
int64_t key_size, value_size; char container_name[max_name];
int32_t key_id, value_id; __s64 key_size, value_size;
char name[max_name]; __s32 container_id;
/* Find key type by name from BTF */ if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
if (snprintf(name, max_name, "%s_key", map->name) == max_name) { max_name) {
pr_warning("map:%s length of BTF key_type:%s_key is too long\n", pr_warning("map:%s length of '____btf_map_%s' is too long\n",
map->name, map->name); map->name, map->name);
return -EINVAL; return -EINVAL;
} }
key_id = btf__find_by_name(btf, name); container_id = btf__find_by_name(btf, container_name);
if (key_id < 0) { if (container_id < 0) {
pr_debug("map:%s key_type:%s cannot be found in BTF\n", pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
map->name, name); map->name, container_name);
return key_id; return container_id;
} }
key_size = btf__resolve_size(btf, key_id); container_type = btf__type_by_id(btf, container_id);
if (key_size < 0) { if (!container_type) {
pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", pr_warning("map:%s cannot find BTF type for container_id:%u\n",
map->name, name); map->name, container_id);
return key_size; return -EINVAL;
} }
if (def->key_size != key_size) { if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", BTF_INFO_VLEN(container_type->info) < 2) {
map->name, name, (unsigned int)key_size, def->key_size); pr_warning("map:%s container_name:%s is an invalid container struct\n",
map->name, container_name);
return -EINVAL; return -EINVAL;
} }
/* Find value type from BTF */ key = (struct btf_member *)(container_type + 1);
if (snprintf(name, max_name, "%s_value", map->name) == max_name) { value = key + 1;
pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
map->name, map->name); key_size = btf__resolve_size(btf, key->type);
return -EINVAL; if (key_size < 0) {
pr_warning("map:%s invalid BTF key_type_size\n",
map->name);
return key_size;
} }
value_id = btf__find_by_name(btf, name); if (def->key_size != key_size) {
if (value_id < 0) { pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
pr_debug("map:%s value_type:%s cannot be found in BTF\n", map->name, (__u32)key_size, def->key_size);
map->name, name); return -EINVAL;
return value_id;
} }
value_size = btf__resolve_size(btf, value_id); value_size = btf__resolve_size(btf, value->type);
if (value_size < 0) { if (value_size < 0) {
pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", pr_warning("map:%s invalid BTF value_type_size\n", map->name);
map->name, name);
return value_size; return value_size;
} }
if (def->value_size != value_size) { if (def->value_size != value_size) {
pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
map->name, name, (unsigned int)value_size, def->value_size); map->name, (__u32)value_size, def->value_size);
return -EINVAL; return -EINVAL;
} }
map->btf_key_type_id = key_id; map->btf_key_type_id = key->type;
map->btf_value_type_id = value_id; map->btf_value_type_id = value->type;
return 0; return 0;
} }
...@@ -2089,12 +2094,12 @@ const char *bpf_map__name(struct bpf_map *map) ...@@ -2089,12 +2094,12 @@ const char *bpf_map__name(struct bpf_map *map)
return map ? map->name : NULL; return map ? map->name : NULL;
} }
uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map) __u32 bpf_map__btf_key_type_id(const struct bpf_map *map)
{ {
return map ? map->btf_key_type_id : 0; return map ? map->btf_key_type_id : 0;
} }
uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map) __u32 bpf_map__btf_value_type_id(const struct bpf_map *map)
{ {
return map ? map->btf_value_type_id : 0; return map ? map->btf_value_type_id : 0;
} }
...@@ -2268,8 +2273,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size, ...@@ -2268,8 +2273,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size,
volatile struct perf_event_mmap_page *header = mem; volatile struct perf_event_mmap_page *header = mem;
__u64 data_tail = header->data_tail; __u64 data_tail = header->data_tail;
__u64 data_head = header->data_head; __u64 data_head = header->data_head;
int ret = LIBBPF_PERF_EVENT_ERROR;
void *base, *begin, *end; void *base, *begin, *end;
int ret;
asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */ asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */
if (data_head == data_tail) if (data_head == data_tail)
......
...@@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj); ...@@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
int bpf_map__fd(struct bpf_map *map); int bpf_map__fd(struct bpf_map *map);
const struct bpf_map_def *bpf_map__def(struct bpf_map *map); const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
const char *bpf_map__name(struct bpf_map *map); const char *bpf_map__name(struct bpf_map *map);
uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map); __u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map); __u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
int bpf_map__set_priv(struct bpf_map *map, void *priv, int bpf_map__set_priv(struct bpf_map *map, void *priv,
......
...@@ -158,6 +158,15 @@ struct bpf_map_def { ...@@ -158,6 +158,15 @@ struct bpf_map_def {
unsigned int numa_node; unsigned int numa_node;
}; };
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
struct ____btf_map_##name { \
type_key key; \
type_val value; \
}; \
struct ____btf_map_##name \
__attribute__ ((section(".maps." #name), used)) \
____btf_map_##name = { }
static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
(void *) BPF_FUNC_skb_load_bytes; (void *) BPF_FUNC_skb_load_bytes;
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
......
...@@ -247,6 +247,34 @@ static struct btf_raw_test raw_tests[] = { ...@@ -247,6 +247,34 @@ static struct btf_raw_test raw_tests[] = {
.max_entries = 4, .max_entries = 4,
}, },
{
.descr = "struct test #3 Invalid member offset",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
/* int64 */ /* [2] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),
/* struct A { */ /* [3] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
BTF_MEMBER_ENC(NAME_TBD, 1, 64), /* int m; */
BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* int64 n; */
/* } */
BTF_END_RAW,
},
.str_sec = "\0A\0m\0n\0",
.str_sec_size = sizeof("\0A\0m\0n\0"),
.map_type = BPF_MAP_TYPE_ARRAY,
.map_name = "struct_test3_map",
.key_size = sizeof(int),
.value_size = 16,
.key_type_id = 1,
.value_type_id = 3,
.max_entries = 4,
.btf_load_err = true,
.err_str = "Invalid member bits_offset",
},
/* Test member exceeds the size of struct. /* Test member exceeds the size of struct.
* *
* struct A { * struct A {
...@@ -479,7 +507,7 @@ static struct btf_raw_test raw_tests[] = { ...@@ -479,7 +507,7 @@ static struct btf_raw_test raw_tests[] = {
.key_size = sizeof(int), .key_size = sizeof(int),
.value_size = sizeof(void *) * 4, .value_size = sizeof(void *) * 4,
.key_type_id = 1, .key_type_id = 1,
.value_type_id = 4, .value_type_id = 5,
.max_entries = 4, .max_entries = 4,
}, },
...@@ -1264,6 +1292,88 @@ static struct btf_raw_test raw_tests[] = { ...@@ -1264,6 +1292,88 @@ static struct btf_raw_test raw_tests[] = {
.err_str = "type != 0", .err_str = "type != 0",
}, },
{
.descr = "arraymap invalid btf key (a bit field)",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
/* 32 bit int with 32 bit offset */ /* [2] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
BTF_END_RAW,
},
.str_sec = "",
.str_sec_size = sizeof(""),
.map_type = BPF_MAP_TYPE_ARRAY,
.map_name = "array_map_check_btf",
.key_size = sizeof(int),
.value_size = sizeof(int),
.key_type_id = 2,
.value_type_id = 1,
.max_entries = 4,
.map_create_err = true,
},
{
.descr = "arraymap invalid btf key (!= 32 bits)",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
/* 16 bit int with 0 bit offset */ /* [2] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
BTF_END_RAW,
},
.str_sec = "",
.str_sec_size = sizeof(""),
.map_type = BPF_MAP_TYPE_ARRAY,
.map_name = "array_map_check_btf",
.key_size = sizeof(int),
.value_size = sizeof(int),
.key_type_id = 2,
.value_type_id = 1,
.max_entries = 4,
.map_create_err = true,
},
{
.descr = "arraymap invalid btf value (too small)",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
BTF_END_RAW,
},
.str_sec = "",
.str_sec_size = sizeof(""),
.map_type = BPF_MAP_TYPE_ARRAY,
.map_name = "array_map_check_btf",
.key_size = sizeof(int),
/* btf_value_size < map->value_size */
.value_size = sizeof(__u64),
.key_type_id = 1,
.value_type_id = 1,
.max_entries = 4,
.map_create_err = true,
},
{
.descr = "arraymap invalid btf value (too big)",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
BTF_END_RAW,
},
.str_sec = "",
.str_sec_size = sizeof(""),
.map_type = BPF_MAP_TYPE_ARRAY,
.map_name = "array_map_check_btf",
.key_size = sizeof(int),
/* btf_value_size > map->value_size */
.value_size = sizeof(__u16),
.key_type_id = 1,
.value_type_id = 1,
.max_entries = 4,
.map_create_err = true,
},
}; /* struct btf_raw_test raw_tests[] */ }; /* struct btf_raw_test raw_tests[] */
static const char *get_next_str(const char *start, const char *end) static const char *get_next_str(const char *start, const char *end)
...@@ -2023,7 +2133,7 @@ static struct btf_raw_test pprint_test = { ...@@ -2023,7 +2133,7 @@ static struct btf_raw_test pprint_test = {
BTF_ENUM_ENC(NAME_TBD, 2), BTF_ENUM_ENC(NAME_TBD, 2),
BTF_ENUM_ENC(NAME_TBD, 3), BTF_ENUM_ENC(NAME_TBD, 3),
/* struct pprint_mapv */ /* [16] */ /* struct pprint_mapv */ /* [16] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 28), BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */ BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */
BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */ BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */
BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */ BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */
......
...@@ -10,11 +10,6 @@ struct ipv_counts { ...@@ -10,11 +10,6 @@ struct ipv_counts {
unsigned int v6; unsigned int v6;
}; };
typedef int btf_map_key;
typedef struct ipv_counts btf_map_value;
btf_map_key dumm_key;
btf_map_value dummy_value;
struct bpf_map_def SEC("maps") btf_map = { struct bpf_map_def SEC("maps") btf_map = {
.type = BPF_MAP_TYPE_ARRAY, .type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int), .key_size = sizeof(int),
...@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = { ...@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
.max_entries = 4, .max_entries = 4,
}; };
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
struct dummy_tracepoint_args { struct dummy_tracepoint_args {
unsigned long long pad; unsigned long long pad;
struct sock *sock; struct sock *sock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment